Spring @Configuration 和 @Component 区别

@Configuration 和 @Component 区别:

  • @Configuration和@Component都是Spring框架中非常重要的注解,它们在Spring的依赖注入和组件扫描中扮演着关键角色。然而,它们在功能和使用上存在一些重要的区别。

  • @Component是一个通用的注解,用于标识一个类作为组件被Spring框架扫描和管理。这个注解可以用于任意的普通Java类、接口、抽象类等。当使用@Component注解标记一个类后,Spring容器将会自动实例化这个类,并将其纳入到Spring上下文中进行管理。

  • @Configuration注解则用于指示一个类是Spring的配置类。配置类包含了一个或多个用@Bean注解标记的方法,用于定义和配置Spring容器中的bean。@Configuration注解通常与@Bean注解一起使用,以提供灵活且可扩展的配置管理。

总结来说,@Component主要用于标识普通组件,并由Spring容器自动管理其实例化过程,而@Configuration主要用于定义和配置Spring容器中的bean,通常与@Bean注解一起使用,提供灵活且可扩展的配置管理。

情景分析:

@Configuration
public class JavaConfiguration {
}
@Component
public class JavaComponent {
}

Spring项目启动,从容器内打印该类可发现:

JavaConfiguration = com.study.config.JavaConfiguration$$SpringCGLIB$$
JavaComponent =   com.study.config.JavaComponent 

此处可以发现JavaConfiguration 是被代理的类,但是仔细看:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
    String value() default "";
}

Configuration 和 Component 本质还是一样的。Configuration 注解的类被代理肯定是被Spring去增强了。

Spring 容器在启动时,会加载默认的一些 PostPRocessor,其中就有 ConfigurationClassPostProcessor,这个后置处理程序专门处理带有 @Configuration 注解的类,这个程序会在 bean 定义加载完成后,在 bean 初始化前进行处理。主要处理的过程就是使用 cglib 动态代理增强类,而且是对其中带有 @Bean 注解的方法进行处理。

在 ConfigurationClassPostProcessor 中的 postProcessBeanFactory 方法中调用了下面的方法:

/**
 * Post-processes a BeanFactory in search of Configuration class BeanDefinitions;
 * any candidates are then enhanced by a {@link ConfigurationClassEnhancer}.
 * Candidate status is determined by BeanDefinition attribute metadata.
 * @see ConfigurationClassEnhancer
 */
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
    Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<String, AbstractBeanDefinition>();
    for (String beanName : beanFactory.getBeanDefinitionNames()) {
        BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
        if (ConfigurationClassUtils.isFullConfigurationClass(beanDef)) {
            //省略部分代码
            configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
        }
    }
    if (configBeanDefs.isEmpty()) {
        // nothing to enhance -> return immediately
        return;
    }
    ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
    for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
        AbstractBeanDefinition beanDef = entry.getValue();
        // If a @Configuration class gets proxied, always proxy the target class
        beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
        try {
            // Set enhanced subclass of the user-specified bean class
            Class<?> configClass = beanDef.resolveBeanClass(this.beanClassLoader);
            Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
            if (configClass != enhancedClass) {
                //省略部分代码
                beanDef.setBeanClass(enhancedClass);
            }
        }
        catch (Throwable ex) {
            throw new IllegalStateException(
              "Cannot load configuration class: " + beanDef.getBeanClassName(), ex);
        }
    }
}

在方法的第一次循环中,查找到所有带有 @Configuration 注解的 bean 定义,然后在第二个 for 循环中,通过enhancer.enhance方法对类进行增强,然后将注入类替换。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值