扩展点:
BeanFactoryPostProcessor 构建 BeanFactory后调用,此时BeanFactory , BeanDefinition 已经解析完毕。
BeanPostProcessor 初始化 Bean 对象时调用,所有bean的构建都会调用这个接口的两个方法。两个方法参数传入的bean属性都已经注入完毕。
InitializingBean Bean 实例创建后,所有的属性注入完毕后调用。
定义bean时可以指定init-method 和 destory-method 方法
InstantiationAwareBeanPostProcessor bean包装类初始化时调用方法
DisposableBean Bean 实例销毁时调用
扩展点调用顺序:
1、调用 BeanFactoryPostProcessor 子类的 postProcessBeanFactory() 方法(工厂必须先创建),这里beanFactory 已经创建,beanDefinition已经解析完毕。
2、调用bean 的构造方法。属性没有初始化(使用的都是默认值),依赖没有注入。
3、调用 BeanPostProcessor.postProcessBeforeInitialization() 方法。(所有bean初始化都会调用)
4、调用 InstantiationAwareBeanPostProcessor.postProcessBeforeInitialization() 方法。(所有bean初始化都会调用)
5、调用bean 定义的 init-method 方法(具体到某个bean的初始化)。
6、如果bean 实现了 InitializingBean 接口,调用 InitializingBean.afterPropertiesSet() 方法(具体到某个bean的初始化)。
7、调用 BeanPostProcessor.postProcessAfterInitialization() 方法。(所有bean初始化都会调用)
8、调用 InstantiationAwareBeanPostProcessor.postProcessAfterInitialization() 方法。(所有bean初始化都会调用)
9、bean 销毁,先调用 destory-method 方法,如果bean实现了DisposableBean接口,再调用DisposableBean.destroy() 方法。
1、BeanFactoryPostProcessor
此接口只有一个方法:
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
所以就是使用ConfigurableListableBeanFactory 进行扩展。
扩展方式:
这个扩展的地方就是调用 ConfigurableListableBeanFactory 方法进行扩展。
ConfigurableListableBeanFactory 可以分析和修改、预初始化单例Bean,并且可以修改已有的BeanDifinition属性和类型
调用地方:
所有实现接口BeanFactoryPostProcessor 的bean 都在这里被调用
AbstractApplicationContext.invokeBeanFactoryPostProcessors(beanFactory);
使用场景:
修改bean definition
修改注入类型的注入实例
ConfigurableListableBeanFactory 源码分析:
public interface ConfigurableListableBeanFactory
extends ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory {
/**
* 忽略给定类型依赖的自动注入
*/
void ignoreDependencyType(Class> type);
/**
* 忽略给定接口类型的自动注入
* 这种特定方式通常被用于使用其它方式解决应用上下文依赖注册。如:BeanFactory通过 BeanFactoryAware 注册,ApplicationContext 通过 ApplicationContextAware 来注册。
* 默认情况只有 BeanFactoryAware 接口是被忽略的。调用此方法忽略接口依赖自动注入。
*/
void ignoreDependencyInterface(Class> ifc);
/**
* 指定依赖的类型,使用 autowiredValue 对象注入。
* 预留给 factory/context 类型注入,但是工厂中没有这类bean 定义。
*/
void registerResolvableDependency(Class> dependencyType, @Nullable Object autowiredValue);
/**
* 确定指定bean是否有自动注入的资格,被注入到声明依赖匹配的类的其它bean中
*/
boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor)
throws NoSuchBeanDefinitionException;
/**
* 获取bean 的 BeanDefinition,可以访问属性值和构造方法参数。
* 返回值不是一个副本,是注册在factory中原始的definition object。意味着可以修改为其它更多的特定类型。
*/
BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
/**
* 获取factory 管理所有bean 的beanName的统一视图。
*/
Iterator getBeanNamesIterator();
/**
* 清除merged bean 定义缓存,删除那些没有资格进行完整元数据缓存的bean。
* 当解析的bean definitions被修改了,如调用了 BeanFactoryPostProcessor 方法修改了bean definition。
* 注意:此时的bean的元数据对已经创建的bean,是要保留的。
*/
void clearMetadataCache();
/**
* 冻结所有的 bean definition, 不让在后面处理修改。
*/
void freezeConfiguration();
/**
* 查询 Configuration 是否被冻结
*/
boolean isConfigurationFrozen();
/**
* 确保所有的非惰性单例(non-lazy-init singletons)全部实例化。用于解决循环依赖问题。
* 如果需要,通过在factory 设置完成时调用
*/
void preInstantiateSingletons() throws BeansException;
}
在spring 源码中有使用 ConfigurableListableBeanFactory 类的方法:
测试:
依赖接口及实现/**
* 依赖接口
*/
public interface TestServerInterface {
void m();
}
@Component
public class TestServer2 implements TestServerInterface {
@Autowired
private Other o;
@Override
public void m() {
System.out.println("this is server2");
}
public Other getO() {
return o;
}
public void setO(Other o) {
this.o = o;
}
}
接口实现类依赖的Other 类:
@Component
public class Other {
public void m(){
System.out.println("other m");
}
}
TestServer 依赖 TestServerInterface 子类
@Component
public class TestServer {
private String name="default";
@Autowired
private TestServerInterface t;
public void test(){
t.m();
System.out.println("spring extend test");
}
@PostConstruct
public void before(){
System.out.println("init-method........");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public TestServerInterface getT() {
return t;
}
public void setT(TestServerInterface t) {
this.t = t;
}
}
BeanFactoryPostProcessor 实现类
/**
* 构建 BeanFactory 完成后调用,此时beanFactory 已经创建,beanDefinition已经解析完毕。
*
* 可以修改bean
* 可以获取beandefinition,修改bean 的配置
*
* 参数是ConfigurableListableBeanFactory,体现了不同BeanFactory
*/
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
System.out.println("BeanFactoryPostProcessor------------");
/**
* 修改注入类型
* 如果此bean还依赖其它的bean的话,那么依赖的bean是null,因为 finishBeanFactoryInitialization 组建bean之间的关系是在这个方法中调用的。
*/
TestServerInterface t = (TestServerInterface)configurableListableBeanFactory.getBean("testServer2");
configurableListableBeanFactory.registerResolvableDependency(TestServerInterface.class, t);
//手动注入Other 对象
TestServer2 t2 = (TestServer2)t;
t2.setO(configurableListableBeanFactory.getBean(Other.class));
/**
* 修改bean 属性
*/
//修改beandefinition 的属性注入
BeanDefinition tb = configurableListableBeanFactory.getBeanDefinition("testServer");
MutablePropertyValues propertyValues = tb.getPropertyValues();
propertyValues.addPropertyValue("name","new name");
System.out.println("BeanFactoryPostProcessor############");
}
}
测试代码(省)
测试总结:
测试:
1、获取testServer ,testServer 的name值被修改为 new name
2、接口TestServerInterface 如果有两个实现类,那么启动时就不知道要注入那一个,在postProcessBeanFactory 方法中,定义了此接口使用 name 为 testServer2 的bean 注入,就解决了这个问。
3、在 postProcessBeanFactory()方法中获取bean,如果还依赖其它的bean的话,那么依赖的bean是不会被注入的,这个时候就要手动注入了要么也调用一下 configurableListableBeanFactory.registerResolvableDependency() 方法,因为 finishBeanFactoryInitialization()方法才是组建bean之间的关系的地方。(见代码手动注入Other)
4、如果有多个BeanFactoryPostProcessor类型的bean,可以使用 @Order()注解来指定调用顺序。
2、BeanPostProcessor
初始化 Bean 对象时调用,所有bean的构建都会调用这个接口的两个方法。两个方法参数传入的bean属性都已经注入完毕。BeanPostProcessor 源码分析:
public interface BeanPostProcessor {
/**
* 所有 bean 初始化之前调用,bean属性已经被填充,所有属性及依赖全部注入。
* 返回的bean包装类或者是原始bean。
*/
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
/**
* 所有 bean 初始化之后调用。所有属性及依赖全部注入。
* 传入的bean属性已经被填充。
* 返回的bean包装类或者是原始bean。
* 从spring 2.0开始,FactoryBean 会被调用两次,一次是FactoryBean 本身,一次是getObject() 创建bean。
*
*/
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
这两个方法区别就是被调用的地方不同,一个是调用bean init-method 之前一个是init-method 之后。
AOP 就是对这些扩展点的使用。
注:
BeanFactoryPostProcessor.postProcessBeanFactory()调用栈
AbstractApplicationContext.refresh() 方法通过调用 invokeBeanFactoryPostProcessors(beanFactory);就是调用postProcessBeanFactory() 方法的入口。
AbstractApplicationContext.refresh()方法中调用的finishBeanFactoryInitialization(beanFactory) 方法中调用了preInstantiateSingletons()方法,确保所有的单例都实例化。所以后面的调用顺序就是在bean实例化之后初始化bean的时候调用了。