Bean的定义及作用域的注解实现
·Bean管理的注解实现及例子
·Classpath扫描与组件管理
·从Spring3.0开始,Spring JavaConfig项目提供了很多特性,包括使用java而不是xml定义bean,比如@Configuration,@Bean,@Import,@DependsOn
·Component是一个通用注解,可用于任何bean
·@Repository(通常用于注解DAO类,即永久层),@Service(通常用于注解Service类,即服务层),@Controller(通常用于Controller类,及控制层MVC)是更有针对性的注解
元注解
·许多Spring提供的注解可以作为自己的代码,即“元数据注解”,元注解是一个简单的注解,可以应用到另一个注解
·除了value(),元注解还可以有其它的属性,允许定制。
·类的自动检测与注册Bean
·Spring可以自动检测类并注册Bean得到ApplicationContext中
·为了能够检测这些类并注册相应的Bean,需要下面内容
<beans xmlns=”http://www.springframeword.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/xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd”>
<context:component-scan base-package=”org.example”/>
<beans>
·<context:component-scan包含<context:annotation-cofig/>,通常在使用前者后,不用再使用后者
·AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor也会被包含进来
·<context:annotation-cofig/>
·通过在基于XML的Spring配置如下标签(请注意包含上下文命名空间)
<beans xmlns=”http://www.springframeword.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/xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd”>
<context:annotation-config/>
<beans>
·<context:annotation-config/>仅会查找在同一个applicationContext中的bean注解
使用过滤器进行自定义扫描
·默认情况下,类被自动发现并注册bean的条件是:使用@Component,@Repository,@Service,@Controller注解或者使用@Component的自定义注解
·可以通过过滤器修改上面的行为,如:下面例子的XML配置忽略所有的@Repository注解并用Stub代替
<beans>
<context:component-scan base-package=”org.example”>
<context:include-filter type=”regex”
expression=”.*Stub.*Repository”/>
<context:exclude-filter type=”annotation”
expression=”org.springframework.stereotype.Repository/>
</context component-scan>
</beans>
`还可以使用use-default-filter=”false” 禁止自动发现与注册
·@Component,@Repository,@Service,@Controller
定义Bean
·扫描过程中组件被自动检测,那么Bean名称是由BeanNameGenertor生成的(以类名为基础,第一个字符小写)(@Component,@Repository,@Service,@Controller都会有个name属性用于显式设置Bean Name)
·可自定义bean命名策略,实现BeanNameGenertor接口,并一定要包含一个无参数构造器
<beans>
<context:component-scan base-package=”org.example”
name-genertor=”org.example.MyNameGenertor”/>
</beans>
作用域(Scope)
·通常情况下自动查找的Spring 组件,其scope是singleton(在一个IOC容器中是单例的),Spring2.5提供了一个表示scope的注解@Scope
·也可以自定义scope策略,实现ScopeMetadataResolver接口并提供一个无参构造器
<beans>
<context:component-scan base-package=”org.example”
scope-resovler=”org.example.MyScopeResolver”/>
</beans>
代理方式
·可以使用scoped-proxy属性指定代理,有三个值可选:no,interface,targetClass
<beans>
<context:component-scan base-package=”org.example”
Scoped-proxy=”interface”/>
</beans>
代码示例:
<?xml version="1.0" encoding="UTF-8"?>
<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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.hushi.springdemo"></context:component-scan>
</beans>
//@Component("bean")
@Scope("prototype")
@Component()
public class BeanAnnotation {
// public void say(String s){
// System.out.println("BeanAnnotation:"+s);
// }
public void showHashCode(){
System.out.println(this.hashCode());
}
}
public class AnnotationTest extends JUnitTestBase {
public AnnotationTest() {
super("applicationContext.xml");
// TODO Auto-generated constructor stub
}
// @Test
// public void testSay() {
// BeanAnnotation ba = (BeanAnnotation) super.getBean("bean");
// ba.say("This is a annotation test");
// }
@Test
public void testShow(){
BeanAnnotation ba = (BeanAnnotation) super.getBean("beanAnnotation");
ba.showHashCode();
ba = (BeanAnnotation) super.getBean("beanAnnotation");
ba.showHashCode();
}
}
public class JUnitTestBase {
private ClassPathXmlApplicationContext context;
private String xml;
public JUnitTestBase(String xml) {
this.xml = xml;
}
public Object getBean(String beanName) {
return context.getBean(beanName);
}
@After
public void after(){
context.destroy();
}
@Before
public void before(){
context = new ClassPathXmlApplicationContext(xml);
context.start();
}
}
@Required(不常用)
·该注解适用于bean属性的setter方法
·这个注解仅仅表示,受影响的bean属性必须在配置时被填充,通过在bean定义或通过自动装配一个明确的属性值
@Autowired(常用)
·注解为“传统的”setter方法
·可用于构造器或成员变量
·默认情况下,如果找不到合适的bean将会导致autowiring失败抛出异常,可以通过下面的方式避免:@Autowired(required=false)
·每个类只能有一个构造器被标记为required=true
public class ServiceInterfaceImpl implements ServiceInterface {
@Autowired
private DaoInterface dao;
@Autowired
public void setDao(DaoInterface dao){
this.dao = dao;
}
@Autowired
public ServiceInterfaceImpl(DaoInterface dao){
this.dao = dao;
}
public void save(String s) {
// TODO Auto-generated method stub
System.out.println("Service接收到参数:"+s);
dao.save(s);
}
public class DaoInterfaceImpl implements DaoInterface {
public void save(String s) {
// TODO Auto-generated method stub
System.out.println("Dao接收到Service传来的参数:"+s);
}
}
public class AnnotationTest extends JUnitTestBase {
public AnnotationTest() {
super("applicationContext.xml");
// TODO Auto-generated constructor stub
}
@Test
public void test(){
ServiceInterfaceImpl service = (ServiceInterfaceImpl) super.getBean("serviceInterfaceImpl");
service.save("test---------");
}
·@Autowired的必要属性,建议使用@required注解
·可以使用其来注解那些总所周知的解析依赖性接口,比如:BeanFactory,ApplicationContext,Environment,ResourceLoader,ApplicationEventPublisher,and MessageSource
·可以通过添加注解给需要该类型的数组的字段或方法,以提供ApplicationContext中的所有特定类型的bean
private Set<MovieCatalog> movieCatalog;
@Autowired
public void setMovieCatalogs(Set<MovieCatalog> movieCatalogs){
This.movieCatalogs = movieCatalogs;
}
applicationContext中的所有MovieCatalog bean或其子类bean都会被装配到该方法中
代码示例:
@Component
public interface BeanInterface {
}
@Component
public class BeanOne implements BeanInterface {
}
@Component
public class BeanTwo implements BeanInterface {
}
@Component
public class BeanInvoker {
@Autowired
private List<BeanInterface> beanList;
@Autowired
private Map<String,BeanInterface> map;
@Autowired
public void setBeanList(List<BeanInterface> beanList){
this.beanList = beanList;
}
@Autowired
public void setMap(Map<String,BeanInterface> map){
this.map = map;
}
public void showName(){
if(this.beanList != null && beanList.size() != 0){
for(BeanInterface list : beanList){
System.out.println(list.getClass().getName());
}
}
if(this.map != null && map.size() != 0){
for(Entry<String, BeanInterface> entry : map.entrySet()){
System.out.println(entry.getKey()+" "+entry.getValue().getClass().getName());
}
}
}
}
public class AnnotationTest extends JUnitTestBase {
public AnnotationTest() {
super("applicationContext.xml");
// TODO Auto-generated constructor stub
}
@Test
public void test(){
BeanInvoker b = (BeanInvoker) super.getBean("beanInvoker");
b.showName();
}
·可以用于自动装配key为String的Map
Key为bean的id,value为对象
·如果希望数组有序,可以让bean实现org.springframework.core.Ordered接口或使用的@Order注解bean,值为整型,对map无效
·Autowired是有Spring BeanPostProcessor处理的,所以不能在自己的BeanPostProcessor类型应用这些注解,这些类型必须通过XML或者Spring的@Bean注解加载
@Qualifier
·按类型自动装配可能多个bean实例的情况,可以使用Spring的@Qulifier注解缩小范围(或指定唯一),也可以用于指定单独的构造器参数或方法参数
·可用于注解集合类型变量