面试官:@Configuration 和 @Component 注解的区别?大部分人都会答错!()

  本篇文章为你整理了面试官:@Configuration 和 @Component 注解的区别?大部分人都会答错!()的详细内容,包含有 面试官:@Configuration 和 @Component 注解的区别?大部分人都会答错!,希望能帮助你了解 面试官:@Configuration 和 @Component 注解的区别?大部分人都会答错!。

  分享Java技术,高并发编程,分布式技术,架构设计,Java面试题,算法,行业动态,程序人生等。

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

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

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

  下面看看实现的细节。

  @Configuration 注解:

  

@Target(ElementType.TYPE)

 

  @Retention(RetentionPolicy.RUNTIME)

  @Documented

  @Component

  public @interface Configuration {

   String value() default "";

  

 

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

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

  配置类必须以类的形式提供(不能是工厂方法返回的实例),允许通过生成子类在运行时增强(cglib 动态代理)。

  配置类不能是final 类(没法动态代理)。

  配置注解通常为了通过 @Bean注解生成 Spring 容器管理的类,

  配置类必须是非本地的(即不能在方法中声明,不能是 private)。

  任何嵌套配置类都必须声明为static。

  @Bean方法可能不会反过来创建进一步的配置类(也就是返回的 bean 如果带有 @Configuration,也不会被特殊处理,只会作为普通的 bean)。

  @Bean 注解方法执行策略

  推荐一个开源免费的 Spring Boot 最全教程:

  https://github.com/javastacks/spring-boot-best-practice

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

  

@Configuration

 

  public class MyBeanConfig {

   @Bean

   public Country country(){

   return new Country();

   @Bean

   public UserInfo userInfo(){

   return new UserInfo(country());

  

 

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

  @Autowired

  private Country country;

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

  @Component 注解

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

  

@Component

 

  public class MyBeanConfig {

   @Bean

   public Country country(){

   return new Country();

   @Bean

   public UserInfo userInfo(){

   return new UserInfo(country());

  

 

  有些特殊情况下,我们不希望 MyBeanConfig被代理(代理后会变成WebMvcConfig$$EnhancerBySpringCGLIB$$8bef3235293)时,就得用 @Component,这种情况下,上面的写法就需要改成下面这样:

  

@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类

  

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类

  

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类

  

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

  

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

  

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即可!其他的均不变

  

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

  近期热文推荐:

  1.1,000+ 道 Java面试题及答案整理(2022最新版)

  2.劲爆!Java 协程要来了。。。

  3.Spring Boot 2.x 教程,太全了!

  4.别再写满屏的爆爆爆炸类了,试试装饰器模式,这才是优雅的方式!!

  5.《Java开发手册(嵩山版)》最新发布,速速下载!

  觉得不错,别忘了随手点赞+转发哦!

  以上就是面试官:@Configuration 和 @Component 注解的区别?大部分人都会答错!()的详细内容,想要了解更多 面试官:@Configuration 和 @Component 注解的区别?大部分人都会答错!的内容,请持续关注盛行IT软件开发工作室。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: