GVKun编程网logo

Bean后置处理器 - InstantiationAwareBeanPostProcessor#postProcessProperties(bean后置处理器)

10

对于想了解Bean后置处理器-InstantiationAwareBeanPostProcessor#postProcessProperties的读者,本文将提供新的信息,我们将详细介绍bean后置处

对于想了解Bean后置处理器 - InstantiationAwareBeanPostProcessor#postProcessProperties的读者,本文将提供新的信息,我们将详细介绍bean后置处理器,并且为您提供关于@Configuration中的来声明BeanPostProcessor和BeanFactoryPostProcessor、Bean 后置处理器 - SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors、Bean后置处理器 - applyMergedBeanDefinitionPostProcessors、Bean后置处理器 - InstantiationAwareBeanPostProcessor#applyBeanPostProcessorsBeforeInstantiation的有价值信息。

本文目录一览:

Bean后置处理器 - InstantiationAwareBeanPostProcessor#postProcessProperties(bean后置处理器)

Bean后置处理器 - InstantiationAwareBeanPostProcessor#postProcessProperties(bean后置处理器)

代码片段:

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean

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;
            //这里也是调用的实例化后的后置处理器, 只是调用的方法不一样
       //这里会进行 @Autowired 和 @Resource 的注入工作
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; } } }

同样的, 通过调试的方式, 来确定这里使用了那些后置处理器:

1.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor

2.CommonAnnotationBeanPostProcessor

3.AutowiredAnnotationBeanPostProcessor

 

ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor

@Override
public PropertyValues postProcessProperties(@Nullable PropertyValues pvs, Object bean, String beanName) {
    // Inject the BeanFactory before AutowiredAnnotationBeanPostProcessor''s
    // postProcessProperties method attempts to autowire other configuration beans.
    if (bean instanceof EnhancedConfiguration) {
        ((EnhancedConfiguration) bean).setBeanFactory(this.beanFactory);
    }
    return pvs;
}

这里是对 EnhancedConfiguration 提供支持. 其实他继承了 BeanFactoryAware 接口, 并且什么都没干

public interface EnhancedConfiguration extends BeanFactoryAware {}

EnhancedConfiguration 是 ConfigurationClassEnhancer 的一个内部接口, 是给 spring 自己内部使用的, 开发人员用不了这个, 也没必要

 

CommonAnnotationBeanPostProcessor

@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    //找出类中标注了@Resource注解的属性和方法
    //else if (field.isAnnotationPresent(Resource.class))
    InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs);
    try {
        metadata.inject(bean, beanName, pvs);
    }
    catch (Throwable ex) {
        throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex);
    }
    return pvs;
}

这里主要是对 @Resource 进行注入

findResourceMetadata在MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition的时候执行过.

所以这里, 大概率是从缓存中拿取结果, 然后进行注入操作. 事实上, 也确实如此.

 

inject 最终会调用

org.springframework.beans.factory.annotation.InjectionMetadata.InjectedElement#inject 方法

protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs)
        throws Throwable {

    if (this.isField) {
        Field field = (Field) this.member;
        ReflectionUtils.makeAccessible(field);
        field.set(target, getResourceToInject(target, requestingBeanName));
    }
    else {
        if (checkPropertySkipping(pvs)) {
            return;
        }
        try {
            Method method = (Method) this.member;
            ReflectionUtils.makeAccessible(method);
            method.invoke(target, getResourceToInject(target, requestingBeanName));
        }
        catch (InvocationTargetException ex) {
            throw ex.getTargetException();
        }
    }
}

这里分两种情况进行处理, 一种是 通过字段注入, 另一种是通过方法注入.

字段注入的方式是比较多见的. 

getResourceToInject() 方法是一个被重写了的方法:

org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.ResourceElement#getResourceToInject

他是在一个内部类中被重写的方法.

@Override
protected Object getResourceToInject(Object target, @Nullable String requestingBeanName) {
    return (this.lazyLookup ? buildLazyResourceProxy(this, requestingBeanName) :
            getResource(this, requestingBeanName));
}

默认情况下, lazy = false, 所以会走 getResource() 方法

org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#getResource

