关于@Configuration注解的思考

package org.spring.boot.example.config;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public final class RootConfig implements InitializingBean {

    public RootConfig() {
        System.out.println("============");
    }

    @Autowired
    private ApplicationContext applicationContext;

    @Bean
    public MyBeanDefinitionRegistryPostProcessor myBeanDefinitionRegistryPostProcessor() {
        return new MyBeanDefinitionRegistryPostProcessor();
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        String id = applicationContext.getId();
        System.out.println("id = " + id);
    }
}

package org.spring.boot.example.config;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;

public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {

    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

    }
}

以上这个类存在两个问题,你知道吗?又知道如何解决吗?以及其中的问题。

首先,对于@Configuration注解的类不可以包含final关键字,通常IDE会警告,原因在与包含@Configuration的类会被增强,而所谓的增强其实就是生成CGLIB动态代理,而CGLIB动态代理就是在运行时生成一个目标的子类,而加有final的类是不能够被继承的,没有子类。去掉final关键字。
在这里插入图片描述
其次,运行时会报空指针异常。如下图所示
在这里插入图片描述
处理方法也简单,添加一个static关键字,如下图所示
在这里插入图片描述
@Configuration注解的类中定义了包含@Bean的方法用于配置相关的bean,但是首先这个@Configuration注解的类也会作为一个bean,称为factoryBean,如果这个方法是静态的,在实例化对应的类的时候不需要实例化这个factoryBean,因为静态方法的反射不需要对象,而非静态方法是需要对象的,所谓非静态方法对应的bean的实例化就会导致对应factoryBean的实例化。在这个案例当中,MyBeanDefinitionRegistryPostProcessor实例化的非常早,远在绝大多数的BeanPostProcessor的实例化之前。而MyBeanDefinitionRegistryPostProcessor的实例化导致RootConfig类型Bean的创建,在此过程中,已经实例化的BeanPostProcessor类型Bean会起作用,而其中用于处理@Autowired注解的AutowiredAnnotationBeanPostProcessor并没有实例化,所以此处的applicationContext并不会被注入。也就说,由于MyBeanDefinitionRegistryPostProcessor实例化导致了RootConfig的提前实例化和初始化,通过添加static就可以避免了。

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.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lang20150928

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值