一般而言,开发者不需要继承ApplicationContext实现类,可以通过实现特定的集成接口来扩展Spring IoC容器的功能。
1. 使用BeanPostProcessor来自定义Bean
BeanPostProcessor接口定义了一些回调方法,可以实现它们来自定义实例化、依赖解析等逻辑。若想在Spring容器完成实例化、配置和初始化一个Bean之后实现一些自定义逻辑,那么可以定义一个或多个BeanPostProcessor实现。
可以为应用配置多个BeanPostProcessor实例,也可以通过设置order属性来控制这些BeanPostProcessor执行的顺序。仅当BeanPostProcessor实现了Ordered接口时,才可以设置这个属性。
BeanPostProcessor的作用域是单个容器,若在一个容器中定义了一个BeanPostProcessor,它将仅在那个容器中操作Bean。
org.springframework.beans.factory.config.BeanPostProcessor接口包含两个回调方法。当这种类被容器注册为post-processor时,对于容器创建的每个Bean实例,在容器初始化回调(比如InitializingBean的afterPropertiesSet)之前post-processor会做一次postProcessBeforeInitialization回调,在任何Bean初始化回调之后post-processor会做一次 postProcessAfterInitialization回调。post-processor可以对一个Bean实例做任何操作。post-processor一般就是检查回调接口,或者为Bean封装一个代理。一些Spring AOP框架类就是post-processor,只为提供代理的封装逻辑。
ApplicationContext会自动检测那些实现了BeanPostProcessor接口的Bean。当使用@Bean工厂方法来定义一个BeanPostProcessor时,工厂方法的返回类型应该是类本身,至少是BeanPostProcessor接口,清晰地表明Bean的post-processor属性。否则,ApplicationContext在创建Bean之前不会检测到它。然而,为了将这些特性应用到其它Bean上,BeanPostProcessor需要早些被实例化。
推荐通过ApplicationContext的自动检测机制来注册BeanPostProcessor,也可以通过ConfigurableBeanFactory的addBeanPostProcessor方法来手动注册。手动注册在需要控制注册前的条件逻辑情景下会很有用,但是Ordered接口对它不再起作用。手动注册总会先于自动检测式的注册。
容器会特殊对待实现了BeanPostProcessor接口的类,它们直接引用的类会在启动时被初始化,作为容器启动的一部分。接下来,所有的BeanPostProcessor排好序被注册,会被应用到容器的所有Bean。因为AOP自动代理本身就是一个BeanPostProcessor,那么它们直接引用的BeanPostProcessor或Bean都是自动代理不可见的(因为这样的BeanPostProcessor或Bean 都在自动代理被实例化之前都已经初始化了),因此不可能自动代理这样的BeanPostProcessor或者Bean。
2. 使用BeanFactoryPostProcessor来自定义配置元数据
这个扩展点是org.springframework.beans.factory.config.BeanFactoryPostProcessor,从语义上和BeanPostProcessor很相似,但有个不同点:BeanFactorPostProcessor操作Bean的配置元数据。Spring IoC容器允许BeanFactoryPostProcessor读取配置元数据,并在容器实例化任何Bean(不包括BeanFactoryPostProcessor本身)之前修改配置元数据。可以配置多个BeanFactoryPostProcessor,并通过order属性来控制它们执行的顺序。
Spring包含一些预定义的BeanFactoryPostProcessor,比如PropertyOverideConfigurer和PropertyPlaceholderConfigurer。
ApplicationContext会自动检测实现了BeanFactoryPostProcessor接口的Bean,并将这些Bean当作post-processor。
3. 使用FactoryBean自定义初始化逻辑
FactoryBean接口是Spring IoC容器实例化逻辑的一个插件化的扩展点。若在系统有着复杂的初始化代码,且更适合使用Java代码(而不是XML),那么就可以创建自定义的FactoryBean,将初始化逻辑写到里面,然后将自定义的FactoryBean插入容器中。
FactoryBean接口提供了三个方法:
(1)Object getObject():返回当前工厂创建的对象实例。
(2)Boolean isSingleton():判断是否是单例。
(3)Class getObjectType():返回对象类型。