spring源码分析----@Bean如何解析的

ConfigurationClassBeanDefinitionReader的loadBeanDefinitionsForConfigurationClass方法

 

 

 

 

 

@Bean是写在被@Configuration标记的类中,然后spring启动之后,对该类进行动态代理,然后在手动调用被@Bean注解的方法时,会进入拦截,进入如下代码中:

看Debugger中的调用堆栈,调用Orc(),直接进入intercept

 

 

ConfigurationClassEnhancer类中的内部类BeanMethodInterceptor的部分代码如下,主要用于处理@Bean方法调用的拦截
/**
 * Intercepts the invocation of any {@link Bean}-annotated methods in order to ensure proper
 * handling of bean semantics such as scoping and AOP proxying.
 * @see Bean
 * @see ConfigurationClassEnhancer
 */
private static class BeanMethodInterceptor implements MethodInterceptor, ConditionalCallback {

   /**
    * Enhance a {@link Bean @Bean} method to check the supplied BeanFactory for the
    * existence of this bean object.
    * @throws Throwable as a catch-all for any exception that may be thrown when invoking the
    * super implementation of the proxied method i.e., the actual {@code @Bean} method
    */
   @Override
   @Nullable
   public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
            MethodProxy cglibMethodProxy) throws Throwable {

      ConfigurableBeanFactory beanFactory = getBeanFactory(enhancedConfigInstance);
      String beanName = BeanAnnotationHelper.determineBeanNameFor(beanMethod);

      // Determine whether this bean is a scoped-proxy
      if (BeanAnnotationHelper.isScopedProxy(beanMethod)) {
         String scopedBeanName = ScopedProxyCreator.getTargetBeanName(beanName);
         if (beanFactory.isCurrentlyInCreation(scopedBeanName)) {
            beanName = scopedBeanName;
         }
      }

      // To handle the case of an inter-bean method reference, we must explicitly check the
      // container for already cached instances.

      // First, check to see if the requested bean is a FactoryBean. If so, create a subclass
      // proxy that intercepts calls to getObject() and returns any cached bean instance.
      // This ensures that the semantics of calling a FactoryBean from within @Bean methods
      // is the same as that of referring to a FactoryBean within XML. See SPR-6602.
      if (factoryContainsBean(beanFactory, BeanFactory.FACTORY_BEAN_PREFIX + beanName) &&
            factoryContainsBean(beanFactory, beanName)) {
         Object factoryBean = beanFactory.getBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName);
         if (factoryBean instanceof ScopedProxyFactoryBean) {
            // Scoped proxy factory beans are a special case and should not be further proxied
         }
         else {
            // It is a candidate FactoryBean - go ahead with enhancement
            return enhanceFactoryBean(factoryBean, beanMethod.getReturnType(), beanFactory, beanName);
         }
      }

      if (isCurrentlyInvokedFactoryMethod(beanMethod)) {
         // The factory is calling the bean method in order to instantiate and register the bean
         // (i.e. via a getBean() call) -> invoke the super implementation of the method to actually
         // create the bean instance.
         if (logger.isInfoEnabled() &&
               BeanFactoryPostProcessor.class.isAssignableFrom(beanMethod.getReturnType())) {
            logger.info(String.format("@Bean method %s.%s is non-static and returns an object " +
                        "assignable to Spring's BeanFactoryPostProcessor interface. This will " +
                        "result in a failure to process annotations such as @Autowired, " +
                        "@Resource and @PostConstruct within the method's declaring " +
                        "@Configuration class. Add the 'static' modifier to this method to avoid " +
                        "these container lifecycle issues; see @Bean javadoc for complete details.",
                  beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName()));
         }
         return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
      }

      return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
   }

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值