这是beanFactory中常见的一些后处理器:

其中这俩个属于bean后处理器:
internalAutowiredAnnotationProcessor解析@Autowired、@Value
internalCommonAnnotationProcessor解析@Resource、@PostConstruct、@PreDestroy
Bean后处理器的作用:为Bean生命周期各个阶段提供扩展。
下面让我来演示一下bean后处理器的作用:
首先看一下基础代码:
public class a04Application {
    public static void main(String[] args) {
        //1
        //GenericApplicationContext是一个干净的容器,”干净“指的是没有添加额外的beanFactory后处理器和bean后处理器
        GenericApplicationContext context = new GenericApplicationContext();
 
        //用原始方法注册三个bean
        context.registerBean("bean1", Bean1.class);
        context.registerBean("bean2", Bean2.class);
        context.registerBean("bean3", Bean3.class);
        //初始化容器
        context.refresh(); //执行beanFactory后处理器,添加bean后处理器,初始化所有单例
    
        //销毁容器
        context.close();
    }
}//这里也可以用DefaultListableBeanFactory,但该容器在添加后处理器的时候需要一个个的手动的去加,并且开启。非常麻烦。而GenericApplicationContext有个refresh方法,能帮我们做这些事。
Bean1代码:
public class Bean1 {
    private static final Logger log = LoggerFactory.getLogger(Bean1.class);
    private Bean2 bean2;
    @Autowired
    public void setBean2(Bean2 bean2){
        log.info("@Autowired生效:{}",bean2);
        this.bean2=bean2;
    }
    private Bean3 bean3;
    @Resource
    public void setBean3(Bean3 bean3){
        log.info("@Resource生效:{}",bean3);
        this.bean3=bean3;
    }
    private String home;
    @Autowired
    public void setHome(@Value("${JAVA_HOME}")String home){
        log.info("@Value生效:{}",home);
        this.home=home;
    }
    @PostConstruct
    public void init(){
        log.info("@PostConstruct生效");
    }
    @PreDestroy
    public void destroy(){
        log.info("@PreDestroy生效");
    }
    @Override
    public String toString() {
        return "Bean1{" +
                "bean2=" + bean2 +
                ", bean3=" + bean3 +
                ", home='" + home + '\'' +
                '}';
    }
}
在Bean1类中我们分别用@Autowired注入Bean2,@Resource注入Bean3,@Value注入环境变量中的端口号,@PostConstruct注入初始化,@PreDestroy注入销毁。
Bean2和Bean3中什么也没有:
public class Bean2 {
}
现在运行的话,结果只会显示把Bean1、2、3三个类注入到了spring容器中,但并没有运行Bean1类中的诸多bean注入。现在还不能解析有关Bean的注解。
下面我们添加internalAutowiredAnnotationProcessor解析@Autowired、@Value 的后处理器:
public class a04Application {
    public static void main(String[] args) {
        //1
        //GenericApplicationContext是一个干净的容器,”干净“指的是没有添加额外的beanFactory后处理器和bean后处理器
        GenericApplicationContext context = new GenericApplicationContext();
 
        //用原始方法注册三个bean
        context.registerBean("bean1", Bean1.class);
        context.registerBean("bean2", Bean2.class);
        context.registerBean("bean3", Bean3.class);
        //2
        context.registerBean(AutowiredAnnotationBeanPostProcessor.class);//解析@Autowired @Value注解的后处理器
        //初始化容器
        context.refresh(); //执行beanFactory后处理器,添加bean后处理器,初始化所有单例
    
        //销毁容器
        context.close();
    }
}此时运行会报错:No qualifying bean of type 'java.lang.String' available
 因为在用@Value注解值注入时,还会用到另一个类去获取变量的真正的值,但默认的解析器没有该功能。
设置新的注解解析器,帮我们获取值
public class a04Application {
    public static void main(String[] args) {
        //1
        //GenericApplicationContext是一个干净的容器,”干净“指的是没有添加额外的beanFactory后处理器和bean后处理器
        GenericApplicationContext context = new GenericApplicationContext();
 
        //用原始方法注册三个bean
        context.registerBean("bean1", Bean1.class);
        context.registerBean("bean2", Bean2.class);
        context.registerBean("bean3", Bean3.class);
        //3  设置一个新的注解解析器的实现 ,帮助我们获取变量的值
        context.getDefaultListableBeanFactory()
                .setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
        //2
        context.registerBean(AutowiredAnnotationBeanPostProcessor.class);//解析@Autowired @Value注解的后处理器
        //初始化容器
        context.refresh(); //执行beanFactory后处理器,添加bean后处理器,初始化所有单例
    
        //销毁容器
        context.close();
    }
}结果:

已经显示@Value和@Autowired生效了
但@Resource注解的Bean3还没注入,我们继续添加后处理器:
public class a04Application {
    public static void main(String[] args) {
        //1
        //GenericApplicationContext是一个干净的容器,”干净“指的是没有添加额外的beanFactory后处理器和bean后处理器
        GenericApplicationContext context = new GenericApplicationContext();
 
        //用原始方法注册三个bean
        context.registerBean("bean1", Bean1.class);
        context.registerBean("bean2", Bean2.class);
        context.registerBean("bean3", Bean3.class);
        //3  设置一个新的注解解析器的实现 ,帮助我们获取变量的值
        context.getDefaultListableBeanFactory()
                .setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
        //2
        context.registerBean(AutowiredAnnotationBeanPostProcessor.class);//解析@Autowired @Value注解的后处理器
        //4 @Resource、初始化、销毁等注解还不能解析
        context.registerBean(CommonAnnotationBeanPostProcessor.class);//解析@Resource,@PostConstruct,@PreDestroy注解
        //初始化容器
        context.refresh(); //执行beanFactory后处理器,添加bean后处理器,初始化所有单例
    
        //销毁容器
        context.close();
    }
}结果:

可以看到@Resource、@PostConstruct、@PreDestroy都生效了。
实际开发中我们还可能遇到这样的需要:用@ConfigurationProperties注解根据前缀和类中的属性名称去匹配配置环境中的信息,比如:javax.home java.version属性读取出来赋值给类中的属性。
我们先来准备一个bean,然后把环境变量注入:
@Component
@ConfigurationProperties(prefix = "java")
public class Bean4 {
    private String home;
    private String version;
    public String getHome(){
        return home;
    }
    public void setHome(String home){
        this.home=home;
    }
    public String getVersion() {
        return version;
    }
    public void setVersion(String version) {
        this.version = version;
    }
    @Override
    public String toString() {
        return "Bean4{" +
                "home='" + home + '\'' +
                ", version='" + version + '\'' +
                '}';
    }
}
其中的home和version变量分别为jdk的路径和版本号。
我们现在把Bean4注入到容器中,尝试获取环境变量:
public class a04Application {
    public static void main(String[] args) {
        //1
        //GenericApplicationContext是一个干净的容器,”干净“指的是没有添加额外的beanFactory后处理器和bean后处理器
        GenericApplicationContext context = new GenericApplicationContext();
 
        //用原始方法注册三个bean
        context.registerBean("bean1", Bean1.class);
        context.registerBean("bean2", Bean2.class);
        context.registerBean("bean3", Bean3.class);
        //5
        context.registerBean("bean4", Bean4.class);
        //3  设置一个新的注解解析器的实现 ,帮助我们获取变量的值
        context.getDefaultListableBeanFactory()
                .setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
        //2
        context.registerBean(AutowiredAnnotationBeanPostProcessor.class);//解析@Autowired @Value注解的后处理器
        //4 @Resource、初始化、销毁等注解还不能解析
        context.registerBean(CommonAnnotationBeanPostProcessor.class);//解析@Resource,@PostConstruct,@PreDestroy注解
        //5 
        System.out.println(context.getBean(Bean4.class));
        //初始化容器
        context.refresh(); //执行beanFactory后处理器,添加bean后处理器,初始化所有单例
    
        //销毁容器
        context.close();
    }
}结果:

home和value值都是null,因为我们需要再加载一个bean后处理器:解析@ConfigurationProperties注解的bean后处理器
public class a04Application {
    public static void main(String[] args) {
        //1
        //GenericApplicationContext是一个干净的容器,”干净“指的是没有添加额外的beanFactory后处理器和bean后处理器
        GenericApplicationContext context = new GenericApplicationContext();
 
        //用原始方法注册三个bean
        context.registerBean("bean1", Bean1.class);
        context.registerBean("bean2", Bean2.class);
        context.registerBean("bean3", Bean3.class);
        //5
        context.registerBean("bean4", Bean4.class);
        //3  设置一个新的注解解析器的实现 ,帮助我们获取变量的值
        context.getDefaultListableBeanFactory()
                .setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
        //2
        context.registerBean(AutowiredAnnotationBeanPostProcessor.class);//解析@Autowired @Value注解的后处理器
        //4 @Resource、初始化、销毁等注解还不能解析
        context.registerBean(CommonAnnotationBeanPostProcessor.class);//解析@Resource,@PostConstruct,@PreDestroy注解
        //6.解析@ConfigurationProperties注解的bean后处理器
        ConfigurationPropertiesBindingPostProcessor.register(context.getDefaultListableBeanFactory());
        //5 
        System.out.println(context.getBean(Bean4.class));
        //初始化容器
        context.refresh(); //执行beanFactory后处理器,添加bean后处理器,初始化所有单例
    
        //销毁容器
        context.close();
    }
}再次运行:

可以看到已经获取到了环境变量。
![YOLOv11融合[CVPR2024]Starnet中的star block取模块](https://i-blog.csdnimg.cn/direct/1049d59124754d98a2b377cecb161b4f.png)

















