一、两种后处理器(Bean后处理器和容器后处理器)
Spring框架提供了很好的扩展性,除了可以与各种第三方框架良好整合外,其IoC容器也允许开发者进行扩展,这种扩展甚至无须实现BeanFactory或ApplicationContext接口,而是允许通过两个处理器对IoC容器进行扩展。
1、Bean后处理器是一种特殊Bean,这种特殊Bean并不对外提供服务,它甚至可以无须id属性,它主要负责对容器中的其他Bean执行后处理,例如为容器中的Bean生成代理等,这种Bean被称为后处理器。
Bean后处理器必须实现BeanPostProcessor接口,它会在Bean实例创建成功后对Bean进行进一步增强处理,该接口包含如下两个方法:
Object postProcessBeforeInitialization(Object bean,String name) throw BeansException目标Bean初始化之前被回调
Object postProcessAfterInitialization(Object bean,String name) throw BeansException目标Bean初始化之后被回调
关联之前基本用法中提到的init-method和实现InitializingBean后提供的afterPropertiesSet()方法,它们的调用顺序如下图
如果采用BeanFactory作为Spring容器时必须手动注册BeanPostProcessor,如果用ApplicationContext作为容器则无需手动注册,它会自动检测到Bean后处理器,自动注册。
如果需要对容器中谋一批Bean进行通用的增强处理,则可考虑使用Bean后处理器
2、容器后处理器负责处理容器本身,它必须实现BeanFactoryPostProcessor接口,该接口必须实现如下一个方法:
void postProcessorBeanFactory(ConfigurableListableBeanFactory beanFactory)由于此方法只是对Spring容器进行后处理,它并不需要完全替换Spring容器,因此该方法无需任何返回值。
实现postProcessorBeanFactory接口的容器后处理器不仅可对BeanFactory执行后处理,也可以对ApplicationContext容器执行后处理。容器后处理器还可用来注册额外的属性编辑器。
Spring已提供如下几个常用的容器后处理器。
①PropertyPlaceHolderConfigurer:属性占位符配置器。
负责读取属性文件里的属性值,并将这些属性值设置成Spring配置文件的元数据,通过使用此后处理器可以将Spring配置文件中的部分元数据放在属性文件中设置,这种配置方式当然有其优势:可以将部分相似的配置(比如说数据库的URL、用户名和密码)放在特定的属性文件失踪,如果只需要修改这部分配置,则无需修改Spring配置文件,修改属性文件即可,从而降低修改配置文件产生错误的风险。(注意抽离得太多个属性文件,可能会降低Spring配置文件的可读性)
例:<bean class="org.springframework,beans.factory.config.PropertyPlaceHolderConfigurer">
<property name="locations">
<list>
<value>dbconn.properties</value>
<!--如果有多个属性文件,依次在下面列出来-->
<!--value>wawa.properties</value-->
</list>
</property>
</bean>
②PropertyOverrideConfigurer:重写占位符配置器。
PropertyOverrideConfigurer的属性文件指定的信息可以直接覆盖Spring配置文件中的元数据。即:PropertyOverrideConfigurer允许XML配置文件中又默认的配置信息。
<bean class="org.springframework,beans.factory.config.PropertyOverrideConfigurer">
<property name="locations">
<list>
<value>dbconn.properties</value>
<!--如果有多个属性文件,依次在下面列出来-->
<!--value>wawa.properties</value-->
</list>
</property>
</bean>④CustomScopeConfigurer:自定义作用域的配置器。
容器后处理器通常用于对Spring容器进行处理,并且总是在容器实例化任何其他Bean之前,读取配置文件的元数据,并有可能修改这些元数据。如果有需要,程序可以配置多个容器后处理器,多个容器后处理器可设置order属性来控制容器后处理器的执行顺序。(为了给容器后处理器指定order属性,则要求容器后处理器必须实现Ordered接口,因此在实现BeanFactoryPostProcessor时,就应当考虑实现Ordered接口)
二、Spring的“零配置”支持Annotation
1、搜索Bean类的Annotation
①@Component:标注一个普通的Spring Bean类
②@Controller:标注一个控制器组件类
③@Service:标注一个业务逻辑组件类
④@Repository:标注一个DAO组件类
如果只需定义一个普通的Spring Bean,则直接使用@Component标注即可。但如果用@Controller、@Service或@Repository来标注这些Bean类,这些Bean类将作为特殊的JavaEE组件对待,也许能更好地被工具处理,或与切面进行关联。在未来Spring版本中,后三种也许还能携带更多语义,因此尽量考虑使用后三种代替@Component
Spring并没有采用Rail框架的“约定优于配置“的方式(Rail要求将不同组件放在不同路径下,然后加载固定路径下的所有组件),指定了某些类可作为SpringBean类使用后,还需要让Spring搜索指定路径,此时需要在Spring配置文件中导入context Schema,并指定一个简单的搜索路径。
在基于XML配置方式下,每个Bean实例的名称都由其id属性指定;在这种基于Annotation的方式下,Spring采用约定的方式来为这些Bean实例指定名称,这些Bean实例的名称默认是Bean类的首字母小写,其他部分不变。当然,Spring也允许在使用@Component标注时指定Bean实例的名称,如@Component("axe"),除此之外,我们还可通过为<component-scan.../>元素添加<include-filter.../>或<exclude-filter../>子元素来指定SpringBean类,<include-filter.../>只要位于指定路径下的Java类满足这种规则,即使这些类没有使用任何Annotation标注,Spring一样会将它们当成Bean类来处理。<exclude-filter../>指定满足该规则的Java类不会被当成Bean类处理
2、指定Bean作用域的Annotation:@Scope("prototype") 类似xml配置中scope
3、依赖配置的Annotation:@Resource(name='beanName') 类似xml配置中的<property ref...>,即可修饰Field,又可修饰setter方法,name属性可以省略,如果修饰的是setter方法,则name属性默认是setter方法去掉前面set子串、首字母小写后得到的子串,如果修饰的是Field,则name属性默认是Field值
4、定制生命周期的Annotation,@PostConstruct对应XML配置中init-method,@PreDestroy对应XML配置中的destroy-method
5、Spring3.0新增的Annotation @DependsOn对应XML配置中的depends-on强制初始化Bean,@Lazy对应XML配置中的lazy取消预初始化
6、自动装配、精确装配的Annotation @Autowired 对应XML配置中的<autowire>可修饰Field或方法,采用byType的自动装配策略,@Qualifier通常用于修饰Field,精确装配
例@Autowired
@Qualifier(”steelAxe“)
private Axe axe;