我们可以通过Bean后处理器跟容器后处理器来拓展Ioc容器。前者能增强bean的功能,后者能增强容器功能。
Bean后处理器
这是一种特殊的bean,不对外提供服务,也无需id属性,只负责对其它的正常bean执行后处理,比如为容器中的bean生成代理等。它会在正常bean创建后被创建,必须实现BeanPostProcessor接口。里面的两个方法会在目标bean初始化之前之后被调用。
使用ApplicationContext作为容器的话,架构会自动扫描哪个是bean后处理器。它对每个正常bean都有效。虽说它叫做后处理器,但是作用时间却还是bean创建前后。执行顺序是:
- 构造器生成实例
- set方法设定值
- postProcessBeforeInitialization方法
- afterPropertiesSet接口方法
- init-method方法
- postProcessAfterInitialization方法
如果使用BeanFactory容器,则需要额外手动注册bean后处理器。需要现使用容器通过id获取bean后处理器,然后向beanFactory中添加BeanPostProcessor。
Spring架构还提供了两个常用的后处理器。BeannameAutoProxyCreator能够根据bean实例的name属性创建Bean实例的代理。DefaultAdvisorAutoProxyCreator能够根据提供的Advisor对容器中的所有Bean实例创建代理。所谓代理Bean就是对目标bean进行增强,在其功能上进行修改得到新的bean。
容器后处理器
bean后处理器负责处理容器中所有的bean,而容器后处理器则负责处理容器本身。容器后处理器必须实现BeanFactoryPostProcessor接口种的postProcessBeanFactory方法,方法体就是对容器(ApplicationContext或者BeanFactory)的处理,可以扩展容器。ApplicationContext也可以自动检测容器后处理器病自动注册。BeanFactory也是同样需要手动注册。在xml中配置它,就把它当做一个普通bean就好了。Spring架构提供了如下几个常用的容器后处理器:
- PropertyPlaceholderConfigurer:属性占位符配置器
- PropertyOverrideConfigurer:重写占位符配置器
- CustomAutowireConfigurer:自定义自动装配的配置器
- CustomScopeConfigurer:自定义作用于的配置器
属性占位符配置器
可以读取properties属性文件里的顺序性,并将这些属性设置成Spring配置文件的数据。
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderCongifurer"> <property name="locations"> <list> <value>dbconn.properties</value> <value>1.properties</value> <value>2.properties</value> </list> </property> </bean> <!--定义数据源bean--> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close" p:driverClass="${jdbc.driverClassName}" p:jdbcUrl="${jdbc.url}" P:user="${jdbc.username}" p:password="${jdbc.password}"/>
${jdbc.url}这种写法会使架构去上面读取的properties文件中找名为jdbc.url的属性,然后取出属性值。这样我们就无需操作xml文件,仅仅修改properties文件就可对全局的常量进行控制。
重写占位符配置器
PropertyOverrideConfigurer是Spring提供的另一个容器后处理器。它的属性文件指定的信息可以直接覆盖xml中的元数据。它的属性文件中的key应该有如下格式:beanid.property。比如说书中的例子是这样写的:
datasource.user=root
datasource.password=123
如果这样写的话,架构就会自动把root跟123付给id名为datasource的bean的user跟password属性。相比于上面的后处理器,这个更为方便,xml中代码更为简洁。
<bean class="org.springframework.beans.factory.config.PropertyOverrideCongifurer"> <property name="locations"> <list> <value>dbconn.properties</value> </list> </property> </bean> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close" />
属性文件如下:
dataSource.user=root dataSource.password=123
当多个覆盖同时存在时,最后一个有效。如下Schema配置可以更简洁地配置重写占位符配置器。
<context:property-override location="classpath:db.properties"/>