bean后处理器的作用

news2024/12/15 12:38:34

这是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();
    }
}

再次运行:

 可以看到已经获取到了环境变量。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2259934.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

YOLOv11融合[CVPR2024]Starnet中的star block取模块

YOLOv11v10v8使用教程: YOLOv11入门到入土使用教程 YOLOv11改进汇总贴:YOLOv11及自研模型更新汇总 《Rewrite the Stars》 一、 模块介绍 论文链接:https://arxiv.org/abs/2403.19967 代码链接:https://github.com/ma-xu/Rewri…

日常灵感:听劝是一种天赋

希望这段分享能给你提供一些新的角度,让你在自己的工作和生活中更好地利用这份“听劝”的天赋! 父与子的救赎:听劝的天赋 学霸爸爸李先生是一个典型的"别人家的父母"。 他从小就是学霸,凭借过硬的学习能力从重点高中一…

The Rise and Potential of Large Language ModelBased Agents:A Survey---讨论

讨论 论法学硕士研究与Agent研究的互利性 近年来,随着激光诱导金属化技术的发展,激光诱导金属化与化学剂交叉领域的研究取得了长足的进步,促进了这两个领域的发展。在此,我们期待着LLM研究和Agent研究相互提供的一些益处和发展机…

React 第十六节 useCallback 使用详解注意事项

useCallback 概述 1、useCallback 是在React 中多次渲染缓存函数的 Hook,返回一个函数的 memoized的值; 2、如果多次传入的依赖项不变,那么多次定义的时候,返回的值是相同的,防止频繁触发更新; 3、多应用在 父组件为函…

Transformer: Attention Is All You Need (2017) 翻译

论文:Attention Is All You Need 下载地址如下: download: Transformer Attention Is All you need Attention Is All You Need 中文 《Attention Is All You Need》是《Transformer》模型的开创性论文,提出了一种全新的基于注意力机制的架构&#xf…

Git-分支(branch)常用命令

分支 我们在做项目开发的时候,无论是软件项目还是其他机械工程项目,我们为了提高效率以及合理的节省时间等等原因,现在都不再是线性进行,而是将一个项目抽离出诸进行线,每一条线在git中我们就叫做分支,bran…

【AIGC进阶-ChatGPT提示词副业解析】反向心理学在沟通中的运用:激将法的艺术

引言 在日常沟通和管理中,直接的表达方式并不总能达到预期效果。反向心理学,特别是其中的激将法,作为一种独特的沟通技巧,往往能在看似消极的表达中激发出积极的反应。本文将深入探讨反向心理学中激将法的运用技巧、实施策略及其…

360智脑张向征:共建可信可控AI生态 应对大模型安全挑战

发布 | 大力财经 人工智能的加速发展,有力推动了社会的数智化转型;与此同时,带来的相关安全风险也日益凸显。近日,在北京市举办的通明湖人工智能开发与应用大会上,360智脑总裁张向征以“大模型安全研究与实践”为主题&…

lc46全排列——回溯

46. 全排列 - 力扣(LeetCode) 法1:暴力枚举 总共n!种全排列,一一列举出来放入list就行,关键是怎么去枚举呢?那就每次随机取一个,然后删去这个,再从剩下的数组中继续去随机选一个&a…

在线设计平台:Axure新手的在线设计助手

Axure是一款在产品设计、用户体验和交互设计领域广泛使用的强大原型设计工具。它使设计师和产品经理能够迅速构建高保真原型,验证设计和功能,并进行用户测试。结合在线设计平台的协作特性,团队可以更高效地创建、分享和优化原型,加…

Burp与小程序梦中情缘

前言 在日常渗透工作中,有时需要对微信小程序进行抓包渗透,通过抓包,我们可以捕获小程序与服务器之间的通信数据,分析这些数据可以帮助我们发现潜在的安全漏洞,本文通过讲述三个方法在PC端来对小程序抓包渗透 文章目…

gpu硬件架构

1.简介 NVIDIA在视觉计算和人工智能(AI)领域处于领先地位;其旗舰GPU已成为解决包括高性能计算和人工智能在内的各个领域复杂计算挑战所不可或缺的。虽然它们的规格经常被讨论,但很难掌握各种组件的清晰完整的图景。 这些GPU的高性…

SpringCloud集成sleuth和zipkin实现微服务链路追踪

文章目录 前言技术积累spring cloud sleuth介绍zipkin介绍Zipkin与Sleuth的协作 SpringCloud多模块搭建Zipkin Server部署docker pull 镜像启动zipkin server SpringCloud 接入 Sleuth 与 Zipkinpom引入依赖 (springboot2.6)appilication.yml配置修改增加测试链路代码 调用微服…

OBS + SRS:打造专业级直播环境的入门指南

OBS SRS:打造专业级直播环境的入门指南 1. OBS简介2. OBS核心功能详解2.1 场景(Scenes)管理2.2 源(Sources)控制2.3 混音器功能2.4 滤镜与特效2.5 直播控制面板 3. OBS推流到SRS服务器配置指南3.1 环境准备3.2 OBS推流…

Ubuntu K8s

https://serious-lose.notion.site/Ubuntu-K8s-d8d6a978ad784c1baa2fc8c531fbce68?pvs74 2 核 2G Ubuntu 20.4 IP 172.24.53.10 kubeadmkubeletkubectl版本1.23.01.23.01.23.0 kubeadm、kubelet 和 kubectl 是 Kubernetes 生态系统中的三个重要组件 kubeadm: 主…

前端(六)浮动流

浮动流 文章目录 浮动流一、标准流二、浮动流 一、标准流 所谓网页布局就是网页排版的方式,css中有三种网页布局的方式:标准流、浮动流和定位流。 标准流也称文档流,这是浏览器默认的排版方式。标准流中网页的元素会按从左往右、从上往下的…

双内核架构 Xenomai 4 安装教程

Xenomai 4是一种双内核架构, 继承了Xenomai系列的特点,通过在Linux内核中嵌入一个辅助核心(companion core),来提供实时能力。这个辅助核心专门处理那些需要极低且有界响应时间的任务。 本文将在官网教程(https://evlproject.org/…

【安全研究】某黑产网站后台滲透与逆向分析

文章目录 x01. 前言x02. 分析 【🏠作者主页】:吴秋霖 【💼作者介绍】:擅长爬虫与JS加密逆向分析!Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长期坚守并致力于Python与爬虫领域研究与…

【SH】微信小程序调用EasyDL零门槛AI开发平台的图像分类研发笔记

文章目录 微信小程序字符串字符串模板字符串拼接 上传图片编写JS代码编写wxml代码编写wxss代码 GET请求测试编写测试代码域名不合法问题 GET和POST请求测试编写JS代码编写wxml代码编写wxss代码 效果展示 微信小程序字符串 字符串模板 这是ES6引入的特性,允许你通过…

6.2 Postman接口收发包

欢迎大家订阅【软件测试】 专栏,开启你的软件测试学习之旅! 文章目录 前言1 接口收发包的类比1.1 获取对方地址(填写接口URL)1.2 选择快递公司(设置HTTP方法)1.3 填写快递单(设置请求头域&#…