@Configuration 和 @Component 的区别 ,别再瞎用了!

您所在的位置:网站首页 service与compment @Configuration 和 @Component 的区别 ,别再瞎用了!

@Configuration 和 @Component 的区别 ,别再瞎用了!

2024-07-01 06:06:52| 来源: 网络整理| 查看: 265

一句话概括就是 @Configuration 中所有带 @Bean 注解的方法都会被动态代理,因此调用该方法返回的都是同一个实例。

理解:调用@Configuration类中的@Bean注解的方法,返回的是同一个示例;而调用@Component类中的@Bean注解的方法,返回的是一个新的实例。

“注意:上面说的调用,而不是从spring容器中获取! 见最下面的示例 1 及 示例 2

下面看看实现的细节。

@Configuration 注解代码语言:javascript复制@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Configuration { String value() default ""; }

从定义来看, @Configuration注解本质上还是@Component,因此 或者 @ComponentScan 都能处理@Configuration注解的类。

@Configuration标记的类必须符合下面的要求:

配置类必须以类的形式提供(不能是工厂方法返回的实例),允许通过生成子类在运行时增强(cglib 动态代理)。配置类不能是final 类(没法动态代理)。配置注解通常为了通过 @Bean注解生成 Spring 容器管理的类,配置类必须是非本地的(即不能在方法中声明,不能是 private)。任何嵌套配置类都必须声明为static。@Bean方法可能不会反过来创建进一步的配置类(也就是返回的 bean 如果带有 @Configuration,也不会被特殊处理,只会作为普通的 bean)。@Bean 注解方法执行策略

先给一个简单的示例代码:

代码语言:javascript复制@Configuration public class MyBeanConfig { @Bean public Country country(){ return new Country(); } @Bean public UserInfo userInfo(){ return new UserInfo(country()); } }

相信大多数人第一次看到上面 userInfo() 中调用 country()时,会认为这里的 Country和上面 @Bean方法返回的 Country 可能不是同一个对象,因此可能会通过下面的方式来替代这种方式:

@Autowiredprivate Country country;

实际上不需要这么做(后面会给出需要这样做的场景),直接调用country() 方法返回的是同一个实例。

@Component 注解

@Component注解并没有通过 cglib 来代理@Bean 方法的调用,因此像下面这样配置时,就是两个不同的 country。

代码语言:javascript复制@Component public class MyBeanConfig { @Bean public Country country(){ return new Country(); } @Bean public UserInfo userInfo(){ return new UserInfo(country()); } }

有些特殊情况下,我们不希望 MyBeanConfig被代理(代理后会变成WebMvcConfig

EnhancerBySpringCGLIB

8bef3235293)时,就得用 @Component,这种情况下,上面的写法就需要改成下面这样:

代码语言:javascript复制@Component public class MyBeanConfig { @Autowired private Country country; @Bean public Country country(){ return new Country(); } @Bean public UserInfo userInfo(){ return new UserInfo(country); } }

这种方式可以保证使用的同一个 Country 实例。

示例 1:调用@Configuration类中的@Bean注解的方法,返回的是同一个示例

第一个bean类

代码语言:javascript复制package com.xl.test.logtest.utils; public class Child { private String name = "the child"; public String getName() { return name; } public void setName(String name) { this.name = name; } }

第二个bean类

代码语言:javascript复制package com.xl.test.logtest.utils; public class Woman { private String name = "the woman"; private Child child; public String getName() { return name; } public void setName(String name) { this.name = name; } public Child getChild() { return child; } public void setChild(Child child) { this.child = child; } }

@Configuration类

代码语言:javascript复制package com.xl.test.logtest.utils; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.stereotype.Component; @Configuration //@Component public class Human { @Bean public Woman getWomanBean() { Woman woman = new Woman(); woman.setChild(getChildBean()); // 直接调用@Bean注解的方法方法getChildBean() return woman; } @Bean public Child getChildBean() { return new Child(); } }

测试类 I

本测试类为一个配置类,这样启动项目是就可以看到测试效果,更加快捷;也可以使用其他方式测试见下面的测试类 II

代码语言:javascript复制package com.xl.test.logtest.utils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; @Configuration public class Man { @Autowired public Man(Woman wn, Child child) { System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); System.out.println(wn.getChild() == child ? "是同一个对象":"不是同一个对象"); } }

启动项目,查看输出结果:

测试类 II

代码语言:javascript复制package com.xl.test.logtest.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import com.xl.test.logtest.utils.Child; import com.xl.test.logtest.utils.Woman; @RestController public class LogTestController { @Autowired Woman woman ; @Autowired Child child; @GetMapping("/log") public String log() { return woman.getChild() == child ? "是同一个对象":"不是同一个对象"; } }

浏览器访问项目,查看结果;输入localhost:8080/log

示例 2 :调用@Component类中的@Bean注解的方法,返回的是一个新的实例。

测试代码,只需要将@Configuration改为@Component即可!其他的均不变

代码语言:javascript复制package com.xl.test.logtest.utils; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.stereotype.Component; //@Configuration @Component public class Human { @Bean public Woman getWomanBean() { Woman woman = new Woman(); woman.setChild(getChildBean()); // 直接调用@Bean注解的方法方法getChildBean() return woman; } @Bean public Child getChildBean() { return new Child(); } }

测试 :

控制台和浏览器展示,均符合预期!

来源:blog.csdn.net/qq_29025955/

article/details/128818957

👉最新2T+免费Java视频学习资料点击领取>>

END

精品资料,超赞福利,免费领

IDEA 插件最佳组合:JRebel+XRebel 完成项目热部署和接口分析优化,太爽了!

宕机了,Redis 如何避免数据丢失?

Spring 新特性,正式“抛弃”Feign了

4 个超实用的 Docker 镜像构建技巧

【原创】怒肝3W字Java学习路线!从入门到封神全包了(建议收藏)

程序员专属导航站(baoboxs.com),一站式工作、学习、娱乐!



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