首页 > 其他分享 >@Configuration 和 @Component 区别

@Configuration 和 @Component 区别

时间:2023-02-10 22:47:39浏览次数:46  
标签:return 区别 Component Bean import Configuration public

本文参考1:https://blog.csdn.net/isea533/article/details/78072133

本文参考2:https://blog.csdn.net/weixin_52850476/article/details/124410800

一句话概括就是 @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 注解方法执行策略

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

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

测试 :
在这里插入图片描述

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

来源:https://blog.csdn.net/qq_29025955/article/details/128818957

标签:return,区别,Component,Bean,import,Configuration,public
From: https://www.cnblogs.com/konglxblog/p/17110535.html

相关文章

  • 核心线程数和最大线程数的区别
    首先看下来自实测的效果图  这里说明线程过多产生的影响和最大线程数与定义的队列长度有关  以上就是核心线程数和最大线程数的区别代码部分<?xmlversion=......
  • PPTP和L2TP有哪些区别?
    PPTP和L2TP有哪些区别?1、PPTP要求互联网络为IP网络。L2TP只要求隧道媒介提供面向数据包的点对点的连接。L2TP可以在IP(使用UDP),帧中继永久虚拟电路(PVCs)、X.25虚拟电路(VCs)或AT......
  • 抽象类和接口的区别
    1、抽象类是单继承,接口可以多实现。2、抽象类中方法的访问权限可以任意,接口里方法的访问权限只能是public3、抽象类中可以有构造方法,接口中不能有。4、抽象类中可以有......
  • 干货:实时渲染和离线渲染的区别?实时云渲染又是什么?
    常见的渲染类型有以下几种:实时渲染、离线渲染、实时云渲染、混合渲染。那么什么是实时渲染?实时渲染和离线渲染有哪些区别?各自有哪些典型应用场景......有没有人感觉知道了......
  • JQuery对象和JS对象区别与转换以及JQuery事件绑定,入口函数,样式控制
    <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>JQuery对象和js对象的转换</title><scriptsrc="js/jquery-3.3.1.min.js"></scri......
  • APP测试与web测试的区别
    web和app的区别web项目,一般都是b/s架构,基于浏览器的。App则是C/S的,必须要有客户端。首先从系统架构来看的话,Web测试只要更新了服务器端,客户端就会同步会更新。而且客......
  • 软件测试和游戏测试到底有什么区别?
    有很多同学进入测试行业之后,一直从事的是软件测试的工作,然后跳槽时遇到一些游戏的公司的面试,就会有点慌,我做的都是软件测试,能胜任游戏测试么?所以,今天我们需要先来了解......
  • 前端-vue基础36-计算属性和方法的区别
     <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,initial-scale=1.0"><titl......
  • 页面导入样式时,使用link和@import有什么区别?
    1.从属关系区别@import是CSS提供的语法规则,只有导入样式表的作用;link是HTML提供的标签,不仅可以加载CSS文件,还可以定义RSS、rel连接属性等。2.加载顺序区别加载页......
  • malloc、calloc和realloc的区别
    1.malloc函数使用方法:参数是所需申请的内存块的字节数,返回指向申请的内存块的首地址的无类型指针,malloc申请的内存块是未初始化的。函数原型:void*malloc(size_tnum_s......