@Configuration注解简介说明

欣喜 Spring 发布时间:2025-03-11 10:21:17 阅读数:13552 1
下文笔者讲述@Configuration注解的相关说明,如下所示

@Configuration注解简介

@Configuration是使用在类上的注解
  表示一个对象是Bean定义的来源
@Configuration类通过@Bean注解方法声明Bean

@Configuration类的功能:
   使用@Configuration注解的功能:
     替代Spring中applicationContext.xml文件
	  使配置更加灵活和方便 
   当某个类标注@Configuration注解时
    表示这个类是Spring一个配置类
	能自动注册到IOC容器并进行实例化
 
@Configuration
class AppConfig {
  @Bean
  public Person person() {
    return new Person() ;
  }
}
AppConfig是一个配置类
  在该类中通过@Bean标注方法注册Bean对象   
 
@Component
static class AppConfig {
  @Bean
  public Person person() {
    return new Person() ;
  }
}
// 测试是否能够获取Person bean对象
try (GenericApplicationContext context = new GenericApplicationContext()) {
  context.registerBean(AppConfig.class) ;
  // ...
  System.out.println(context.getBean(Person.class)) ;
}
 
 
使用@Configuration替换
 
@Configuration
static class AppConfig {
  @Bean
  public Person person() {
    return new Person() ;
  }
  @Bean
  public Date d1() {
    System.out.println(person()) ;
    return new Date() ;
  }
  @Bean
  public Date d2() {
    System.out.println(person()) ;
    return new Date() ;
  }
}

ConfigurationClassPostProcessor 实现原理

Spring提供了一个ConfigurationClassPostProcessor处理器
  注册@Configuration注解。
该处理器是一个BeanFactoryPostProcessor 

处理配置类

public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor {
  public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
    // ...
    // 处理配置类bean
    processConfigBeanDefinitions(registry);
  }
  public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
    // 获取所有的bean
    String[] candidateNames = registry.getBeanDefinitionNames();
    // 遍历
    for (String beanName : candidateNames) {
      BeanDefinition beanDef = registry.getBeanDefinition(beanName) ;
      // 判断当前的bean是否有ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE属性
      // 默认都是没有的,所以这里进入到else if 中
      if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
        // 打印日志
      } 
      // 在checkConfigurationClassCandidate会处理配置类的相应属性
      else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
        configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
      }
    }
    // ...
  }
}

ConfigurationClassUtils

abstract class ConfigurationClassUtils {
  public static final String CONFIGURATION_CLASS_FULL = "full";
  public static final String CONFIGURATION_CLASS_LITE = "lite";
  public static boolean checkConfigurationClassCandidate(
      BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
    // 省去无关代码
    // 获取到当前配置类的所有注解信息
    AnnotationMetadata metadata = AnnotationMetadata.introspect(beanClass) ;
    // 获取注解类@Configuration信息
    Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
    if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
      // 如果@Configuration中的proxyBeanMethods属性为true,
	  那么就将当前配置类对应的BeanDefinition设置属性
      // 标记为true,其实这里的目的就是要不要创建代理,如果为true创建代理
      beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
    }
    // 不创建代理
    else if (config != null || isConfigurationCandidate(metadata)) {
      beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
    }
    else {
      return false;
    }
  }
}

为配置类生成代理

public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor {
  public void postProcessBeanFactory(ConfigurablelistableBeanFactory beanFactory) {
    // ...
    // 增强配置类,创建代理
    enhanceConfigurationClasses(beanFactory);
  }
  public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
    Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
    for (String beanName : beanFactory.getBeanDefinitionNames()) {
      BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
      // 获取设置的标记属性,要么是full,要么是lite
      Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE);
      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();
      // 确定配置类的class
      Class<?> configClass = beanDef.getBeanClass();
      // 创建代理
      Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
      if (configClass != enhancedClass) {
        beanDef.setBeanClass(enhancedClass);
      }
    }
  }
}

 
使用ConfigurationClassEnhancer#enhance 创建目标配置类的代理对象。


class ConfigurationClassEnhancer {
  private static final Callback[] CALLBACKS = new Callback[] {
      new BeanMethodInterceptor(),
      new BeanFactoryAwareMethodInterceptor(),
      NoOp.INSTANCE
  }
  public Class<?> enhance(Class<?> configClass, @Nullable ClassLoader classLoader) {
    Class<?> enhancedClass = createClass(newEnhancer(configClass, classLoader));
    return enhancedClass;
  }
  private Enhancer newEnhancer(Class<?> configSuperClass, @Nullable ClassLoader classLoader) {
    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(configSuperClass);
    // 设置生成的子类要实现的接口,该接口实现了BeanFactoryAware,
    // 所以容器在实例化初始化该代理对象的时候会自动注入当前容器的BeanFactory对象。
    enhancer.setInterfaces(new Class<?>[] {EnhancedConfiguration.class});
    enhancer.setUseFactory(false);
    enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
    // 这里有个作用就是为当前的代理bean添加BeanFactory类型的字段。
    enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));
    enhancer.setCallbackFilter(CALLBACK_FILTER);
    enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
    return enhancer;
  } 
  private Class<?> createClass(Enhancer enhancer) {
    Class<?> subclass = enhancer.createClass();
    Enhancer.registerStaticCallbacks(subclass, CALLBACKS);
    return subclass;
  }
}
 

拦截配置方法

private static class BeanMethodInterceptor implements MethodInterceptor {
  public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
          MethodProxy cglibMethodProxy) throws Throwable {
    ConfigurableBeanFactory beanFactory = getBeanFactory(enhancedConfigInstance);
    // 获取当前@Bean注解的方法名(也就是对应的BeanName)
    String beanName = BeanAnnotationHelper.determineBeanNameFor(beanMethod);
    // ...
    // 从容器中查找对应的bean(也就是你调用的那个方法创建的bean对象)
    return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
  }
  private Object resolveBeanReference(Method beanMethod, Object[] beanMethodArgs,
        ConfigurableBeanFactory beanFactory, String beanName) {
    // 获取bean实例
    Object beanInstance = (useArgs ? beanFactory.getBean(beanName, beanMethodArgs) :
            beanFactory.getBean(beanName));
    // ...
    return beanInstance;
  }
}
 
版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。

本文链接: https://www.Java265.com/JavaFramework/Spring/202503/8368.html

最近发表

热门文章

好文推荐

Java265.com

https://www.java265.com

站长统计|粤ICP备14097017号-3

Powered By Java265.com信息维护小组

使用手机扫描二维码

关注我们看更多资讯

java爱好者