@Configuration注解配置 配置类
1)基本使用
1、在类上加上 @Configuration注解:告诉 SpringBoot 这是一个配置类 == Spring 的配置文件(eg:bean.xml)
2、配置类里面使用 @Bean 标注在方法上给容器注册组件,默认也是单例模式。
3、配置类本身也是组件; 可以通过MyConfig bean = run.getBean(MyConfig.class); 获取对象。
4、proxyBeanMethods 属性:代理 bean 方法, 默认为 true。
Full 模式(proxyBeanMethods = true),Lite 模式 (proxyBeanMethods = false)
@Configuration(proxyBeanMethods = true) 中 proxyBeanMethods 默认为 true ??
1、外部无论对配置类中的这个组件注册方法(eg:orgInfo()方法)调用多少次,获取的都是之前注册在IOC容器中的单实例对象。
所以 OrgInfo orgInfo1 = myConfig.orgInfo(); OrgInfo orgInfo2 = myConfig.orgInfo(); 中,对象 orgInfo1、orgInfo2 指向同一个内存地址,取出的是同一个单实例对象。
2、@Configuration(proxyBeanMethods = true) 代理对象调用方法。SpringBoot 每次都会检查这个组件是否在容器中存在,保持组件单实例。
3、proxyBeanMethods = true,获取的配置类对象 MyConfig 为以下
MyConfig$$EnhancerBySpringCGLIB$$ccb97cdd@35e478f 对象,通过 CGLIB代理对象。
@Configuration(proxyBeanMethods = fasle) 中 proxyBeanMethods 为 fasle??
1、获取的配置类对象为 MyConfig@13e698c7 类型;
2、每次调用配置类中的方法,SpringBoot 都会创建一个新的对象;
OrgInfo orgInfo1 = myConfig.orgInfo(); OrgInfo orgInfo2 = myConfig.orgInfo(); 中,对象 orgInfo1 与 orgInfo2不相等。
proxyBeanMethods = true 时测试结果:
@Configuration(proxyBeanMethods = true)
public class MyConfig {
/**
* 外部无论对配置类中的这个组件注册方法调用多少次,获取的都是之前注册在IOC容器中的单实例对象
*/
@Bean
public OrgInfo orgInfo() {
return new OrgInfo("001", "测试");
}
}
@SpringBootApplication
public class AgedManageApplication {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(AgedManageApplication.class, args);
//com.wondersgroup.aged.configuration.MyConfig$$EnhancerBySpringCGLIB$$ccb97cdd@35e478f
MyConfig myConfig = run.getBean(MyConfig.class);
System.out.println("bean=" + myConfig);//MyConfig$$EnhancerBySpringCGLIB$$ccb97cdd@35e478f
//1、外部无论对配置类中的这个组件注册方法调用多少次,获取的都是之前注册在IOC容器中的单实例对象。
//2、@Configuration(proxyBeanMethods = true) 代理对象调用方法。SpringBoot每次都会检查这个组件是否在容器中存在,保持组件单实例。
OrgInfo orgInfo1 = myConfig.orgInfo();
OrgInfo orgInfo2 = myConfig.orgInfo();
System.out.println(orgInfo1 == orgInfo2);//输出true
}
}
proxyBeanMethods = false 时测试结果:
2)Full 模式与 Lite 模式
Full 模式(proxyBeanMethods = true),Lite 模式 (proxyBeanMethods = false)
1、配置类组件之间无依赖关系用 Lite 模式加速容器启动过程(SpringBoot启动更快),减少判断(获取bean对象时,不需要去判断 IOC容器中是否已存在被调用的bean对象)。
2、配置类组件之间有依赖关系,方法被调用时得到的是之前单实例组件,用 Full 模式。
Full 模式(proxyBeanMethods = true):主要用于组件依赖:如下:
@Configuration(proxyBeanMethods = true)
public class MyConfig {
@Bean
public OrgInfo orgInfo() {
OrgInfo orgInfo = new OrgInfo("001", "测试");
//组件依赖: 组件 OrgInfo 依赖组件 MdmAddress
//proxyBeanMethods = true 时, orgInfo.setAddress(address());设置的就是 IOC容器中的 MdmAddress 组件,也就是下面那个 id为 addr 的组件
orgInfo.setAddress(address());
return orgInfo;
}
@Bean(value = "addr") // @Bean 把组件 MdmAddress 注册到 IOC 容器中
public MdmAddress address() {
return new MdmAddress();
}
}
@SpringBootApplication
public class AgedManageApplication {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(AgedManageApplication.class, args);
//从 IOC 中拿到 address1 对象
MdmAddress address1 = run.getBean("addr", MdmAddress.class);
//从 组件 OrgInfo 中拿到 address2 对象
OrgInfo orgInfo = run.getBean("orgInfo", OrgInfo.class);
MdmAddress address2 = orgInfo.getAddress();
//proxyBeanMethods = true 时,测试拿到的 address1、address2对象是否是同一个对象,输出true 说明拿到的是同一个对象
// 如果 Lite 模式 (proxyBeanMethods = false)那么此处会输出 false,拿到就不是同一个对象
System.out.println(address1 == address2);//输出 true
}
}
3)@Bean 注解
@Bean 注解:给容器中添加组件,以方法名作为主键的id,返回的类型就是组件的类型,返回的值就是组件在容器中的实例对象。
@Bean(value = "addr") // bean的id 默认是方法名,可以通过 value = "addr" 修改 id 名
public MdmAddress address() {}
代码示例:
package com.wondersgroup.aged.configuration;
import com.wondersgroup.aged.entity.MdmAddress;
import com.wondersgroup.aged.entity.OrgInfo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author by LMGD
* @date 2022-04-25 22:24
* @description
*/
/**
* 1、配置类里面使用 @Bean 标注在方法上给容器注册组件,默认也是单例模式
* 2、配置类本身也是组件; 可以通过MyConfig bean = run.getBean(MyConfig.class); 获取对象
*/
@Configuration //@Configuration注解:告诉 SpringBoot这是一个配置类 等于 Spring的配置文件(eg:bean.xml)
public class MyConfig {
/**
* 在 SpringBoot 容器中注入两个组件 orgInfo、addr
*/
/**
* 外部无论对配置类中的这个组件注册方法调用多少次获取的都是之前注册在IOC容器中的单实例对象
*/
@Bean //@Bean 注解:给容器中添加组件,以方法名作为主键的id,返回的类型就是组件的类型,返回的值就是组件在容器中的实例对象。
public OrgInfo orgInfo() {
return new OrgInfo("001", "测试");
}
@Bean(value = "addr") // bean的id 默认是方法名,可以通过 value = "addr" 修改 id 名
public MdmAddress address() {
return new MdmAddress();
}
}
测试配置类 :
@SpringBootApplication
public class AgedManageApplication {
public static void main(String[] args) {
//获取SpringBoot IOC容器
ConfigurableApplicationContext run = SpringApplication.run(AgedManageApplication.class, args);
//从容器中获取组件,SpringBoot容器默认是单例模式,所以每次从容器中取出 orgInfo 对象都是同一个对象。
//组件 orgInfo1 == orgInfo2 输出 true
OrgInfo orgInfo1 = run.getBean("orgInfo", OrgInfo.class);
OrgInfo orgInfo2 = run.getBean("orgInfo", OrgInfo.class);
System.out.println(orgInfo1);
System.out.println(orgInfo2);
System.out.println(orgInfo1 == orgInfo2 ? true : false);
//从容器中获取组件,获取配置类
MyConfig bean = run.getBean(MyConfig.class);
System.out.printf("bean=" + bean);
//bean=com.wondersgroup.aged.configuration.MyConfig$$EnhancerBySpringCGLIB$$c1fe757b@c3c4c1c
}
}
输出结果: