关于java:面试官Configuration-和-Component-注解的区别大部分人都会答错

一句话概括就是 @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开发手册(嵩山版)》最新公布,速速下载!

感觉不错,别忘了顺手点赞+转发哦!

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理