- @Autowired
@Autowired市按照类型匹配进行依赖注入的,它可以标注于类定义的多个位置:
- 域或属性
- 构造方法定义
- 方法定义 @Autowired不仅可以标注在传统的setter方法之上,而且还可以标注于任意名称的方法定义,只要该方法定义了需要被注入的参数就行。
为了给容器中定义的每个bean定义对应的实例注入依赖,需要遍历所有bean,然后通过反射,检查每个bean定义对应的类上各种可能位置上的@Autowired,如果存在,就可以从当前容器管理的对象中获取符合条件的对象,设置给@Autowired所标注的属性域/构造方法或方法定义。AutowiredAnnotationBeanPostProcessor是Spring提供的用于这个目的的BeanPostProcessor实现,所以只要在IoC容器的配置文件中追加
<bean class="org.springframework.beans.factory.annotation. AutowiredAnnotationBeanPostProcessor"/>
就可以让整个应用开始运作了。
- @Qualifier
@Qualifier是byName自动绑定的注解版,IoC容器无法从多个同一类型的实例中选取我们真正想要的,那就用@Qualifier直接点名。
- @Resource
IoC容器根据@Resource所制定的名称,到容器中查找beanName与之对应的实例,然后将查找到的对象实例注入给@Resource所标注的对象。例如
public class FXNewsProvider { @Resource(name="djNesListener") private IFXNewsListener newsListener; @Resource(name="djNesPersister") private IFXNewsPersister newsPersister; }
@Resource和@Autowired标注的地方大致相同,都可以标注在属性域或方法上,也可以在构造方法或普通方法上标注。
- @PostConstruct 和 @PreDestory
这两个注解并不是服务于依赖注入的,主要用于标注对象生命周期管理相关方法,与Spring的InitializingBean和DisposableBean接口,以及配置中的init-method和destroy-method起到类似作用。
只使用@Resource, @PostConstruct和@PreConstruct,并不能立马起作用。就像@Autowired需要AutowiredAnnotationBeanPostProcessor一样,这些注解也需要一个BeanPostProceesor,即CommonAnnotationBeanPostProcessor,这样这些注解才能发挥作用。
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/>
既然不管是@Autowired还是@Resource都需要添加相应的BeanPostProcessor到容器,那我们可以在基于XSD的配置文件中使用一个<context:annotation-config> 配置搞定义上所有的BeanPostProcessor。
<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" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> <context:annotation-config/> <bean id="newsProvider" class="..FXNewsProvider"/> <!--其他bean定义--> ... </beans>
Spring提供的@Autowired加上@Qualifier和JSR250提供的@Resource等注解属于不同派系,如果要实现依赖注入的话,使用一个派别的注解就可以了。
- classpath-scanning
不仅依赖关系可以用注解,不用xml配置,Bean的定义也可以不用配置。这就需要classpath-scanning功能了。
使用相应的注解对组成应用程序的相关类进行标注后,classpath-scanning功能可以从某一顶层包(base package)开始扫描。当扫描到某个类标注了相应注解后,就会提取该类的相关信息,构建对应的BeanDefinition,然后把构建完的BeanDefinition注册到容器。
<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-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> <context:component-scan base-package="org.spring21"/> </beans>
如果要扫描的类定义在不同的包下面,也可以为base-package指定多个以逗号分隔的扫描路径。
<context:component-scan>默认扫描的注解类型是@Component,不过在@Component语义基础上细化后的@Repository,@Servicce和@Controller也同样可以被扫描到。
<context:component-scan>在扫描相关类定义并将它们添加到容器的时候,会使用一种默认的命名规则,来生成那些添加到容器的bean定义的名称(beanName)。这种命名规则就是类名称首字母小写后就是该类bean的beanName。如下例,如果使用默认名称就是如果想自定义一个名称,可以这样写:
@Component("djNewsListener") public class DowJonesNewsListener implements IFXNewsListener
<context:component-scan>不仅把注册bean的功能完成了,甚至把<context:annotation-config>的任务也完成了,所以只用<context:component-scan>就可以扫描到bean, 并把它们的依赖关系也注册到了容器中。除此之外,<context:component-scan>的嵌套配置项可以对默认的扫描结果进行过滤以排除某些类。
<context:component-scan base-package="org.spring21"> <context:include-filter type="annotation" expression="cn.spring21.annotation.FXService"/> <context:exclude-filter type="aspectj" expression=".."/> </context:component-scan>