一.spring-core IoC container(2) 基于annotation的配置方式

   上节阐述了spring bean 基于xml的配置及其他的bean概述,本届阐述spring基于annotation的方式配置Bean。在这里要说明的是,基于annotation的配置会优先于xml配置方式,所以,对于同一个bean,后续的xml配置会覆盖前面的annotation的配置。

一般可以通过下面的xml进行注册

<?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:annotation-config/>

</beans>
<context:annotation-config/>配置会隐式向spring容器注入AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、 PersistenceAnnotationBeanPostProcessor、RequiredAnnotationBeanPostProcessor 这四个BeanPostProcessor,这四个BeanPostProcessor的作用让系统能够识别相应的注解

常用注解说明

@Required
常用于Bean中属性的setter上

public class SimpleMovieLister {
    private MovieFinder movieFinder;
    @Required
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }
    // ...
}

这个注解表示被注解的属性需要配置的期间被填充,可以通过在bean中明确的赋值,或者自动装配。如果没有,容器则会抛出异常。

@Autowired

@Autowired可以对成员变量、方法和构造函数进行标注,来完成自动装配的工作。
注意:@Autowired是根据类型(byType)进行自动装配的,如果需要按名称进行装配,则需要配合@Qualifier使用;
@Autowired 可以使用构造方法上,也可以在传统的setter方法上
在构造上使用:
public class MovieRecommender {
    private final CustomerPreferenceDao customerPreferenceDao;
    @Autowired
    public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
        this.customerPreferenceDao = customerPreferenceDao;
    }
    // ...
}
在4.3以后,目标Bean中只有一个构造方法,那么可以省略这个注解,如果有多个构造方法,则至少要有一个构造方法要使用@Autowired 注解

在setter上使用:
public class SimpleMovieLister {
    private MovieFinder movieFinder;
    @Autowired
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }
    // ...
}
还可以将注释应用于具有任意名称和/或多个参数的方法:
public class MovieRecommender {
    private MovieCatalog movieCatalog;
    private CustomerPreferenceDao customerPreferenceDao;
    @Autowired
    public void prepare(MovieCatalog movieCatalog,
            CustomerPreferenceDao customerPreferenceDao) {
        this.movieCatalog = movieCatalog;
        this.customerPreferenceDao = customerPreferenceDao;
    }
    // ...
}
可以用@autowired在属性上注解
public class MovieRecommender {
    private final CustomerPreferenceDao customerPreferenceDao;
    @Autowired
    private MovieCatalog movieCatalog;
    @Autowired
    public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
        this.customerPreferenceDao = customerPreferenceDao;
    }
   // ...
}

由于@Autowired 是基于类(byType)实现自动装配的,如果在容器中有多个类,可能会导致程序出错。这使得我们需要自动装备进行更加进一步的限制:
@Primary
这个注解表示如果自动装备的Bean存在有多个候选者,那么这个候选者将会成为自动装配的Bean

javacode-conf:
@Configuration
public class MovieConfiguration {
    @Bean
    @Primary
    public MovieCatalog firstMovieCatalog() { ... }
    @Bean
    public MovieCatalog secondMovieCatalog() { ... }
    // ...
}
xml-conf:
   ......
    <context:annotation-config/>
    <bean class="example.SimpleMovieCatalog" primary="true">
        <!-- inject any dependencies required by this bean -->
    </bean>

    <bean class="example.SimpleMovieCatalog">
        <!-- inject any dependencies required by this bean -->
    </bean>

    <bean id="movieRecommender" class="example.MovieRecommender"/>
    ......

@Qualifier(“main”)
@Autowired配合@Qualifier("main") 可以实现根据名字进行自动装备,上述代码会装备上具有<qualifier value="main"/> 的Bean。

    <bean class="example.SimpleMovieCatalog">
        <qualifier value="main"/>
        <!-- inject any dependencies required by this bean -->
    </bean>

@Qualifier() 也可以作为构造或者方法的参数进行使用

@Autowired
    public void prepare(@Qualifier("main")MovieCatalog movieCatalog,
            CustomerPreferenceDao customerPreferenceDao) {
        this.movieCatalog = movieCatalog;
        this.customerPreferenceDao = customerPreferenceDao;
    }

这只是@Qualifier() 的最基本用法,更详细的构造@Qualifier() 接口等可以看官方文档说明。

@Resource
使用@Resource 可以实现Bean自动装配时,通过byName 注入。

public class SimpleMovieLister {
    private MovieFinder movieFinder;
    @Resource(name="myMovieFinder")
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }

}

如果在@Resource 中没带任何参数,则会使用默认的name,这个name与你定义的类对象名称保持一致

public class SimpleMovieLister {
    //在此使用@Resource 则会自动装配name="first" 的bean
    private MovieFinder first;
    //在此使用@Resource 则会自动装配name="second" 的bean
    @Resource
    public void setMovieFinder(MovieFinder second) {
        this.movieFinder = movieFinder;
    }
}

需要说明的是,当没有多个同类型的Bean时,@autowired和@Resource 都是可以直接实现自动装配效果的
@PostConstruct and @PreDestroy

public class CachingMovieLister {
    //bean初始化之前
    @PostConstruct
    public void populateMovieCache() {
        // populates the movie cache upon initialization...
    }
    //bean销毁之前
    @PreDestroy
    public void clearMovieCache() {
        // clears the movie cache upon destruction...
    }
}

使用类路径扫描和管理组件

在上述的注解使用过程中,Bean的初始化配置仍然在XML中,通过上述的注解只是通过解决类中的依赖关系的配置问题。这一部分通过扫描类路径检测出对应组件的方法,而这些组件又由类构成,这就使得我们可以不通过XML初始化Bean。先介绍几个注解

@Component (把普通pojo实例化到spring容器中,相当于配置文件中的<bean id="" class=""/>)
@Repository 用于标注数据访问组件,即DAO组件
@Controller用于标注控制层组件(如struts中的action) 
@Service用于标注业务层组件 

其实下面的三个注解只是第一个注解的细化而已,通过细化可以实现spring自动的异常转换,并且在配合面向切面变成的工具使用更加方便

检测类和bean注册自动化

spring实现组件的自动检测和注册需要做如下的配置
基于XML的配置:

<?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">
        //告诉spring需要扫描的包有哪些
    <context:component-scan base-package="org.example"/>
</beans>

基于javacode的配置:

@Configuration
@ComponentScan(basePackages = "org.example")
public class AppConfig  {
    ...
}

spring扫描的范围是通过类似过滤的方式可以自动配置的
这里写图片描述

@Configuration
@ComponentScan(basePackages = "org.example",
        includeFilters = @Filter(type = FilterType.REGEX, pattern = ".*Stub.*Repository"),
        excludeFilters = @Filter(Repository.class))
public class AppConfig {
    ...
}
或者
<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>
这段配置表示忽略@Repository注解而使用.*Stub.*Repository 取代
使用components定义容器中的元数据

spring@Component 也可以像@Configuration 一样通过 @Bean 注解像容器中注入元数据

@Component
public class FactoryMethodComponent {
    @Bean
    @Qualifier("public")
    public TestBean publicInstance() {
        return new TestBean("publicInstance");
    }
    public void doWork() {
        // Component method implementation omitted
    }
}

基于annotation的配置方式的学习暂且到此为止,里面还有很多细节之处没有详细叙述,用到的时候仍需要参考文档

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值