BeanPostProcessor由浅入深:
1、BeanPostProcessor原理:
该接口我们也叫后置处理器,作用是在Bean对象在实例化和依赖注入完毕后,在显示调用初始化方法的前后添加我们自己的逻辑。注意是Bean实例化完毕后及依赖注入完成后触发的。流程图如下(如何使用这里就不附上代码,相信大家已经了解)
首先-初始化bean—>检查容器中是否存在BeanPostProcessor,
如果存在就调用postProcessBeforeInitialization方法
.
—>如果返回null(或者所有的BeanPostProcessor执行完毕)
.
—->执行bean的初始化方法
.
—->再次判断容器中是否存在BeanPostProcessor
.
—>如果存在就调用postProcessAfterInitialization方法
.
—>如果返回null(或者所有的BeanPostProcessor执行完毕)
.
—>运行结束
如果一开始容器中就没有 BeanPostProcessor,那么就会直接支持bean的初始化方法,结束;(结合流程与源码一起会更加清晰,下附源码)
2、容器启动到Bean创建–底层源码流程:
test方法—-…—->refresh()
—->finishBeanFactoryInitialization()
.
—->preInstantiateSingletons()
.
—->preInstantiateSingletons()
.
—->getBean()
.
—->doGetBean()
.
—-> getSingleton(beanName, new ObjectFactory()
这是一个简单的流程,可以大致看一下在容器启动的时候具体调用了哪些方法;我们先进入doGetBean方法里面:发现其实是调用了getSingleton方法获取实例,
如果没有获取到又通过getObject()里面的 createBean(beanName, mbd, args)创建实例,总之这个实例一定要创建出来
因为长度问题这里只取这篇文章对最关键的一部分展示(谅解一下)
doGetBean()
.....................................................
if (mbd.isSingleton()) {
// 获取单实例bean 获取不到的话就通过getObject()里面的 createBean(beanName, mbd, args); 创建实例
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
}
});
createBean(beanName, mbd, args)里面实际又调用 Object beanInstance = doCreateBean(beanName, mbdToUse, args) 创建实例 并用Object接收
3、让我们看看doCreateBean是如何创建bean实例的:
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
...........................................................
Object exposedObject = bean;
try {
//在里面进行各种判断为属性赋值,先为属性赋值,下面再调用initializeBean()
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
//后置处理器的调用,以及bean的初始化都在此被执行(ง •_•)ง ,后面进入initializeBean方法
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
...........................................................
return exposedObject;
}
4、
initializeBean
方法(也就是
BeanPostProcessor
最关键的执行步骤):
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
**// 1. 应用后处理器的BeforeInitialization方法**
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
**//调用bean的初始化方法**
invokeInitMethods(beanName, wrappedBean, mbd); **ini-method**
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
**// 3. 调用后处理器的AfterInitialization方法**
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
}
可以看到,初始化方法是在BeanPostProcessor执行之后才执行的,下面让我们了解一下applyBeanPostProcessorsBeforeInitialization具体是如何获取,并执行的
5、
applyBeanPostProcessorsBeforeInitialization
:
进入方法,首先通过foreach遍历容器中得到的所有BeanPostProcessor;挨个执行beforeInitialization,
一但返回null,跳出for循环,不会执行后面的BeanPostProcessor.postProcessorsBeforeInitialization(同理applyBeanPostProcessorsAfterInitialization也是如此)
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
//初始化之前按调用了BeforeInitialization方法
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
3、总的来说,就是再doCreateBean创建bean的时候调用了populateBean(beanName, mbd, instanceWrapper)方法给bean进行属性赋值。
⭐(细节问题:一定时先给bean属性赋值,再调用的BeanPostProcessor,初始化方法)在属性赋值以后调用了初始化bean的方法initializeBean
在initializaBean里面就调用了后置处理器,可以发现,BeanPostProcessor是在初始化方法前后调用的(ini-method)
{
1- applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
2- invokeInitMethods(beanName, wrappedBean, mbd);执行自定义初始化
3- applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
6、尾:
谈一下
BeanPostProcessor
及其子类:(这里只涉及一下
ApplicationContextAwareProcessor
)1、
InitDestroyAnnotationBeanPostProcessor
处理初始化方法(我们初始化方法是如何执行的,如何被容器发现的,都是因为这个组件在工作,可在int-method打断点看看具体调试)
2、
AutowiredAnnotationBeanPostProcessor
处理自动装配,为什么Spring可以自动装配呢,当然是因为有这个类了,这里就不多说。
3、
BeanValidationPostProcessor
主要是用来数据校验,一般在MVC里面用的比较多
4、
ApplicationContextAwareProcessor
作用是帮我们组件里面注入IOC容器 如何注入呢?看代码
只需要实现ApplicationContextAware接口,并且重写setApplicationContext方法,再将ApplicationContext对象传入即可
@Component
public class Dog implements ApplicationContextAware {
//@Autowired
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
// TODO Auto-generated method stub
this.applicationContext = applicationContext;
}
走一下源码:
从initializeBean初始化bean的时候里面调用了applyBeanPostProcessorsBeforeInitialization--->postProcessBeforeInitialization--->invokeAwareInterfaces
@Override
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
AccessControlContext acc = null;
if (System.getSecurityManager() != null &&
(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) { 在这里进行了判断,判断是否实现了ApplicationContextAware以及这些其他的的接口
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
if (acc != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
invokeAwareInterfaces(bean); 如果是的话就调用invokeAwareInterfaces给里面注入值,怎么注入的,看下面的方法;(虽然是if语句,但是都会进行判断,注意细节)
return null;
}
}, acc);
}
else {
invokeAwareInterfaces(bean);
}
return bean;
}
注入:
private void invokeAwareInterfaces(Object bean) { 判断是哪个Aware,那把哪个Aware注入进去
if (bean instanceof Aware) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
if (bean instanceof ApplicationContextAware) {
这里我们是ApplicationContextAware,所以直接把bean强转ApplicationContextAware再调用setApplicationContext,直接把IOC容器注入进去,然后就实现了向组件里面注入ioc容器了
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
}
如果哪里不足,还请指出,大家一起共同进步(
^ _^
),加油。
##BeanPostProcessor原理由浅入深