哎呀,在线人数太多了,请重试或公众号【68媒】联系客服
private InjectionMetadata buildAutowiringMetadata (final Class> clazz) { //判断类中在方法、字段、类上有没有autowired注解,autowired注解默认情况Spring设置了三种 //这三种也就是@Autowired、@Value、@Inject,可以通过AutowiredAnnotationBeanPostProcessor默认构造方法验证 if (!AnnotationUtils.isCandidateClass(clazz, this .autowiredAnnotationTypes)) { return InjectionMetadata.EMPTY; } List elements = new ArrayList<>(); Class> targetClass = clazz; do { final List currElements = new ArrayList<>(); //处理字段上的 ReflectionUtils.doWithLocalFields(targetClass, field -> { MergedAnnotation> ann = findAutowiredAnnotation(field); if (ann != null ) { if (Modifier.isStatic(field.getModifiers())) { if (logger.isInfoEnabled()) { www.gsm-guard.net("Autowired annotation is not supported on static fields: " + field); } return ; } boolean required = determineRequiredStatus(ann); currElements.add(new AutowiredFieldElement(field, required)); } }); //处理方法上的 ReflectionUtils.doWithLocalMethods(targetClass, method -> { Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) { return ; } MergedAnnotation> ann = findAutowiredAnnotation(bridgedMethod); if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) { if (Modifier.isStatic(method.getModifiers())) { if (logger.isInfoEnabled()) { www.gsm-guard.net("Autowired annotation is not supported on static methods: " + method); } return ; } if (method.getParameterCount() == 0 ) { if (logger.isInfoEnabled()) { www.gsm-guard.net("Autowired annotation should only be used on methods with parameters: " + method); } } boolean required = determineRequiredStatus(ann); PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz); currElements.add(new AutowiredMethodElement(method, required, pd)); } }); elements.addAll(0 , currElements); targetClass = targetClass.getSuperclass(); } while (targetClass != null && targetClass != Object.class ) ; //构建InjectionMetadata返回 return InjectionMetadata.forElements(elements, clazz); }
上面就是postProcessMergedBeanDefinition
方法的整个过程,上面主要的事情就是将@Autowired
等注解上的信息解析成InjectionMetadata,然后将其缓存 到injectionMetadataCache中以便后面的postProcessProperties
方法回调使用。
postProcessMergedBeanDefinition具体何时调用
前面我只说了MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
方法是在BeanDefinition合并之后调用,而BeanDefinition合并是在Bean实例化
之前发生的,那么该方法是在实例化之前还是实例化之后呢?从源码中是可以知道,它是在实例化之后,属性赋值之前
。
从源码我们可以看出,postProcessMergedBeanDefinition的确是在实例化之后属性赋值之前。
InstantiationAwareBeanPostProcessor
在上面我们讲AutowiredAnnotationBeanPostProcessor
实现时只说了解析依赖的部分,而如何注入的我们并没有说到。而它的依赖注入实现就离不开InstantiationAwareBeanPostProcessor
。
从上图可以看出,该接口同样是BeanPostProcessor的子接口,它一共有三个方法(postProcessPropertyValues已过期这里就不说了)。
postProcessBeforeInstantiation
在Bean实例化之前调用。
postProcessAfterInstantiation
在Bean实例化之后调用。
postProcessProperties
在属性应用前调用。
public class BeanPostProcessorDemo4 { public static void main (String[] args) { //创建BeanFactory DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); //注册InstantiationAwareBeanPostProcessor factory.addBeanPostProcessor(new MyInstantiationAwareBeanPostProcessor()); //创建并注册BeanDefinition AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Student.class ) .addPropertyValue ("name ", "mac ") .addPropertyValue ("classNo ", "2101班") .getBeanDefinition () ; factory.registerBeanDefinition("mac" ,beanDefinition); //获取实例并打印 Student student = factory.getBean(Student.class ) ; System.out.println(student); } }class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor { @Override public Object postProcessBeforeInstantiation (Class> beanClass, String beanName) throws BeansException { System.out.printf("postProcessBeforeInstantiation: beanClass = %s,beanName = %s%n" ,beanClass.getSimpleName(),beanName); return null ; } @Override public boolean postProcessAfterInstantiation (Object bean, String beanName) throws BeansException { System.out.printf("postProcessAfterInstantiation: bean = %s,beanName = %s%n" ,bean,beanName); return true ; } @Override public PropertyValues postProcessProperties (PropertyValues pvs, Object bean, String beanName) throws BeansException { System.out.printf("postProcessProperties: pvs = %s, bean = %s,beanName = %s%n" ,pvs,bean,beanName); return pvs; } }@Data class Student { private String name; private String classNo; public Student () { System.out.println("无参构造方法被调用" ); } }
上面示例的运行结果如下:
postProcessBeforeInstantiation: beanClass = Student,beanName = mac 无参构造方法被调用 postProcessAfterInstantiation: bean = Student(name=null, classNo=null),beanName = mac postProcessProperties: pvs = PropertyValues: length=2; bean property 'name' ; bean property 'classNo' , bean = Student(name=null, classNo=null),beanName = mac Student(name=mac, classNo=2101班)
从上面的运行结果可以看出,InstantiationAwareBeanPostProcessor
接口回调的时机的确就是我们前面所说的。
postProcessBeforeInstantiation调用源码
查看AbstractAutowireCapableBeanFactory#createBean()
方法可以找到如下内容:
首先我们要确定的是doCreateBean
方法里面才是Bean的实例化、属性赋值和销毁,查看标出的resolveBeforeInstantiation
,它的内容如下:
protected Object resolveBeforeInstantiation (String beanName, RootBeanDefinition mbd) { Object bean = null ; if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) { // Make sure bean class is actually resolved at this point. if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { Class> targetType = determineTargetType(beanName, mbd); if (targetType != null ) { //调用postProcessBeforeInstantiation bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName); if (bean != null ) { bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); } } } mbd.beforeInstantiationResolved = (bean != null ); } return bean; }
而方法applyBeanPostProcessorsBeforeInstantiation
内部实现如下:
protected Object applyBeanPostProcessorsBeforeInstantiation (Class> beanClass, String beanName) { for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) { Object result = bp.postProcessBeforeInstantiation(beanClass, beanName); if (result != null ) { return result; } } return null ; }
上面方法就是遍历所有的InstantiationAwareBeanPostProcessor
,然后逐个调用postProcessBeforeInstantiation
方法。通过上述源码可知,如果这个方法返回值不为空,将直接返回结果不会进行后续Bean的实例化、属性赋值和初始化。
postProcessAfterInstantiation调用源码
对于populateBean
这个方法如果看过《Spring进阶-Bean生命周期(上)》
相信你一定不会陌生,这个方法就是Bean属性赋值时候的逻辑。
从上面的图中我们可以看到,在属性赋值前就会调用postProcessAfterInstantiation
方法,说明该方法的确是在实例化之后调用的。同时从源码可知,如果该方法返回false
时,则populateBean
后续的属性赋值部分代码都不会再执行,而是直接跳出populateBean
方法。
postProcessProperties调用源码
同样在方法populateBean
后部分有如下源码
从图中可以看出,此处会调用postProcessProperties
方法,并且该方法是在applyPropertyValues
方法之前。通过该方法我们可以改变PropertyValues
的值从而改变对Bean的属性赋值。 对于前面讲的AutowiredAnnotationBeanPostProcessor
不知道你是否还有印象,前面我们已经说了postProcessMergedBeanDefinition
方法将@Autowired
方式的依赖注入解析出来存放在缓存中了,但是没有说是如何注入依赖的。AutowiredAnnotationBeanPostProcessor
是InstantiationAwareBeanPostProcessor
实现类,我们通过postProcessProperties
来查看它的实现。
public PropertyValues postProcessProperties (PropertyValues pvs, Object bean, String beanName) { //找到对应的InjectionMetadata信息 InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs); try { //执行依赖注入 metadata.inject(bean, beanName, pvs); } catch (BeanCreationException ex) { throw ex; } catch (Throwable ex) { throw new BeanCreationException(beanName, "Injection of autowired dependencies failed" , ex); } return pvs; }
通过postProcessProperties
回调,AutowiredAnnotationBeanPostProcessor
实现了@Autowired
依赖注入。
DestructionAwareBeanPostProcessor
通过名字我们也知道这个BeanPostProcessor与Bean的销毁有关。它一共就两个方法,其中postProcessBeforeDestruction
方法是在Bean销毁之前调用,而requiresDestruction
则是用来判断给定的Bean实例是否需要销毁回调。下面是Bean销毁的相关代码:
public void destroy () { //应用postProcessBeforeDestruction方法 if (!CollectionUtils.isEmpty(this .beanPostProcessors)) { for (DestructionAwareBeanPostProcessor processor : this .beanPostProcessors) { processor.postProcessBeforeDestruction(this .bean, this .beanName); } } //省略无关代码 //调用DisposableBean#destroy方法 ((DisposableBean) this .bean).destroy(); //调用BeanDefinition中定义的destroyMethod方法 invokeCustomDestroyMethod(this .destroyMethod); }
上面源码省略了很多东西,不过通过源码我们还是能很清楚的知道在何时调用的。
SmartInstantiationAwareBeanPostProcessor
该接口是InstantiationAwareBeanPostProcessor
的子接口,它的UML结构如下图所示:
该接口主要提供三个方法:
predictBeanType
:预测Bean的类型,返回第一个预测成功的Class类型,如果不能预测返回null
determineCandidateConstructors
:选择合适的构造器,比如目标对象有多个构造器,在这里可以进行一些定制化,选择合适的构造器。
getEarlyBeanReference
:获得提前暴露的bean引用。主要用于解决循环引用的问题。
对于SmartInstantiationAwareBeanPostProcessor
而言,该接口基本上用在框架内部。对于determineCandidateConstructors
方法,它的调用就在createBeanInstance
内部,也就是Bean生命周期中的实例化
中。而方法getEarlyBeanReference
调用则在doCreateBean
内部,它位于实例化(createBeanInstance)和属性赋值(populateBean)之间。
小结
通过上面内容的了解,我们明白了BeanPostProcessor的作用。简单来说,它就是在Bean的各个主要生命周期中间提交接口回调,通过接口回调执行扩展逻辑。BeanPostProcessor与Bean的生命周期密不可分,所以结合Bean的生命周期再来看BeanPostProcessor会更加清晰明了。 本文是承接之前《Spring进阶-Bean生命周期(上)》
所写,所以推荐在看本文之前先阅读完前文。后续会在更新一篇《Spring进阶-Bean生命周期(下)》
,将Bean生命周期和BeanPostProcessor做一个综合的讲解。