话不多说,先看代码:
/**
* Populate the bean instance in the given BeanWrapper with the property values
* from the bean definition.
* @param beanName the name of the bean
* @param mbd the bean definition for the bean
* @param bw the BeanWrapper with bean instance
*/
@SuppressWarnings("deprecation") // for postProcessPropertyValues
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// Skip property population phase for null instance.
return;
}
}
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
//判断是否需要属性设置
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {//第五次
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
}
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (BeanPostProcessor bp : getBeanPostProcessors()) {//第六次
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);//循环依赖
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
}
if (needsDepCheck) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
checkDependencies(beanName, mbd, filteredPds, pvs);
}
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
其中第五次和第六次调用后置处理器的关键代码:
//判断是否需要属性设置
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {//第五次
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
}
for (BeanPostProcessor bp : getBeanPostProcessors()) {//第六次
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);//循环依赖
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
为什么这2个要一起说呢,因为这两个是一起作用的。
1、当第五次调用的时候。如果判断返回了false,那么第六次就不再执行了。
2、当第五次调用的时候。如果判断返回了true,那么第六次将继续执行。
3、从第六次执行代码可以看出:如果我们返回为null,spring将会自行再处理一次。这样就避免了返回为null的情况。
我们接着前面的代码来。
修改一下test和app的代码:
package test.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import test.dao.Dao;
@Component
public class Test {
@Autowired
Dao dao;
public void test(){
System.out.println(dao);
}
}
package test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import test.config.Appconfig;
import test.config.Test;
import test.dao.Dao;
import test.dao.DaoImpl;
import test.service.DaoService;
import test.service.MYService;
import java.io.IOException;
public class App {
public static void main(String[] args) {
AnnotationConfigApplicationContext annotationConfigApplicationContext=new AnnotationConfigApplicationContext();
annotationConfigApplicationContext.register(Appconfig.class);
annotationConfigApplicationContext.refresh();
// System.out.println((Dao)(annotationConfigApplicationContext.getBean("daoImpl")));
((Test)annotationConfigApplicationContext.getBean("test")).test();
}
}
我们先看一下不写后置处理器的结果:
接下来写上后置处理器:
package test.mypostprocessors;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.stereotype.Component;
@Component
public class MYInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
/**
* spring第一次调用后置处理器的方法
* 这个方法是在实例化之前产生作用,当这个方法不返回null的时候,就会直接调用BeanPostProcessor的postProcessAfterInitialization方法然后直接返回出去
* 这样就跳过了中间的许多步骤(如推断构造方法,自动装配)
* 如果这个方法返回null,则会按照spring的流程继续走下去
* @param beanClass the class of the bean to be instantiated
* @param beanName the name of the bean
* @return
* @throws BeansException
*/
// @Override
// public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
// if(beanName.equals("daoService"))
// System.out.println("aaaaaaaa");
return Proxy.newProxyInstance(this.getClass().getClassLoader(),new Class[]{MYService.class},new MYInvocationHandler());
// return null;
// }
/**
* 这个方法是在实例化之后产生作用,由于返回的值是bool类型
* 判断是否需要对属性的填充或修改(@Autowired要不要管)
* @param bean the bean instance created, with properties not having been set yet
* @param beanName the name of the bean
* @return
* @throws BeansException
*/
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if(beanName.equals("test"))
System.out.println("postProcessAfterInstantiation----"+beanName);
return false;
}
//设置属性值
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
if(beanName.equals("test")) {
System.out.println("postProcessProperties----" + beanName);
}
return null;
}
}
因为我手动返回了false,那么test中dao能否拿到呢?
打印了postProcessAfterInstantiation----test证明使用了我们的后置处理器,postProcessProperties没有打印证明没有使用,而我们能看见test的dao属性为null。而我们正常的不应该是这样,证明第五次返回了false的话,就不会执行第六次了。
如果返回true,那么就一定会执行第六次后置处理器,由于不可能不注入,因此,第六次后置处理器若返回的不合理则spring自己依旧还会去处理,这个过程暂时不说,不属于后置处理器的范畴。
图中能看到postProcessProperties----test打印出来了,证明postProcessProperties调用了,由于我返回的null不合理,spring又自己去实现了一次。这里具体的不详述,有兴趣的可以自己看看这部分的源码:
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
至此,第五次、第六次的后置处理器就说完了。