protected Object getResource(LookupElement element, @Nullable String requestingBeanName)
        throws NoSuchBeanDefinitionException {

    if (StringUtils.hasLength(element.mappedName)) {
        return this.jndiFactory.getBean(element.mappedName, element.lookupType);
    }
    if (this.alwaysUseJndiLookup) {
        return this.jndiFactory.getBean(element.name, element.lookupType);
    }
    if (this.resourceFactory == null) {
        throw new NoSuchBeanDefinitionException(element.lookupType,
                "No resource factory configured - specify the ''resourceFactory'' property");
    }
    return autowireResource(this.resourceFactory, element, requestingBeanName);
}

根据设置的不同属性, 进不同的方法, 这里主要看 autowireResource , 因为一般情况是不需要去设置这些属性的

protected Object autowireResource(BeanFactory factory, LookupElement element, @Nullable String requestingBeanName)
        throws NoSuchBeanDefinitionException {

    Object resource;
    Set<String> autowiredBeanNames;
    String name = element.name;

    if (factory instanceof AutowireCapableBeanFactory) {
        AutowireCapableBeanFactory beanFactory = (AutowireCapableBeanFactory) factory;
        DependencyDescriptor descriptor = element.getDependencyDescriptor();
        //优先使用 根据 name 注入, 这个 name 就是 beanName
        //当 beanName 找不到时, 才就会去根据 type 来注入
        //依据是 !factory.containsBean(name) 
        if (this.fallbackToDefaultTypeMatch && element.isDefaultName && !factory.containsBean(name)) {
            autowiredBeanNames = new LinkedHashSet<>();
            //根据type(类型)来进行依赖注入
            resource = beanFactory.resolveDependency(descriptor, requestingBeanName, autowiredBeanNames, null);
            if (resource == null) {
                //如果返回时 resource , 则表明, spring容器中找不到, 也创建不了 这个依赖的bean
                throw new NoSuchBeanDefinitionException(element.getLookupType(), "No resolvable resource object");
            }
        }
        else {
            //根据name(名称)来进行依赖注入
            resource = beanFactory.resolveBeanByName(name, descriptor);
            autowiredBeanNames = Collections.singleton(name);
        }
    }
    else {
        resource = factory.getBean(name, element.lookupType);
        autowiredBeanNames = Collections.singleton(name);
    }

    if (factory instanceof ConfigurableBeanFactory) {
        ConfigurableBeanFactory beanFactory = (ConfigurableBeanFactory) factory;
        for (String autowiredBeanName : autowiredBeanNames) {
            if (requestingBeanName != null && beanFactory.containsBean(autowiredBeanName)) {
                beanFactory.registerDependentBean(autowiredBeanName, requestingBeanName);
            }
        }
    }

    return resource;
}

都说, @Resource 在不设置 name 和 type 的情况下, 是优先使用 name 去 获取/创建 依赖的 bean , 如果name找不到, 才会使用 type.

这段代码, 就是支撑的依据.

 

AutowiredAnnotationBeanPostProcessor

@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    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;
}

这里主要是对 @Autowired 和 @Value 进行注入的. findAutowiringMetadata

findAutowiringMetadata在MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition的时候执行过.

所以此处, 是从缓存中拿取结果, 然后进行注入操作.

最终会调用本类中的方法:

org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject

@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    Field field = (Field) this.member;
    Object value;
    if (this.cached) {
        value = resolvedCachedArgument(beanName, this.cachedFieldValue);
    }
    else {
        DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
        desc.setContainingClass(bean.getClass());
        Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
        Assert.state(beanFactory != null, "No BeanFactory available");
        TypeConverter typeConverter = beanFactory.getTypeConverter();
        try {
            //根据 type 进行依赖注入
            value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
        }
        catch (BeansException ex) {
            throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
        }
        synchronized (this) {
            if (!this.cached) {
                if (value != null || this.required) {
                    this.cachedFieldValue = desc;
                    registerDependentBeans(beanName, autowiredBeanNames);
                    if (autowiredBeanNames.size() == 1) {
                        String autowiredBeanName = autowiredBeanNames.iterator().next();
                        if (beanFactory.containsBean(autowiredBeanName) &&
                                beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
                            this.cachedFieldValue = new ShortcutDependencyDescriptor(
                                    desc, autowiredBeanName, field.getType());
                        }
                    }
                }
                else {
                    this.cachedFieldValue = null;
                }
                this.cached = true;
            }
        }
    }
    if (value != null) {
        ReflectionUtils.makeAccessible(field);
        field.set(bean, value);
    }
}

 

这里有一个隐藏的后置处理器: SmartInstantiationAwareBeanPostProcessor

留到下一篇看

@Configuration中的来声明BeanPostProcessor和BeanFactoryPostProcessor

@Configuration中的来声明BeanPostProcessor和BeanFactoryPostProcessor

最近在遇到比较一个问题,通常我们在spring中使用@Configuration来注解一个类时,可以同时用Autowire 和@Value 给该配置类自动注入属性值,如下:


@Configuration
public class ConfigA {
   @Autowired
   private Environment environment;
   @Value("${name}")
   private string name;
   @Bean
   public A a() {
       A a = new A();
       a.name = name;
       return a;
   }
}

我们正常情况下都是能自动注入environment和name的,但是当在configration 中如果声明了一个BeanPostProcessor时,如下:

   @Bean
    public MyBeanPostProcessor myBeanPostProcessor(A a) {
        log.info("env=:{}", environment);
        MyBeanPostProcessor myBeanPostProcessor = new MyBeanPostProcessor();
        myBeanPostProcessor.setA(a);
        return myBeanPostProcessor;
    }

你会发现打出来的log env 为null,同时A的name 也为null,这个配置类的 @Autowired和@Value都没有生效。
翻阅spring 的官网,其中有一段小tip,如下

    
Make sure that the dependencies you inject that way are of the simplest kind only. @Configuration classes are processed quite early during the initialization of the context, and forcing a dependency to be injected this way may lead to unexpected early initialization. Whenever possible, resort to parameter-based injection, as in the preceding example.

Also, be particularly careful with BeanPostProcessor and BeanFactoryPostProcessor definitions through @Bean. Those should usually be declared as static @Bean methods, not triggering the instantiation of their containing configuration class. Otherwise, @Autowired and @Value may not work on the configuration class itself, since it is possible to create it as a bean instance earlier than AutowiredAnnotationBeanPostProcessor.

意思就是BeanPostProcessor 和BeanFactoryPostProcessor 会在configuration 本身这个bean初始化之前,可以在spring onrefresh 方法中找到这段代码

image.png

踩坑记录一下。

Bean 后置处理器 - SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors

Bean 后置处理器 - SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors

spring 在创建对象 (org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance) 的时候,使用了这个 构造函数后置处理器,用来选择使用哪个构造函数的.

所以这个后置处理器的执行时机是: 对象实例化之前执行

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#determineConstructorsFromBeanPostProcessors

@Nullable
protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName)
        throws BeansException {

    if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
                SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
                Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
                if (ctors != null) {
                    return ctors;
                }
            }
        }
    }
    return null;
}

这里满足条件的后置处理器,就两个:

1.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor

2. AutowiredAnnotationBeanPostProcessor

 

ImportAwareBeanPostProcessor

@Override
@Nullable
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {
    return null;
}

这个类并没有实现这个接口,而是父类去实现的:

org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter#determineCandidateConstructors

然而,他也是 啥也没干.   

怎么感觉这个后置处理器,哪哪都有他,却哪哪都不干活.

 

AutowiredAnnotationBeanPostProcessor

@Override
@Nullable
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
        throws BeanCreationException {

    // Let''s check for lookup methods here...
    if (!this.lookupMethodsChecked.contains(beanName)) {
        try {
            ReflectionUtils.doWithMethods(beanClass, method -> {
                Lookup lookup = method.getAnnotation(Lookup.class);
                if (lookup != null) {
                    Assert.state(this.beanFactory != null, "No BeanFactory available");
                    LookupOverride override = new LookupOverride(method, lookup.value());
                    try {
                        RootBeanDefinition mbd = (RootBeanDefinition)
                                this.beanFactory.getMergedBeanDefinition(beanName);
                        mbd.getMethodOverrides().addOverride(override);
                    }
                    catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanCreationException(beanName,
                                "Cannot apply @Lookup to beans without corresponding bean definition");
                    }
                }
            });
        }
        catch (IllegalStateException ex) {
            throw new BeanCreationException(beanName, "Lookup method resolution failed", ex);
        }
        this.lookupMethodsChecked.add(beanName);
    }

    // Quick check on the concurrent map first, with minimal locking.
    Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
    if (candidateConstructors == null) {
        // Fully synchronized resolution now...
        synchronized (this.candidateConstructorsCache) {
            candidateConstructors = this.candidateConstructorsCache.get(beanClass);
            if (candidateConstructors == null) {
                Constructor<?>[] rawCandidates;
                try {
                    //反射获取所有构造函数
                    rawCandidates = beanClass.getDeclaredConstructors();
                }
                catch (Throwable ex) {
                    throw new BeanCreationException(beanName,
                            "Resolution of declared constructors on bean Class [" + beanClass.getName() +
                            "] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
                }
                //候选构造方法
                List<Constructor<?>> candidates = new ArrayList<>(rawCandidates.length);
                Constructor<?> requiredConstructor = null;
                Constructor<?> defaultConstructor = null;
                //这个貌似是 Kotlin 上用的, 不用管它
                Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);
                int nonSyntheticConstructors = 0;
                //遍历这些构造函数
                for (Constructor<?> candidate : rawCandidates) {
                    //判断构造方法是否是合成的
                    if (!candidate.isSynthetic()) {
                        nonSyntheticConstructors++;
                    }
                    else if (primaryConstructor != null) {
                        continue;
                    }
                    //查看是否有 @Autowired 注解
                    //如果有多个构造方法, 可以通过标注 @Autowired 的方式来指定使用哪个构造方法
                    AnnotationAttributes ann = findAutowiredAnnotation(candidate);
                    if (ann == null) {
                        Class<?> userClass = ClassUtils.getUserClass(beanClass);
                        if (userClass != beanClass) {
                            try {
                                Constructor<?> superCtor =
                                        userClass.getDeclaredConstructor(candidate.getParameterTypes());
                                ann = findAutowiredAnnotation(superCtor);
                            }
                            catch (NoSuchMethodException ex) {
                                // Simply proceed, no equivalent superclass constructor found...
                            }
                        }
                    }
                    //有 @Autowired 的情况
                    if (ann != null) {
                        if (requiredConstructor != null) {
                            throw new BeanCreationException(beanName,
                                    "Invalid autowire-marked constructor: " + candidate +
                                    ". Found constructor with ''required'' Autowired annotation already: " +
                                    requiredConstructor);
                        }
                        boolean required = determineRequiredStatus(ann);
                        if (required) {
                            if (!candidates.isEmpty()) {
                                throw new BeanCreationException(beanName,
                                        "Invalid autowire-marked constructors: " + candidates +
                                        ". Found constructor with ''required'' Autowired annotation: " +
                                        candidate);
                            }
                            requiredConstructor = candidate;
                        }
                        candidates.add(candidate);
                    }
                    //无参构造函数的情况
                    else if (candidate.getParameterCount() == 0) {
                        //构造函数没有参数, 则设置为默认的构造函数
                        defaultConstructor = candidate;
                    }
                }
                //到这里, 已经循环完了所有的构造方法

                //候选者不为空时
                if (!candidates.isEmpty()) {
                    // Add default constructor to list of optional constructors, as fallback.
                    if (requiredConstructor == null) {
                        if (defaultConstructor != null) {
                            candidates.add(defaultConstructor);
                        }
                        else if (candidates.size() == 1 && logger.isInfoEnabled()) {
                            logger.info("Inconsistent constructor declaration on bean with name ''" + beanName +
                                    "'': single autowire-marked constructor flagged as optional - " +
                                    "this constructor is effectively required since there is no " +
                                    "default constructor to fall back to: " + candidates.get(0));
                        }
                    }
                    candidateConstructors = candidates.toArray(new Constructor<?>[0]);
                }
                //类的构造方法只有1个, 且该构造方法有多个参数
                else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
                    candidateConstructors = new Constructor<?>[] {rawCandidates[0]};
                }
                //这里不会进, 因为 primaryConstructor = null
                else if (nonSyntheticConstructors == 2 && primaryConstructor != null &&
                        defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {
                    candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor};
                }
                //这里也不会进, 因为 primaryConstructor = null
                else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {
                    candidateConstructors = new Constructor<?>[] {primaryConstructor};
                }
                else {
                    //如果方法进了这里, 就是没找到合适的构造方法
                    //1. 类定义了多个构造方法, 且没有 @Autowired , 则有可能会进这里
                    candidateConstructors = new Constructor<?>[0];
                }
                this.candidateConstructorsCache.put(beanClass, candidateConstructors);
            }
        }
    }
   //这里如果没找到, 则会返回 null, 而不会返回空数组
return (candidateConstructors.length > 0 ? candidateConstructors : null); }

这个方法比较长,但是仔细看,是能看懂的。大致可以划分为几个步骤:

1. 获取类的所有构造方法

2. 遍历构造方法

  |-> 只有一个无参构造方法,则返回 null

  |-> 只有一个有参构造方法,则返回这个构造方法

  |-> 有多个构造方法且没有 @Autowired, 此时 spring 则会蒙圈了,不知道使用哪一个了。这里的后置处理器,翻译过来,叫智能选择构造方法后置处理器.

     当选择不了的时候,干脆返回 null

  |-> 有多个构造方法,且在其中一个方法上标注了 @Autowired , 则会返回这个标注的构造方法

  |-> 有多个构造方法,且在多个方法上标注了 @Autowired, 则 spring 会抛出异常,spring 会认为,你指定了几个给我,是不是你弄错了

 

注:

这地方有个问题需要注意一下,如果你写了多个构造方法,且没有写 无参构造方法,那么此处返回 null, 

在回到 createBeanInstance 方法中,如果不能走 autowireConstructor (), 而走到 instantiateBean () 中去的话,会报错的.

因为类已经没有无参构造函数了

 

Bean后置处理器 - applyMergedBeanDefinitionPostProcessors

Bean后置处理器 - applyMergedBeanDefinitionPostProcessors

创建完对象之后, 接下来, 就应该想办法对属性进行注入了, 其中就包括 @Autowired 注入

但是在注入之前, 貌似 还没有对 @Autowired 进行扫描和解析.

代码块:

if (instanceWrapper == null) {
    /**
     * 创建 bean 实例,并将实例包裹在 BeanWrapper 实现类对象中返回。
     * createBeanInstance中包含三种创建 bean 实例的方式:
     *   1. 通过工厂方法创建 bean 实例
     *   2. 通过构造方法自动注入(autowire by constructor)的方式创建 bean 实例
     *   3. 通过无参构造方法方法创建 bean 实例
     *
     * 若 bean 的配置信息中配置了 lookup-method 和 replace-method,则会使用 CGLIB 增强 bean 实例。
     */
    instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
    mbd.resolvedTargetType = beanType;
}

// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
    if (!mbd.postProcessed) {
        try {
            //调用属性合并后置处理器, 进行属性合并
            //这里会进行 一些注解 的扫描
            //CommonAnnotationBeanPostProcessor -> @PostConstruct @PreDestroy @Resource
            //AutowiredAnnotationBeanPostProcessor -> @Autowired @Value
            applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
        }
        catch (Throwable ex) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                    "Post-processing of merged bean definition failed", ex);
        }
        mbd.postProcessed = true;
    }
}

接着看里面的内容

protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
        if (bp instanceof MergedBeanDefinitionPostProcessor) {
            MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
            bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
        }
    }
}

通过调试, 可以获取, 这里满足条件的, 有三个后置处理器, 按照调用先后顺序为: 

1.CommonAnnotationBeanPostProcessor

2.AutowiredAnnotationBeanPostProcessor

3.ApplicationListenerDetector

接下来看看里面都干了啥

 

CommonAnnotationBeanPostProcessor

这一步, 主要是扫描作用. 

1. 扫描 @PostConstruct 和 @PreDestroy (这个很直观的能看到, 其无参构造函数中, 出现了这两个注解)

2. 扫描 @Resource , 这个需要到 findResourceMetadata 中, 才能看到

public CommonAnnotationBeanPostProcessor() {
    setOrder(Ordered.LOWEST_PRECEDENCE - 3);
    setInitAnnotationType(PostConstruct.class);
    setDestroyAnnotationType(PreDestroy.class);
    ignoreResourceType("javax.xml.ws.WebServiceContext");
}

/**
 * 1.遍历扫描方法上标注了 @PostConstruct  和 @PreDestroy 注解的类
 * 2.遍历扫描方法上标注了 @Resource 注解的类
 * @param beanDefinition
 * @param beanType
 * @param beanName
 */
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
    super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
    InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
    metadata.checkConfigMembers(beanDefinition);
}

1. 调用父类方法, 进行@PostConstruct 和 @PreDestroy 扫描

org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor#postProcessMergedBeanDefinition

@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
    LifecycleMetadata metadata = findLifecycleMetadata(beanType);
    metadata.checkConfigMembers(beanDefinition);
}

findLifecycleMetadata最终会调用 org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor#buildLifecycleMetadata 方法

private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
    List<LifecycleElement> initMethods = new ArrayList<>();
    List<LifecycleElement> destroyMethods = new ArrayList<>();
    Class<?> targetClass = clazz;

    do {
        final List<LifecycleElement> currInitMethods = new ArrayList<>();
        final List<LifecycleElement> currDestroyMethods = new ArrayList<>();

        ReflectionUtils.doWithLocalMethods(targetClass, method -> {
            if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {
                LifecycleElement element = new LifecycleElement(method);
                currInitMethods.add(element);
                if (logger.isTraceEnabled()) {
                    logger.trace("Found init method on class [" + clazz.getName() + "]: " + method);
                }
            }
            if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {
                currDestroyMethods.add(new LifecycleElement(method));
                if (logger.isTraceEnabled()) {
                    logger.trace("Found destroy method on class [" + clazz.getName() + "]: " + method);
                }
            }
        });

        initMethods.addAll(0, currInitMethods);
        destroyMethods.addAll(currDestroyMethods);
        //当前类解析完后, 拿到父类继续进行解析, 直到父类为 Object
        targetClass = targetClass.getSuperclass();
    }
    while (targetClass != null && targetClass != Object.class);

    return new LifecycleMetadata(clazz, initMethods, destroyMethods);
}

这里就是遍历类和其父类, 进行查找的.

 

2. 进行 @Resource 扫描

Resource 扫描, 是在本类中完成的.

org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#findResourceMetadata

private InjectionMetadata findResourceMetadata(String beanName, final Class<?> clazz, @Nullable PropertyValues pvs) {
    // Fall back to class name as cache key, for backwards compatibility with custom callers.
    String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
    // Quick check on the concurrent map first, with minimal locking.
    InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
    if (InjectionMetadata.needsRefresh(metadata, clazz)) {
        synchronized (this.injectionMetadataCache) {
            metadata = this.injectionMetadataCache.get(cacheKey);
            if (InjectionMetadata.needsRefresh(metadata, clazz)) {
                if (metadata != null) {
                    metadata.clear(pvs);
                }
                metadata = buildResourceMetadata(clazz);
                this.injectionMetadataCache.put(cacheKey, metadata);
            }
        }
    }
    return metadata;
}

这里主要看 buildResourceMetadata( ) 方法.

private InjectionMetadata buildResourceMetadata(final Class<?> clazz) {
    List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
    Class<?> targetClass = clazz;

    do {
        final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();

        //扫描字段
        ReflectionUtils.doWithLocalFields(targetClass, field -> {
            if (webServiceRefClass != null && field.isAnnotationPresent(webServiceRefClass)) {
                if (Modifier.isStatic(field.getModifiers())) {
                    throw new IllegalStateException("@WebServiceRef annotation is not supported on static fields");
                }
                currElements.add(new WebServiceRefElement(field, field, null));
            }
            else if (ejbRefClass != null && field.isAnnotationPresent(ejbRefClass)) {
                if (Modifier.isStatic(field.getModifiers())) {
                    throw new IllegalStateException("@EJB annotation is not supported on static fields");
                }
                currElements.add(new EjbRefElement(field, field, null));
            }
            else if (field.isAnnotationPresent(Resource.class)) {
                //静态字段上标注 @Resource , 会抛异常
                if (Modifier.isStatic(field.getModifiers())) {
                    throw new IllegalStateException("@Resource annotation is not supported on static fields");
                }
                if (!this.ignoredResourceTypes.contains(field.getType().getName())) {
                    currElements.add(new ResourceElement(field, field, null));
                }
            }
        });

        //扫描方法
        ReflectionUtils.doWithLocalMethods(targetClass, method -> {
            Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
            if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
                return;
            }
            if (method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
                if (webServiceRefClass != null && bridgedMethod.isAnnotationPresent(webServiceRefClass)) {
                    if (Modifier.isStatic(method.getModifiers())) {
                        throw new IllegalStateException("@WebServiceRef annotation is not supported on static methods");
                    }
                    if (method.getParameterCount() != 1) {
                        throw new IllegalStateException("@WebServiceRef annotation requires a single-arg method: " + method);
                    }
                    PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
                    currElements.add(new WebServiceRefElement(method, bridgedMethod, pd));
                }
                else if (ejbRefClass != null && bridgedMethod.isAnnotationPresent(ejbRefClass)) {
                    if (Modifier.isStatic(method.getModifiers())) {
                        throw new IllegalStateException("@EJB annotation is not supported on static methods");
                    }
                    if (method.getParameterCount() != 1) {
                        throw new IllegalStateException("@EJB annotation requires a single-arg method: " + method);
                    }
                    PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
                    currElements.add(new EjbRefElement(method, bridgedMethod, pd));
                }
                else if (bridgedMethod.isAnnotationPresent(Resource.class)) {
                    if (Modifier.isStatic(method.getModifiers())) {
                        throw new IllegalStateException("@Resource annotation is not supported on static methods");
                    }
                    Class<?>[] paramTypes = method.getParameterTypes();
                    //如果目标方法, 没有参数, 或者有多个参数, 则抛出异常
                    if (paramTypes.length != 1) {
                        throw new IllegalStateException("@Resource annotation requires a single-arg method: " + method);
                    }
                    if (!this.ignoredResourceTypes.contains(paramTypes[0].getName())) {
                        //这里拿到方法名, 会去跟类中的属性进行匹配
                        //匹配的规则是: method.equals(pd.getReadMethod()) || method.equals(pd.getWriteMethod())
                        //这个 readMethod 就是 getXXX 或 isXXX, writeMethod 就是 setXXX
                        //如果匹配不上, pd = null
                        PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
                        currElements.add(new ResourceElement(method, bridgedMethod, pd));
                    }
                }
            }
        });

        elements.addAll(0, currElements);
        targetClass = targetClass.getSuperclass();
    }
    while (targetClass != null && targetClass != Object.class);

    return new InjectionMetadata(clazz, elements);
}

注意到, 这里只进行了扫描转换工作, 并没有进行属性注入工作.

 

AutowiredAnnotationBeanPostProcessor

public AutowiredAnnotationBeanPostProcessor() {
    this.autowiredAnnotationTypes.add(Autowired.class);
    this.autowiredAnnotationTypes.add(Value.class);
    try {
        this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
                ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
        logger.trace("JSR-330 ''javax.inject.Inject'' annotation found and supported for autowiring");
    }
    catch (ClassNotFoundException ex) {
        // JSR-330 API not available - simply skip.
    }
}

@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
    InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
    metadata.checkConfigMembers(beanDefinition);
}

从这段代码, 可以猜测, 自动注入的类型, 是个集合, 这里有两个

1. @Autowired

2. @Value

findAutowiringMetadata() 最终会调用本类方法: 

org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#buildAutowiringMetadata

private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
    List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
    //需要处理的目标类
    Class<?> targetClass = clazz;

    do {
        final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();

        // 通过反射获取该类所有的字段,并遍历每一个字段,通过方法 findAutowiredAnnotation 遍历每一个字段的所用注解,
        // 如果用autowired修饰了,则返回 auotowired 相关属性
        ReflectionUtils.doWithLocalFields(targetClass, field -> {
            AnnotationAttributes ann = findAutowiredAnnotation(field);
            if (ann != null) {
                // 校验autowired注解是否用在了static方法上
                if (Modifier.isStatic(field.getModifiers())) {
                    if (logger.isInfoEnabled()) {
                        logger.info("Autowired annotation is not supported on static fields: " + field);
                    }
                    return;
                }
                boolean required = determineRequiredStatus(ann);
                currElements.add(new AutowiredFieldElement(field, required));
            }
        });

        //通过反射处理类的method
        ReflectionUtils.doWithLocalMethods(targetClass, method -> {
            Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
            if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
                return;
            }
            AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
            if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
                if (Modifier.isStatic(method.getModifiers())) {
                    if (logger.isInfoEnabled()) {
                        logger.info("Autowired annotation is not supported on static methods: " + method);
                    }
                    return;
                }
                if (method.getParameterCount() == 0) {
                    if (logger.isInfoEnabled()) {
                        logger.info("Autowired annotation should only be used on methods with parameters: " +
                                method);
                    }
                }
                boolean required = determineRequiredStatus(ann);
                //这里也会进行属性的匹配, 按照规则 : method.equals(pd.getReadMethod()) || method.equals(pd.getWriteMethod())
                //如果匹配不上, pd = null
                PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
                currElements.add(new AutowiredMethodElement(method, required, pd));
            }
        });

        //用@Autowired修饰的注解可能不止一个,因此都加在 elements 这个容器里面,一起处理
        elements.addAll(0, currElements);
        targetClass = targetClass.getSuperclass();
    }
    while (targetClass != null && targetClass != Object.class);

    return new InjectionMetadata(clazz, elements);
}

这里也只是进行了扫描, 没有进行属性注入工作.

 

ApplicationListenerDetector

@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
    this.singletonNames.put(beanName, beanDefinition.isSingleton());
}

这个类也是挺能凑热闹的. 这里没有进行任何扫描工作. 只是记录了容器中的 bean 是否是单例模式.

这里记录这个标志, 是为了后面用的. 对监听器进行过滤用的.

 

Bean后置处理器 - InstantiationAwareBeanPostProcessor#applyBeanPostProcessorsBeforeInstantiation

Bean后置处理器 - InstantiationAwareBeanPostProcessor#applyBeanPostProcessorsBeforeInstantiation

在 createBean 方法中, doCreateBean 方法前, 调用了这样一句代码:

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean

// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
// 在 bean实例化之前 应用后置处理,如果后置处理返回的bean不为空,则直接返回
// 返回的是一个寡妇对象, 属性什么的, spring不会去维护
// spring不推荐开发人员使用这个接口 InstantiationAwareBeanPostProcessor
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
    return bean;
}

这是一个扩展方法, 如果返回了 bean , 那么就不走后面的创建流程了. 

要注意这里的执行时机: 对象实例化之前执行

@Nullable
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) {
                bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                if (bean != null) {
                    bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                }
            }
        }
        mbd.beforeInstantiationResolved = (bean != null);
    }
    return bean;
}

InstantiationAwareBeanPostProcessor 这个后置处理器, 不但定义了 实例化之前的处理器, 还定义了  实例化之后的处理器. 

所以, 这里如果返回的bean不为null, 还需要执行实例化之后的处理器, 来保证流程的完整性. 

在这里, 就不看实例化之后的回调了.

 

直接看 applyBeanPostProcessorsBeforeInstantiation() 方法:

@Nullable
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
        if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
            Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
            if (result != null) {
                return result;
            }
        }
    }
    return null;
}

 

首先来看一下, 这个接口:

public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {

    @Nullable
    default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        return null;
    }

 
    default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        return true;
    }

   
    @Nullable
    default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
            throws BeansException {

        return null;
    }

  
    @Deprecated
    @Nullable
    default PropertyValues postProcessPropertyValues(
            PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {

        return pvs;
    }

}

注意到, 这个接口是 继承了 BeanPostProcessor , 表示他是一个 bean 的后置处理器. 和前面章节出现过的 BeanFactory 后置处理器 是不同的

 

通过断点调试, 不难发现, 6个后置处理器中, 满足条件的就三个, 按照执行顺序排列为: 

1.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor

2.CommonAnnotationBeanPostProcessor

3.AutowiredAnnotationBeanPostProcessor

 

那接下来, 就需要看一下, 里面分别干了什么

ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor

org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter#postProcessBeforeInstantiation

@Override
@Nullable
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
    return null;
}

从这里看, 他本身都没有实现或重写这个方法, 而是由它的父类去实现的.

里面啥也没干, 直接返回了 null.

 

CommonAnnotationBeanPostProcessor

@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
    return null;
}

啥也没干

 

AutowiredAnnotationBeanPostProcessor

org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter#postProcessBeforeInstantiation

@Override
@Nullable
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
    return null;
}

他本身也没有实现这个方法, 而是父类去实现的.

里面也是啥也没干.

 

到这里, 这个后置处理器就执行完了, 大家都没干事情, 都是直接返回的 null. 所以, spring后续流程还是要走的

 

我们今天的关于Bean后置处理器 - InstantiationAwareBeanPostProcessor#postProcessPropertiesbean后置处理器的分享已经告一段落,感谢您的关注,如果您想了解更多关于@Configuration中的来声明BeanPostProcessor和BeanFactoryPostProcessor、Bean 后置处理器 - SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors、Bean后置处理器 - applyMergedBeanDefinitionPostProcessors、Bean后置处理器 - InstantiationAwareBeanPostProcessor#applyBeanPostProcessorsBeforeInstantiation的相关信息,请在本站查询。

本文标签: