您的位置:首页 > 编程语言 > Java开发

Spring v3.0.2 Learning Note 9 - Classpath Scanning

2010-10-25 11:11 113 查看
在classpath自动扫描将组件纳入容器管理

前面的例子都是使用xml的bean定义来配置组件,即便使用了@Resource或者@Autowired的方式减少了一部分bean的定义,但是在一个稍大的项目中,通常还是会有几十甚至数百个组件,查找或维护都不太方便。

自从Spring
v2.5以后,引入了组件自动扫描的机制,它可以在类路径下寻找标注了@Component、@Service、@Controller、
@Repository注解的类,并将这些类纳入spring容器进行管理。它的作用和在xml文件中使用bean节点配置组件是完全一样的。

要使用自动扫描,需要用以下配置:

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:context="http://www.springframework.org/schema/context"

xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd ">

<context:component-scan base-package="com.spring.test"/>

</beans>

其中base-package
为需要扫描的包及其子包。

context:component-scan已经包含了
<context:annotation-config>,所以不需要再添加<context:annotation-config>也可使用@Resource等注解。

@Service 用于标注业务层组件
@Controller 用于标注控制层组件(如struts中的action)
@Repository 用于标注数据访问组件,即DAO组件
@Component 泛指组件,当组件不好归类,可使用这个注解。

以目前的spring的版本,上面的组件的处理器的处理都是一样的,没有区别。

修改以前用到的例子,来使用classpath扫描的方式工作。

package com.spring.test.dao;

import org.springframework.stereotype.Repository;

@Repository
public class PersonDao {

public void add() {

System.out.println("This is add() method in DAO layer.");

}

}

------------------------------------------------------------------------------------------

package com.spring.test.manager.impl;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.spring.test.dao.PersonDao;

import com.spring.test.manager.IPersonService;

@Service
public class PersonManager implements IPersonService {

@Resource

private PersonDao personDao;

public void setPersonDao(PersonDao personDao) {

this.personDao = personDao;

}

@Override

public void save() {

personDao.add();

}

}

-----------------------------------------------------------------------------------------

测试类1:

package com.spring.test.junit;

import org.junit.AfterClass;

import org.junit.BeforeClass;

import org.junit.Test;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.spring.test.manager.IPersonService;

public class PersonServiceTest {

@BeforeClass

public static void setUpBeforeClass() throws Exception {

}

@AfterClass

public static void tearDownAfterClass() throws Exception {

}

@Test

public void test() {

ApplicationContext ctx = new ClassPathXmlApplicationContext(

"spring.xml");

// 注意classpath扫描的方式下,如何取bean的id

IPersonService personService = (IPersonService) ctx

.getBean("personManager");

personService.save();

}

}

classpath自动扫描的方式,如何知道bean的id

若@Service中没有给定bean的id/name,默认状况下是类名,但是第一个字母变为小写,如上例中的
(IPersonService)
ctx.getBean("personManager");会取到类
com.spring.test.manager.impl.PersonManager。如果有多个同名的PersonManager,但是处在不同的
package下,如何办呢?则可在@Service中指定bean的name

@Service("service
name"),如果采用了指定名称的方式,则按照名称来匹配组件。比如:@Service("personService"),如果运行测试类1会出错,
因为名称不匹配了,需要改为 (IPersonService) ctx.getBean("personService");才可以工作。

classpath自动扫描的方式,如何指定作用域

如果不指定,默认状态为singleton,如果需要修改,采用以下方法:

@Scope("prototype")

@Service("personManager")

public class PersonManager implements IPersonService {

// 省略

}

指定初始化方法和销毁方法

@PostConstruct
 等同于bean定义的init-method="初始化方法名"

@PreDestroy
等同于bean定义的destroy-method="销毁方法名"

package com.spring.test.manager.impl;

import javax.annotation.PostConstruct;

import javax.annotation.PreDestroy;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.spring.test.dao.PersonDao;

import com.spring.test.manager.IPersonService;

@Service("personManager")

public class PersonManager implements IPersonService {

@Resource

private PersonDao personDao;

public void setPersonDao(PersonDao personDao) {

this.personDao = personDao;

}

@PostConstruct

public void init() {

System.out.println("This is init() method.");

}

@PreDestroy

public void destroy() {

System.out.println("This is destroy() method.");

}

@Override

public void save() {

personDao.add();

}

}

---------------------------------------------------------------------------

package com.spring.test.junit;

import org.junit.AfterClass;

import org.junit.BeforeClass;

import org.junit.Test;

import org.springframework.context.support.AbstractApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class PersonServiceTest {

@BeforeClass

public static void setUpBeforeClass() throws Exception {

}

@AfterClass

public static void tearDownAfterClass() throws Exception {

}

@Test

public void test() {

AbstractApplicationContext ctx = new ClassPathXmlApplicationContext(

"spring.xml");

ctx.close();

}

}

运行此测试类,发现控制台输出了初始化方法和销毁方法中的内容。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: