Back to Javatutorial

ConfigurationClassPostProcessor(二):处理@Bean注解

docs/Spring全家桶/Spring源码分析/Spring重要机制探秘/ConfigurationClassPostProcessor(二):处理@Bean注解.md

1.0.028.4 KB
Original Source

ConfigurationClassPostProcessor ĵڶƪҪǷ spring @Bean עĴ̡

3. spring δ @Bean עģ

нģǼ spring @Bean עĴ̡

3.1 demo ׼

Ϊ˵⣬ֱϴ룺

׼ Bean:

public class BeanObj1 {
    public BeanObj1() {
        System.out.println("beanObj1Ĺ췽");
    }

    @Override
    public String toString() {
        return "BeanObj1{}";
    }
}

public class BeanObj2 {
    public BeanObj2() {
        System.out.println("beanObj2Ĺ췽");
    }

    @Override
    public String toString() {
        return "BeanObj2{}";
    }
}

ע⣺඼û Component``@Service ע⡣

׼һ࣬ͨ @Bean עķ bean

@Component
public class BeanConfigs {

    @Bean
    public BeanObj1 beanObj1() {
        return new BeanObj1();
    }

    @Bean
    public BeanObj2 beanObj2() {
        //  beanObj1() 
        beanObj1();
        return new BeanObj2();
    }

}

@ComponentScan
public class Demo02Main {

    public static void main(String[] args) {
        ApplicationContext context 
                = new AnnotationConfigApplicationContext(Demo02Main.class);
        Object obj1 = context.getBean("beanObj1");
        Object obj2 = context.getBean("beanObj2");
        System.out.println("obj1:" + obj1);
        System.out.println("obj2:" + obj2);
        System.out.println(context.getBean("beanConfigs"));
    }
}

룬¼Ҫ˵

  • BeanConfigs ʹõע @Componentһƪķ@Component Ҳ࣬ͬ @Configuration ע⣻
  • Demo02Main У AnnotationConfigApplicationContext Ϊ Demo02Mainһע @ComponentScanעûָɨ·һƪķָɨ·spring Ĭɨڰ
  • DzûֱӰ BeanConfigs עᵽУ new AnnotationConfigApplicationContext(BeanConfigs.class) һƪķ֪spring Ƚ Demo02Main ࣬ϵ @Component ע⣬Ӷɨ赽 BeanConfigs ࣬Ȼ BeanConfigsڲ @Bean ǽҲͨԵķʽ֤

ϴ룬£

beanObj1Ĺ췽
beanObj1Ĺ췽
beanObj2Ĺ췽
obj1:BeanObj1{}
obj2:BeanObj2{}
org.springframework.learn.explore.demo05.BeanConfigs@2b71e916

demo з

ע ConfigurationClassPostProcessor ĵڶƪһƪͬĴ룬ֻһʴٽϸ

3.2 ࣺConfigurationClassPostProcessor#processConfigBeanDefinitions

ֱӽ ConfigurationClassPostProcessor#processConfigBeanDefinitions £

AnnotationConfigApplicationContext#AnnotationConfigApplicationContext(Class)
 |-AbstractApplicationContext#refresh
  |-AbstractApplicationContext#invokeBeanFactoryPostProcessors
   |-PostProcessorRegistrationDelegate
      #invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory, List)
    |-PostProcessorRegistrationDelegate#invokeBeanDefinitionRegistryPostProcessors
     |-ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
      |-ConfigurationClassPostProcessor#processConfigBeanDefinitions

ʱ candidates ֻһ Ԫأ

3.2 demo02MainConfigurationClassParser#doProcessConfigurationClass

һǽ @ComponentScan עḶ́һƪϸֻջ

AnnotationConfigApplicationContext#AnnotationConfigApplicationContext(Class)
 |-AbstractApplicationContext#refresh
  |-AbstractApplicationContext#invokeBeanFactoryPostProcessors
   |-PostProcessorRegistrationDelegate
      #invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory, List)
    |-PostProcessorRegistrationDelegate#invokeBeanDefinitionRegistryPostProcessors
     |-ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
      |-ConfigurationClassPostProcessor#processConfigBeanDefinitions
       |-ConfigurationClassParser#parse(Set<BeanDefinitionHolder>)
        |-ConfigurationClassParser#parse(AnnotationMetadata, String)
          |-ConfigurationClassParser#processConfigurationClass
           |-ConfigurationClassParser#doProcessConfigurationClass

Demo02Main @ComponentScan ֮󣬿Կ beanConfigs Ѿɨ赽ˣ

beanConfigs ࣬˻н

ջǻص ConfigurationClassParser#doProcessConfigurationClassеĵ£

AnnotationConfigApplicationContext#AnnotationConfigApplicationContext(Class)
 |-AbstractApplicationContext#refresh
  |-AbstractApplicationContext#invokeBeanFactoryPostProcessors
   |-PostProcessorRegistrationDelegate
      #invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory, List)
    |-PostProcessorRegistrationDelegate#invokeBeanDefinitionRegistryPostProcessors
     |-ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
      |-ConfigurationClassPostProcessor#processConfigBeanDefinitions
       |-ConfigurationClassParser#parse(Set<BeanDefinitionHolder>)
        |-ConfigurationClassParser#parse(AnnotationMetadata, String)
          |-ConfigurationClassParser#processConfigurationClass
           |-ConfigurationClassParser#doProcessConfigurationClass
            |-ConfigurationClassParser#parse(String, String)
             |-ConfigurationClassParser#processConfigurationClass
              |-ConfigurationClassParser#doProcessConfigurationClass

ʱ ConfigurationClassParser#doProcessConfigurationClassǾͲ demo02Main beanConfigs ˡ

3.3 beanConfigsConfigurationClassParser#doProcessConfigurationClass

ConfigurationClassParser#doProcessConfigurationClass @Bean עĴ£

/**
 * ķ
 */
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, 
        SourceClass sourceClass) throws IOException {
    // 1\.  @Component ע⣬ݹ鴦ڲ࣬IJע
    ...

    // 2\. @PropertySourceע⣬IJע
    ...

    // 3\.  @ComponentScan/@ComponentScans ע⣬IJע
    ...

    // 4\. @Importע⣬IJע
    ...

    // 5\. @ImportResourceע⣬IJע
    ...

    // 6\. @Beanע
    // Ľ
    Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
    for (MethodMetadata methodMetadata : beanMethods) {
        // ӵ configClass Уٴ
        configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
    }

    // 7\. ĸ࣬ processConfigurationClass(...) һѭʱ
    ...
    return null;
}

ȡ @Bean ķõ retrieveBeanMethodMetadata(...)Ǹȥ

private Set<MethodMetadata> retrieveBeanMethodMetadata(SourceClass sourceClass) {
    AnnotationMetadata original = sourceClass.getMetadata();
    // ȡ @Bean עķ
    Set<MethodMetadata> beanMethods = original.getAnnotatedMethods(Bean.class.getName());
    ...
    return beanMethods;
}

ٸȥյõ StandardAnnotationMetadata#getAnnotatedMethods:

public Set<MethodMetadata> getAnnotatedMethods(String annotationName) {
    Set<MethodMetadata> annotatedMethods = null;
    if (AnnotationUtils.isCandidateClass(getIntrospectedClass(), annotationName)) {
        try {
            // 1\. ͨĻȡеķ
            Method[] methods = ReflectionUtils.getDeclaredMethods(getIntrospectedClass());
            for (Method method : methods) {
                // 2\. жǷ @Bean ע
                if (isAnnotatedMethod(method, annotationName)) {
                    if (annotatedMethods == null) {
                        annotatedMethods = new LinkedHashSet<>(4);
                    }
                    annotatedMethods.add(new StandardMethodMetadata(
                        method, this.nestedAnnotationsAsMap));
                }
            }
        }
        catch (Throwable ex) {
            throw new IllegalStateException();
        }
    }
    return annotatedMethods != null ? annotatedMethods : Collections.emptySet();
}

ܺ⣬ؼ

  1. ͨȡз
  2. õķһжϸ÷Ƿ @Bean ע⣻

beanConfigs еڻȡˣ ConfigurationClass beanMethods ԣ

3.4 @Bean ǵķص BeanDefinitionMap

ȡ beanMethod ʱֻ ConfigurationClass beanMethods Уûмص beanFactory BeanDefinitionMap УС̽Ǻʱ뵽 BeanDefinitionMap С

ǵ ConfigurationClassPostProcessor#processConfigBeanDefinition ôһд룺

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
    ...
    // ν
    //  @Import ࡢд@Beanķ@ImportResource ԴתBeanDefinition
    this.reader.loadBeanDefinitions(configClasses);
    ...
}

Ǽ BeanDefinition ĵط @Import ࡢд @Bean ķ@ImportResource Դת BeanDefinitionصע @Bean Ĵ£

ConfigurationClassBeanDefinitionReader

    public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
        TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
        //  configurationModel
        for (ConfigurationClass configClass : configurationModel) {
            loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
        }
    }

    /**
     * ظ ConfigurationClass  BeanDefinition
     * 1\. @Import 
     * 2\. е @Bean 
     * 3\. @ImportResource Դ
     * 4\. @Import  ImportBeanDefinitionRegistrar
     */
    private void loadBeanDefinitionsForConfigurationClass(
            ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {

        if (trackedConditionEvaluator.shouldSkip(configClass)) {
            ...
        }

        //  @Import 
        if (configClass.isImported()) {
            registerBeanDefinitionForImportedConfigurationClass(configClass);
        }
        //  @Bean 
        for (BeanMethod beanMethod : configClass.getBeanMethods()) {
            loadBeanDefinitionsForBeanMethod(beanMethod);
        }
        //  @ImportResource Դ
        loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
        //  @Import  ImportBeanDefinitionRegistrar
        loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
    }

    /**
     *  @Bean 
     * 1\. BeanDefinitionbeanMethod ʹõ ConfigurationClassBeanDefinition
     * 2\.  @Bean ĸԣõ BeanDefinition 
     * 3\.  BeanDefinition עᵽ beanFactory 
     */
    private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
        ConfigurationClass configClass = beanMethod.getConfigurationClass();
        MethodMetadata metadata = beanMethod.getMetadata();
        String methodName = metadata.getMethodName();

        ...

        // 1\. beanMethodʹõConfigurationClassBeanDefinition
        ConfigurationClassBeanDefinition beanDef = 
                new ConfigurationClassBeanDefinition(configClass, metadata);
        beanDef.setResource(configClass.getResource());
        beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));

        // 2\.  @Bean ĸ
        if (metadata.isStatic()) {
            // ̬ @Bean 
            if (configClass.getMetadata() instanceof StandardAnnotationMetadata) {
                beanDef.setBeanClass(
                    ((StandardAnnotationMetadata) configClass.getMetadata()).getIntrospectedClass());
            }
            else {
                beanDef.setBeanClassName(configClass.getMetadata().getClassName());
            }
            beanDef.setUniqueFactoryMethodName(methodName);
        }
        else {
            // ͨ @Bean 
            beanDef.setFactoryBeanName(configClass.getBeanName());
            beanDef.setUniqueFactoryMethodName(methodName);
        }

        if (metadata instanceof StandardMethodMetadata) {
            beanDef.setResolvedFactoryMethod(
                ((StandardMethodMetadata) metadata).getIntrospectedMethod());
        }

        beanDef.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
        beanDef.setAttribute(
                org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor.
                SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);

        AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);

        Autowire autowire = bean.getEnum("autowire");
        if (autowire.isAutowire()) {
            beanDef.setAutowireMode(autowire.value());
        }

        boolean autowireCandidate = bean.getBoolean("autowireCandidate");
        if (!autowireCandidate) {
            beanDef.setAutowireCandidate(false);
        }

        String initMethodName = bean.getString("initMethod");
        if (StringUtils.hasText(initMethodName)) {
            beanDef.setInitMethodName(initMethodName);
        }

        String destroyMethodName = bean.getString("destroyMethod");
        beanDef.setDestroyMethodName(destroyMethodName);

        ...

        // 3\. BeanDefinitionעᵽbeanFactory
        this.registry.registerBeanDefinition(beanName, beanDefToRegister);
    }

ConfigurationClassBeanDefinitionReader#loadBeanDefinitions ֵմ ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForBeanMethodⲿ߼£

  1. configClass ϣÿ configClass Definitions ش
  2. configClass Definitions شʱһ @Import/@Bean/@ImportResource ע⣬Сǽע @Bean Ĵ
  3. @Bean ʱȴ BeanDefinition(@Bean Ӧ BeanDefinition ConfigurationClassBeanDefinition@Bean ԣõ BeanDefinition Уǰ BeanDefinition עᵽ beanFactory .

ˣִ ConfigurationClassBeanDefinitionReader#loadBeanDefinitions BeanDefinition ͼص beanFactory ˣӦ BeanDefinition ConfigurationClassBeanDefinition.

3.5 @Bean ʵ

ʵĴͬͨ @Component һ£ͬͨ @Component õǹ췽 @Bean ʹõ factoryMethod£

AbstractAutowireCapableBeanFactory#createBeanInstance

/**
 * ʵĴʽ
 * 1\. ʹ instanceSupplierSupplierjava8ṩ࣬Դһlambdaʽ
 * 2\. ʹù @Bean עӦķ
 * 3\. ʹõǹ췽ע룬췽 @Autowired ע
 * 4\. 췽ע룬޲ι죬Ҳвι
 *
 */
protected BeanWrapper createBeanInstance(String beanName, 
        RootBeanDefinition mbd, @Nullable Object[] args) {
    // ȷѾ˴ class
    Class<?> beanClass = resolveBeanClass(mbd, beanName);
    ...

    // ǷbeanSupplierSupplierjava8ṩ࣬Դһlambdaʽ
    //  AbstractBeanDefinition#setInstanceSupplier ָ
    Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
    if (instanceSupplier != null) {
        return obtainFromSupplier(instanceSupplier, beanName);
    }
    if (mbd.getFactoryMethodName() != null) {
        // ùʵ
        return instantiateUsingFactoryMethod(beanName, mbd, args);
    }
    // Ƿһ
    boolean resolved = false;
    // Ƿù캯ע
    boolean autowireNecessary = false;
    ...
    if (resolved) {
        if (autowireNecessary) {
            return autowireConstructor(beanName, mbd, null, null);
        }
        else {
            // ޲ι캯
            return instantiateBean(beanName, mbd);
        }
    }
    // Candidate constructors for autowiring?
    // жǷвι캯
    Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(
            beanClass, beanName);
    if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
            mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
        return autowireConstructor(beanName, mbd, ctors, args);
    }
    ctors = mbd.getPreferredConstructors();
    if (ctors != null) {
        // 캯ע
        return autowireConstructor(beanName, mbd, ctors, null);
    }
    // ޲ι캯
    return instantiateBean(beanName, mbd);
}

Ӵspring ʵķʽ 4 ֣

  1. ʹ instanceSupplier``Supplier java8 ṩ࣬Դһ lambda ʽ
  2. ʹù @Bean עӦķ
  3. ʹõǹ췽ע룬췽 @Autowired ע
  4. 췽ע룬޲ι죬Ҳвι

Ҫע @Bean ʵʽҲǹʵʽǽȥ£

public BeanWrapper instantiateUsingFactoryMethod(String beanName, 
             RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
    BeanWrapperImpl bw = new BeanWrapperImpl();
    this.beanFactory.initBeanWrapper(bw);
    Object factoryBean;
    Class<?> factoryClass;
    boolean isStatic;
    String factoryBeanName = mbd.getFactoryBeanName();
    if (factoryBeanName != null) {
        factoryBean = this.beanFactory.getBean(factoryBeanName);
        factoryClass = factoryBean.getClass();
        isStatic = false;
    }
    ...

    Method factoryMethodToUse = null;
    ArgumentsHolder argsHolderToUse = null;
    Object[] argsToUse = null;
    //  factoryMethod IJ
    if (explicitArgs != null) {
        argsToUse = explicitArgs;
    }
    else {
        ...
    }

    if (factoryMethodToUse == null || argsToUse == null) {
        factoryClass = ClassUtils.getUserClass(factoryClass);
        List<Method> candidates = null;
        if (mbd.isFactoryMethodUnique) {
            if (factoryMethodToUse == null) {
                factoryMethodToUse = mbd.getResolvedFactoryMethod();
            }
            if (factoryMethodToUse != null) {
                candidates = Collections.singletonList(factoryMethodToUse);
            }
        }
        // ʡ˺ö
        ...
    }
    bw.setBeanInstance(instantiate(beanName, mbd, 
            factoryBean, factoryMethodToUse, argsToUse));
    return bw;
}

ϷǾĴ룬ԭȽ϶࣬󲿷ִڴ argsToUse factoryMethodToUse ϸڷdz࣬ͲչˣҪע¼

  1. factoryBean @Bean ʵ beanConfig;
  2. factoryMethodToUse: ʵõķҲDZ @Bean עķ BeanConfigs#beanObj1;
  3. argsToUse @Bean עķҪõIJ BeanConfigs#beanObj1 ûָ null;

ʵıʵʽҲ뵽ˣʵˣǵ÷ʵˣ

ConstructorResolver#instantiate(...)

private Object instantiate(String beanName, RootBeanDefinition mbd,
        @Nullable Object factoryBean, Method factoryMethod, Object[] args) {
    try {

        return this.beanFactory.getInstantiationStrategy().instantiate(
                mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args);
    }
    catch (Throwable ex) {
        ...
    }
}

SimpleInstantiationStrategy#instantiate(...)

@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
        @Nullable Object factoryBean, final Method factoryMethod, Object... args) {
    try {
        ...
        try {
            currentlyInvokedFactoryMethod.set(factoryMethod);
            // ൱ڵ beanConfigs.beanObj1()
            Object result = factoryMethod.invoke(factoryBean, args);
            if (result == null) {
                result = new NullBean();
            }
            return result;
        }
        finally {
            ...
        }
    }
    catch (...) {
        ...
    }
}

SimpleInstantiationStrategy#instantiate(...) нзʵˣ

ʵɺ󣬺ע롢ʼȶͨ spring bean һ£Ͳٷˡ

3.6 @Configuration @Bean ʹ

@Component @Bean ʹʱĴ

@Component
public class BeanConfigs {
    @Bean
    public Xxx xxx() {
        ...
    }
}

ʵϣʹõ @Configuration @Bean ϣ

@Configuration
public class BeanConfigs {
    @Bean
    public Xxx xxx() {
        ...
    }
}

ǰʹõ @Component кβأǾ¡

1. demo ׼

demo ׼

//@Component
@Configuration
public class BeanConfigs {

    @Bean
    public BeanObj1 beanObj1() {
        return new BeanObj1();
    }

    @Bean
    public BeanObj2 beanObj2() {
        //  beanObj1() 
        beanObj1();
        return new BeanObj2();
    }

}

demo ֻǽ @Component 滻Ϊ @Configurationִ££

beanObj1Ĺ췽
beanObj2Ĺ췽
obj1:BeanObj1{}
obj2:BeanObj2{}
org.springframework.learn.explore.demo02.BeanConfigs$$EnhancerBySpringCGLIB$$dca1c55b@75c072cb

ǽ֮ǰִҲ

Ƚϣͬ

  1. beanObj1 Ĺ췽һΣ
  2. beanConfigs Ӧ BeanConfigs$$EnhancerBySpringCGLIB$$dca1c55b@75c072cb˵һʹ cglib

ʵϣͬ㶼ԹΪһԭspring beanConfigs ˴ BeanConfigs#beanObj1 ʵʵõǴ **spring Ա @Configuration ǵ cglib **

ôôеأǼ̽

2. ĴConfigurationClassPostProcessor#enhanceConfigurationClasses

һƪĿƪǾᵽ ConfigurationClassPostProcessor ִʱõprocessConfigBeanDefinitions(...) enhanceConfigurationClasses(...)``processConfigBeanDefinitions(...) spring @Import``@Configuration עĽǰѾˣ enhanceConfigurationClasses(...) DZ @Configuration ǵĹؼڣ

enhanceConfigurationClasses(...) £

ConfigurationClassPostProcessor#enhanceConfigurationClasses

public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
    Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
    for (String beanName : beanFactory.getBeanDefinitionNames()) {
        BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
        Object configClassAttr = beanDef.getAttribute(
            ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE);
        ...
        // 1\. жǷΪһȫ
        if (ConfigurationClassUtils.CONFIGURATION_CLASS_FULL.equals(configClassAttr)) {
            ...
            configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
        }
    }
    // ȫࣺ
    ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
    for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
        AbstractBeanDefinition beanDef = entry.getValue();
        beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
        //  BeanClass
        Class<?> configClass = beanDef.getBeanClass();
        // 2\.  enhancedClass
        Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
        if (configClass != enhancedClass) {
            // 3\.  BeanClassֵΪenhancedClass
            beanDef.setBeanClass(enhancedClass);
        }
    }
}

Ƚϼ򵥣£

  1. жǷΪȫ࣬һƪУᵽ spring Ѵ @Configuration ע proxyBeanMethods != false Ϊ Full ࣬ǸǰıжϷΪȫ࣬ԣʱ beanConfigs һȫࣻ
  2. ȫ࣬ configClass ɶӦ enhancedClass
  3. ɵ enhancedClass õ beanDefinition beanClass С

ִ˷beanConfigs Ӧ beanDefinition beanClass Ǵˣ

beanConfigs ʵˡ

3. ִдķ

ɴ󣬴ִеأ spring ִ beanConfigs.beanObj1() أ˵Ҫ̸ cglib ķִˡֱɣ enhancer.enhance(configClass, this.beanClassLoader)

public Class<?> enhance(Class<?> configClass, @Nullable ClassLoader classLoader) {
    if (EnhancedConfiguration.class.isAssignableFrom(configClass)) {
        return configClass;
    }
    // newEnhancer(...) ǹؼ
    Class<?> enhancedClass = createClass(newEnhancer(configClass, classLoader));
    return enhancedClass;
}

private static final Callback[] CALLBACKS = new Callback[] {
        // ֤ @Bean ĵ
        new BeanMethodInterceptor(),
        new BeanFactoryAwareMethodInterceptor(),
        NoOp.INSTANCE
};

//  CallbackFilterĶΪCallback
private static final ConditionalCallbackFilter CALLBACK_FILTER 
        = new ConditionalCallbackFilter(CALLBACKS);

// cglibǿ
private Enhancer newEnhancer(Class<?> configSuperClass, @Nullable ClassLoader classLoader) {
    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(configSuperClass);
    enhancer.setInterfaces(new Class<?>[] {EnhancedConfiguration.class});
    enhancer.setUseFactory(false);
    enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
    enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));
    // callbackFilter
    enhancer.setCallbackFilter(CALLBACK_FILTER);
    enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
    return enhancer;
}

cglib ݣ spring aop ֮ cglib һϸˣⲻٷֱ˵ۣcglib ִдʱִе Enhancer callbackFilter Ե MethodInterceptor#intercept CALLBACKS е BeanMethodInterceptorǾݣ

ConfigurationClassEnhancer.BeanMethodInterceptor

private static class BeanMethodInterceptor implements MethodInterceptor, ConditionalCallback {
    @Override
    @Nullable
    public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
                MethodProxy cglibMethodProxy) throws Throwable {
        ConfigurableBeanFactory beanFactory = getBeanFactory(enhancedConfigInstance);
        String beanName = BeanAnnotationHelper.determineBeanNameFor(beanMethod);
        ...
        // ǵõǰ factoryMethod ֱӵøķ
        if (isCurrentlyInvokedFactoryMethod(beanMethod)) {
            // øķҲĿ귽
            return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
        }
        // ֱӻȡ beanFactoryеĶ
        return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
    }

    private Object resolveBeanReference(Method beanMethod, Object[] beanMethodArgs,
            ConfigurableBeanFactory beanFactory, String beanName) {
        try {
            ...
            // õĵ beanFactory.getBean(...) ѾdzϤ
            Object beanInstance = (useArgs ? beanFactory.getBean(beanName, beanMethodArgs) :
                    beanFactory.getBean(beanName));
            ...
            return beanInstance;
        }
        finally {
            ...
        }
    }

    /**
     * жִܷеǰ MethodInterceptor
     */
    @Override
    public boolean isMatch(Method candidateMethod) {
        return (candidateMethod.getDeclaringClass() != Object.class &&
                !BeanFactoryAwareMethodInterceptor.isSetBeanFactory(candidateMethod) &&
                BeanAnnotationHelper.isBeanAnnotated(candidateMethod));
    }
}

BeanMethodInterceptor ʵ MethodInterceptor ConditionalCallback``ConditionalCallback#isMatch жϵǰ MethodInterceptor ִܷУMethodInterceptor#intercept ִеķݣִ߼Ϊ

  1. ֱӵõǰ factoryMethod ֱӵøķҲ beanConfigs.beanObj1()̻ʵ beanObj1 ʱã
  2. ֱӵõǰ factoryMethod ڱķеã beanFactory.getBean(...) ȡ bean̻ʵ beanObj1 ʱ á

ϾΪʲô beanObj1 Ĺ췽ֻһΣԼΪʲô beanConfigs Ǵԭˡ

һ䣬@ConfigurationproxyBeanMethods() ѡǷĴĬֵ trueã

@Configuration(proxyBeanMethods=false)
public class BeanConfigs {
    ...
}

BeanConfigs Ͳдˣнͬ @Component עһͲչʾˡ

4. С

1. ڲҲܱ

ʾУõģ

    @Bean
    public BeanObj2 beanObj2() {
        //  beanObj1() 
        beanObj1();
        return new BeanObj2();
    }

beanObj2() е beanObj1()ڲãbeanObj1() Ҳܱ

شcglib ĵ÷֣

@Override
public Object intercept(Object proxyObj, Method method, Object[] objects, 
            MethodProxy proxy) throws Throwable {
    // 1 ʹĿֱӵĿķ
    // return proxy.invoke(target, objects);
    // 2 ʹô󣬵丸ķ
    return proxy.invokeSuper(proxyObj, objects);
}

beanObj2() ĵʹ2Ҳʹô beanObj2()``beanObj2() this Ϊ

beanObj2() ֱӵ beanObj1()൱ʹô beanObj1()Ȼܱˡ

ӡУڲòܱΪ spring ڴ Aop ʱʹõǷ 1 ĵ÷ʽʱ this Ϊԭʼ󣬵Ȼܱˡ

2. ˽ע룿

磬һ BeanObj3:

@Component
public class BeanObj3 {

    public BeanObj3() {
        System.out.println("beanObj3Ĺ췽");
    }

    @Override
    public String toString() {
        return "BeanObj3{}";
    }
}

Ȼ BeanConfigs ע룺

@Configuration
public class BeanConfigs {

    @Autowired
    private BeanObj3 beanObj3;

    @Bean
    public BeanObj1 beanObj1() {
        return new BeanObj1();
    }

    @Bean
    public BeanObj2 beanObj2() {
        //  beanObj1() 
        beanObj1();
        System.out.println("beanObj3" + this.beanObj3);
        return new BeanObj2();
    }

}

BeanConfigs Զע beanObj3 ԣȻ beanObj2() ִӡ beanObj3 ԡУ£

Կע beanObj3 ҲܻȡˡиˣbeanObj3 Ŀģ this ǴѲɴõĿ˽ԣ

ȣӵ beanFactory beanDefinitionMap е BeanConfigs$$EnhancerBySpringCGLIB$$Xxx ࣩࣨ BeanConfigsspring ڽעʱҵǰ༰丸еעԽע룬ˣȻӵ spring е BeanConfigs$$EnhancerBySpringCGLIB$$XxxBeanConfigs е beanObj3 һᱻע룬ԭ cglib ĴϵBeanConfigs BeanConfigs$$EnhancerBySpringCGLIB$$Xxx ĸࡣ

BeanConfigs$$EnhancerBySpringCGLIB$$Xxx ̳ beanObj3 ֱӿнɣ

յõ beanConfigs 󣬿Կһ beanObj3 ԣһֵ

3.7 ܽ

Ҫ ConfigurationClassPostProcessor @Bean עḶ́ܽ£

  1. ࣬ͨȡб @Bean ǵķ
  2. Щװһ BeanDefinition עᵽ beanFactory УӦ BeanDefinition Ϊ ConfigurationClassBeanDefinition
  3. ȫ࣬ cglib
  4. ʵʱʹ÷öӦķʵõʵspring ٶע롢ʼȣ
  5. ڱ @Bean еõǰ @Bean ʱǰ @Bean ڵȫ࣬ȥ beanFactory вҶӦ bean(ҵĹǣҵ򷵻أҲ򴴽ٷأ**ص bean spring bean ) cglib ɣǰ @Bean ڵ಻ȫ࣬ᰴͨķã bean ʵأص bean û spring bean **

ĵķ͵ˣǼ ConfigurationClassPostProcessor ע̡


ԭӣhttps://my.oschina.net/funcy/blog/4492878 ߸ˮƽд֮ӭָԭףҵתϵ߻Ȩҵתע