17、Bean的生命周期
-
bean的生命周期:bean的创建—初始化—销毁的过程
-
容器负责管理bean的生命周期
-
我们可以自定义初始化和销毁方法,容器在bean进行到当前生命周期的时候来调用我们自定义的初始化和销毁方法
-
构造(对象创建)
单实例:在容器启动时创建对象
多实例:在每次获取的时候创建对象 -
初始化:
单实例:容器 关闭的时候
多实例:容器不会管理这个bean,容器不会调用销毁方法,如果需要销毁必须使用手动调用。
指定初始化和销毁方法有三种
1、使用@Bean(initMethod = “init”,destroyMethod = “destory”)
2、通过让Bean实现InitializingBean接口来定义初始化逻辑 ,DisposableBean接口来销毁bean
3、@PostConstruct、@PreDestory注解初始化和销毁方式
4、@BeanPostProcessor后置处理器,在bean初始化进行相应操作
18、@Bean(initMethod = “init”,destroyMethod = “destory”)指定初始化和销毁方式
1)指定初始化和销毁方式
使用@Bean(initMethod = “init”,destroyMethod = “destory”)
多实例bean的销毁,由用户自定义,容器不再管理
指定前
创建bean并设置初始化和销毁方法
public class Car {
public Car(){
System.out.println("car is constructor........");
}
public void init(){
System.out.println("car is inited........");
}
public void destory(){
System.out.println("car is destoried.....");
}
}
创建配置类,并配置bean
@Configuration
public class MainConfigOfLifeCycle {
@Bean
public Car car(){
return new Car();
}
}
测试类
public class testLife {
//创建ioc容器
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
@Test
public void testLifeCycle(){
System.out.println(" 容器创建完成");
}
}
测试结果
car is constructor........
容器创建完成
指定后
创建配置类,并配置bean
注意: @Bean(initMethod = “init”,destroyMethod = “destory”)
@Configuration
public class MainConfigOfLifeCycle {
@Bean(initMethod = "init",destroyMethod = "destory")
public Car car(){
return new Car();
}
}
测试类
public class testLife {
//创建ioc容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
@Test
public void testLifeCycle(){
System.out.println("容器创建完成");
applicationContext.close();
}
}
测试结果:
car is constructor........
car is inited........
容器创建完成
car is destoried.....
19、InitializingBean接口定义初始化和销毁方式
2)通过让Bean实现InitializingBean接口来定义初始化逻辑 ,DisposableBean接口来销毁bean
创建自定义bean,并实现InitializingBean、DisposableBean接口,同时改写destory()和afterPropertiesSet()方法
@Component
public class Cat implements InitializingBean, DisposableBean {
public Cat() {
System.out.println("cat is generated.....");
}
//销毁方法
@Override
public void destroy() throws Exception {
System.out.println("cat is destoried ......");
}
//初始化方法
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("cat is inited ......");
}
}
修改配置类
@Configuration
@ComponentScan("com.atguigu")
public class MainConfigOfLifeCycle {
@Bean(initMethod = "init",destroyMethod = "destory")
public Car car(){
return new Car();
}
}
测试类
public class testLife {
//创建ioc容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
@Test
public void testLifeCycle(){
System.out.println("容器创建完成");
applicationContext.getBean("cat");
applicationContext.close();
}
}
测试结果
cat is generated.....
cat is inited ......
car is constructor........
car is inited........
容器创建完成
car is destoried.....
cat is destoried ......
20、@PostConstruct、@PreDestory注解初始化和销毁方式
3)通过让Bean实现PostConstruct接口来定义初始化逻辑 ,PreDestory接口来销毁bean
@PostConstuct:在bean创建完成并且属性赋值完成初始化方法,作用在方法上
@preDestory:再容器销毁bean之前通知我们进行清理工作
比较好的一篇文章
@PostConstruct详解
**创建bean类并添加相应注解 **
@Component
public class Dog {
public Dog() {
System.out.println("dog is generated");
}
//对象创建并赋值之后调用
@PostConstruct
public void init(){
System.out.println("dog is constructed ......");
}
//容器移除对象之前
@PreDestroy
public void destory(){
System.out.println("dog is destoried ......");
}
}
测试类
public class testLife {
//创建ioc容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
@Test
public void testLifeCycle(){
System.out.println("容器创建完成");
//applicationContext.getBean("cat");
applicationContext.close();
}
}
测试结果
cat is generated.....
cat is inited ......
dog is generated
car is constructor........
car is inited........
容器创建完成
car is destoried.....
cat is destoried ......
21、@BeanPostProcessor后置处理器
4)@BeanPostProcessor后置处理器,在bean初始化进行相应操作,包括:
postProcessBeforeInitialization:在初始化之前工作
postProcessAfterInitialization:在初始化之后工作(调用)
具体来说需要事项BeanPostProcessor接口,并改写postProcessBeforeInitialization(Object o, String s)、postProcessAfterInitialization(Object o, String s)方法
创建自定义后置处理器
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("初始化完成前工作调用"+beanName+"=>"+bean);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("初始化完成后工作调用"+beanName+"=>"+bean);
return bean;
}
}
测试类
public class testLife {
//创建ioc容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
@Test
public void testLifeCycle(){
System.out.println("容器创建完成");
//applicationContext.getBean("cat");
applicationContext.close();
}
}
测试结果
初始化完成前工作调用org.springframework.context.event.internalEventListenerProcessor=>org.springframework.context.event.EventListenerMethodProcessor@4b5189ac
初始化完成后工作调用org.springframework.context.event.internalEventListenerProcessor=>org.springframework.context.event.EventListenerMethodProcessor@4b5189ac
初始化完成前工作调用org.springframework.context.event.internalEventListenerFactory=>org.springframework.context.event.DefaultEventListenerFactory@704deff2
初始化完成后工作调用org.springframework.context.event.internalEventListenerFactory=>org.springframework.context.event.DefaultEventListenerFactory@704deff2
初始化完成前工作调用mainConfigOfLifeCycle=>com.atguigu.config.MainConfigOfLifeCycle$$EnhancerBySpringCGLIB$$9bbbd82c@2b9ed6da
初始化完成后工作调用mainConfigOfLifeCycle=>com.atguigu.config.MainConfigOfLifeCycle$$EnhancerBySpringCGLIB$$9bbbd82c@2b9ed6da
cat is generated.....
初始化完成前工作调用cat=>com.atguigu.bean.Cat@59d4cd39
cat is inited ......
初始化完成后工作调用cat=>com.atguigu.bean.Cat@59d4cd39
dog is generated
初始化完成前工作调用dog=>com.atguigu.bean.Dog@1187c9e8
初始化完成后工作调用dog=>com.atguigu.bean.Dog@1187c9e8
初始化完成前工作调用mainConfig=>com.atguigu.config.MainConfig$$EnhancerBySpringCGLIB$$201ea2bd@6d7fc27
初始化完成后工作调用mainConfig=>com.atguigu.config.MainConfig$$EnhancerBySpringCGLIB$$201ea2bd@6d7fc27
初始化完成前工作调用bookController=>com.atguigu.controller.BookController@135606db
初始化完成后工作调用bookController=>com.atguigu.controller.BookController@135606db
初始化完成前工作调用bookDAO=>com.atguigu.dao.BookDAO@6c372fe6
初始化完成后工作调用bookDAO=>com.atguigu.dao.BookDAO@6c372fe6
初始化完成前工作调用bookService=>com.atguigu.service.BookService@2a3888c1
初始化完成后工作调用bookService=>com.atguigu.service.BookService@2a3888c1
初始化完成前工作调用com.atguigu.bean.Color=>com.atguigu.bean.Color@4167d97b
初始化完成后工作调用com.atguigu.bean.Color=>com.atguigu.bean.Color@4167d97b
初始化完成前工作调用com.atguigu.bean.Red=>com.atguigu.bean.Red@14fa86ae
初始化完成后工作调用com.atguigu.bean.Red=>com.atguigu.bean.Red@14fa86ae
初始化完成前工作调用com.atguigu.bean.Blue=>com.atguigu.bean.Blue@6e15fe2
初始化完成后工作调用com.atguigu.bean.Blue=>com.atguigu.bean.Blue@6e15fe2
初始化完成前工作调用com.atguigu.bean.Yellow=>com.atguigu.bean.Yellow@68f1b17f
初始化完成后工作调用com.atguigu.bean.Yellow=>com.atguigu.bean.Yellow@68f1b17f
初始化完成前工作调用female=>Person{name='wanger', age=23}
初始化完成后工作调用female=>Person{name='wanger', age=23}
初始化完成前工作调用colorFactoryBean=>com.atguigu.bean.ColorFactory@7cbd9d24
初始化完成后工作调用colorFactoryBean=>com.atguigu.bean.ColorFactory@7cbd9d24
初始化完成前工作调用rainbow=>com.atguigu.bean.RainBow@1b45c0e
初始化完成后工作调用rainbow=>com.atguigu.bean.RainBow@1b45c0e
car is constructor........
初始化完成前工作调用car=>com.atguigu.bean.Car@73a8da0f
car is inited........
初始化完成后工作调用car=>com.atguigu.bean.Car@73a8da0f
容器创建完成
car is destoried.....
cat is destoried ......
22、@Value为属性赋值
在bean类的属性上直接使用@Value注解来赋值
创建bean类(pojo类)
public class Person {
//value的值可以是1、基本数据类型值,2、可以写表达式如#{},3、可以用${}取出配置文件的值(在运行的环境变量中的值)
@Value("张三")
private String name;
@Value("#{23+4}")
private Integer age;
public Person() {
}
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
创建配置类
@Configuration
public class MainConfigOfPropertyValues {
@Bean
public Person person(){
return new Person();
}
}
测试类
public class TestAno {
AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext(MainConfigOfPropertyValues .class);
@Test
public void testProperty(){
printBeans(applicationContext);
System.out.println("====");
Person person = (Person) applicationContext.getBean("person");
System.out.println(person);
}
private void printBeans(AnnotationConfigApplicationContext applicationContext){
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String name:beanDefinitionNames) {
System.out.println(name);
}
}
}
测试结果
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfigOfPropertyValues
person
====
Person{name='张三', age=27}
23、@PropertySource加载外部配置文件属性赋值
需要加载外部配置文件,读取配置文件中 的k/v,保存到运行中的环境变量中
1、创建配置文件,在文件中创建若干键值对
创建文件 person.properties
person.name=zhangsanfeng
2、在配置类中使用@PropertySource指定配置文件
注意:@PropertySource(value={“classpath:/person.properties”})
//加载外部配置文件,读取配置文件中 的k/v,保存到运行中的环境变量中
@PropertySource(value={"classpath:/person.properties"})
@Configuration
public class MainConfigOfPropertyValues {
@Bean
public Person person(){
return new Person();
}
}
3、bean类中引用相应的值
注意:
@Value(“${person.name}”)
private String name;
public class Person {
//value的值可以是1、基本数据类型值,2、可以写表达式如#{},3、可以用${}取出配置文件的值(在运行的环境变量中的值)
@Value("${person.name}")
private String name;
@Value("#{23+4}")
private Integer age;
public Person() {
}
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
4、测试类
public class TestAno {
AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext(MainConfigOfPropertyValues .class);
@Test
public void testProperty(){
printBeans(applicationContext);
System.out.println("====");
Person person = (Person) applicationContext.getBean("person");
System.out.println(person);
ConfigurableEnvironment environment = applicationContext.getEnvironment();
String property=environment.getProperty("person.name");
System.out.println(property);
}
private void printBeans(AnnotationConfigApplicationContext applicationContext){
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String name:beanDefinitionNames) {
System.out.println(name);
}
}
}
5、测试结果
注意:Person{name=‘zhangsanfeng’, age=27}
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfigOfPropertyValues
person
====
Person{name='zhangsanfeng', age=27}
zhangsanfeng
24、@Autowired&自动装配
自动装配:Spring利用依赖注入(DI),完成对IOC容器中各个组件的依赖关系赋值
1)@Autowired
一个组件需要使用到另外一个组件,直接对被使用的组件上添加@Autowired注解就可以注入这个组件。它:
- 默认优先按照类型去容器内找到对应的组件:如: BookDAO bookDAO =
applicationContext.getBean(BookDAO.class); - 如果有多个同类型的组件,再将属性名作为组件的id去容器中查找(没测试出来,总是报找到两个bean)
dao类
@Repository
public class BookDAO {
}
service类
@Service
public class BookService {
@Autowired
private BookDAO bookDao;
public void print(){
System.out.println(bookDao);
}
}
controller
@Controller
public class BookController {
@Autowired
private BookService bookService;
}
配置类
@Configuration
@ComponentScan({"com.atguigu"})
public class MainConfigAutowired {
}
测试类
public class TestAuto {
AnnotationConfigApplicationContext applicationContext= new AnnotationConfigApplicationContext(MainConfigAutowired.class);
@Test
public void testAutowired(){
BookService bookService = applicationContext.getBean(BookService.class);
BookDAO bookDAO = applicationContext.getBean(BookDAO.class);
System.out.println(bookService);
System.out.println(bookDAO);
}
}
测试结果
com.atguigu.service.BookService@7357a011
com.atguigu.dao.BookDAO@30bce90b
25、@Qualifier&自动装配
@Qualifier明确指定需要装配哪一个组件,具体写法如:@Qualifier(“bookDAO3”)
@Configuration
@ComponentScan({"com.atguigu"})
public class MainConfigAutowired {
@Qualifier("bookDAO")
@Bean("bookDAO2")
public BookDAO bookDAO(){
BookDAO bookDAO = new BookDAO();
bookDAO.setLable("2");
return bookDAO;
}
}
26、@Primary自动装配
如果容器内没有任何bean,单IOC自动装配默认一定要将属性装配好,否则会报错,可以使用在@Autowired(required=false),这里设置了required为非必须
以上情况可以使用@Primary来让Spring装配的时候,选择该注解的类为首选类
@Configuration
@ComponentScan({"com.atguigu"})
public class MainConfigAutowired {
@Qualifier("bookDAO")
@Bean("bookDAO2")
public BookDAO bookDAO(){
BookDAO bookDAO = new BookDAO();
bookDAO.setLable("2");
return bookDAO;
}
}
27、@Resource自动装配
@Resource是用来 替代@Autowired的,和@Autowired一样实现自动装配,默认按照组件名称进行装配,没有能支持@Primary
@Service
public class BookService {
@Resource
private BookDAO bookDAO2;
public void print(){
System.out.println(bookDAO2);
}
}
28、@Inject自动装配
- 也是用来替代@Autowired的
- 需要在pom.xml中导入inject依赖
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
装配的写法
@Service
public class BookService {
@Inject
private BookDAO bookDAO2;
public void print(){
System.out.println(bookDAO2);
}
}
29、标注在方法上方法的自动装配
默认加在ioc容器的组件,容器启动会调用无参构造器创建对象,再进行初始化等操作
- 标注在方法上,Spring容器 创建当前对象,就会调用方法,完成赋值, 方法使用的参数,自定义类型的值从ioc容易中获取
- 标注在构造方法上
- 也可以放在参数列表上
Boos类
@Component
public class Boss {
private Car car;
public Car getCar(){
return car;
}
//标注在方法上,Spring容器 创建当前对象,就会调用方法,完成赋值
//方法使用的参数,自定义类型的值从ioc容易中获取
@Autowired
public void setCar(Car car){
this.car=car;
}
@Override
public String toString() {
return "Boss{" +
"car=" + car +
'}';
}
}
Car类
@Component
public class Car {
}
测试 类
public class TestAuto {
@Test
public void testAutowired(){
AnnotationConfigApplicationContext applicationContext= new AnnotationConfigApplicationContext(MainConfigAutowired.class);
Boss Boos = applicationContext.getBean(Boss.class);
System.out.println(Boos);
Car car = applicationContext.getBean(Car.class);
System.out.println(car);
}
}
测试结果
Boss{car=com.atguigu.bean.Car@198d6542}
com.atguigu.bean.Car@198d6542
ps:两个car对象的地址是一样的
- 如果只有一个有参构造器,则参数上的@Autowired可以不写,可以从组件中自动获取
30、标注在构造器位置的自动装配
- 也可以把@Autowried放在有参构造器上
@Component
public class Boss {
private Car car;
@Autowired
public Boss(Car car) {
this.car = car;
}
public Car getCar(){
return car;
}
//标注在方法上,Spring容器 创建当前对象,就会调用方法,完成赋值
//方法使用的参数,自定义类型的值从ioc容易中获取
//@Autowired
public void setCar(Car car){
this.car=car;
}
@Override
public String toString() {
return "Boss{" +
"car=" + car +
'}';
}
}
- 还可以放在参数列表上
@Component
public class Boss {
private Car car;
public Boss(Car car) {
this.car = car;
}
public Car getCar(){
return car;
}
//标注在方法上,Spring容器 创建当前对象,就会调用方法,完成赋值
//方法使用的参数,自定义类型的值从ioc容易中获取
//@Autowired
public void setCar(@Autowired Car car){
this.car=car;
}
@Override
public String toString() {
return "Boss{" +
"car=" + car +
'}';
}
}
31、Aware注入Spring底层组件
自定义组件要想使用Spring容器底层的一些组件(ApplicationContext,BeanFactory等)
- 自定义组件实现XXXAware
- 在创建对象 的时候,会调用接口规定的方法注入相应组件,
- Aware把Spring底层的一些组件注入到自定义的bean中
bean类
@Component
public class Red implements ApplicationContextAware, BeanNameAware, EmbeddedValueResolverAware {
private ApplicationContext applicationContext;
//获得一个注解的环境
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext=applicationContext;
System.out.println(applicationContext);
}
//可以设置bean的名字
@Override
public void setBeanName(String name) {
System.out.println(name);
}
//传入String值的解析器
@Override
public void setEmbeddedValueResolver(StringValueResolver stringValueResolver) {
String osName = stringValueResolver.resolveStringValue("你好${os.name}");
System.out.println(osName);
}
}
测试类
public class TestAuto {
@Test
public void testAutowired(){
AnnotationConfigApplicationContext applicationContext= new AnnotationConfigApplicationContext(MainConfigAutowired.class);
}
}
测试结果
red
你好Mac OS X
org.springframework.context.annotation.AnnotationConfigApplicationContext@214b199c: startup date [Mon Jul 31 11:27:51 CST 2023]; root of context hierarchy
32、@Profile环境搭建
Profile是Spring为我们提供的可以根据当前环境,动态的激活和切换一系列组件(bean)的功能。
环境:开发环境,测试环境,生产环境,在不同环境下可能链接不同的数据库,因此需要可以根据当前环境,动态的激活和切换一系列组件。
如引不同的数据源,需要导入以下依赖
c3p0和mysql链接驱动
<!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.mysql/mysql-connector-j -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.0.32</version>
</dependency>
创建dbConfig.propreties
db.user=root
db.password=xxxxxxxx
db.driverClass=com.mysql.cj.jdbc.Driver
创建配置类
@PropertySource("classpath:/dbConfig.properties")
@Configuration
public class MainConfigProfile implements EmbeddedValueResolverAware {
@Value("${db.user}")
private String user;
//值解析器
private StringValueResolver valueResolver;
private String driverClass;
@Bean("productDatasource")
public DataSource dataSource(@Value("${db.password}") String password) throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser(user);
dataSource.setPassword(password);
dataSource.setJdbcUrl("jdbc:mysql://localhost8080:3306/fruitdb");
//使用值解析器解析driver
dataSource.setDriverClass(driverClass);
return dataSource;
}
@Bean("testDatasource")
public DataSource dataSourceTest(@Value("${db.password}") String password) throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser(user);
dataSource.setPassword(password);
dataSource.setJdbcUrl("jdbc:mysql://localhost8080:3306/empdb");
dataSource.setDriverClass(driverClass);
return dataSource;
}
@Bean("developmentDatasource")
public DataSource dataSourceDevelopment(@Value("${db.password}") String password) throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser(user);
dataSource.setPassword(password);
dataSource.setJdbcUrl("jdbc:mysql://localhost8080:3306/userDb");
dataSource.setDriverClass(driverClass);
return dataSource;
}
@Override
public void setEmbeddedValueResolver(StringValueResolver stringValueResolver) {
this.valueResolver=stringValueResolver;
this.driverClass=this.valueResolver.resolveStringValue("${db.driverClass}");
}
}
测试类
public class TestAuto {
@Test
public void testAutowired(){
AnnotationConfigApplicationContext applicationContext= new AnnotationConfigApplicationContext(MainConfigProfile.class);
//获取beans的类名数组
String[] beanNamesForType = applicationContext.getBeanNamesForType(DataSource.class);
for (String name: beanNamesForType ) {
System.out.println(name);
}
}
}
测试结果
productDatasource
testDatasource
developmentDatasource
33、@Profile根据环境注册bean
- @Profile:指定组件在哪个环境的情况下才能被注册到容器中,不指定的话,在任何情况下都能注册组件
- 加了环境标识(@Profile)的bean,只有这个环境被激活才能注册到容器中,默认都default标识被注册
- 没有标注环境标识的bean,在任何环境下都是加载的
@Profile("default")
如何激活
1)使用命令行动态参数:在虚拟机参数位置加载-Dspring.profiles.active=test或其他标识
2)代码方式
配置类
@PropertySource("classpath:/dbConfig.properties")
@Configuration
public class MainConfigProfile implements EmbeddedValueResolverAware {
@Value("${db.user}")
private String user;
//值解析器
private StringValueResolver valueResolver;
private String driverClass;
@Profile("test")
@Bean
public Red red(){
return new Red();
}
//定义生产环境
@Profile("product")
@Bean("productDatasource")
public DataSource dataSource(@Value("${db.password}") String password) throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser(user);
dataSource.setPassword(password);
dataSource.setJdbcUrl("jdbc:mysql://localhost8080:3306/fruitdb");
//使用值解析器解析driver
dataSource.setDriverClass(driverClass);
return dataSource;
}
//定义测试环境
@Profile("test")
@Bean("testDatasource")
public DataSource dataSourceTest(@Value("${db.password}") String password) throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser(user);
dataSource.setPassword(password);
dataSource.setJdbcUrl("jdbc:mysql://localhost8080:3306/empdb");
dataSource.setDriverClass(driverClass);
return dataSource;
}
//定义开发环境
@Profile("development")
@Bean("developmentDatasource")
public DataSource dataSourceDevelopment(@Value("${db.password}") String password) throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser(user);
dataSource.setPassword(password);
dataSource.setJdbcUrl("jdbc:mysql://localhost8080:3306/userDb");
dataSource.setDriverClass(driverClass);
return dataSource;
}
@Override
public void setEmbeddedValueResolver(StringValueResolver stringValueResolver) {
this.valueResolver=stringValueResolver;
this.driverClass=this.valueResolver.resolveStringValue("${db.driverClass}");
}
}
测试类
public class TestAuto {
@Test
public void testAutowired(){
//1.获取一个applicationContext
AnnotationConfigApplicationContext applicationContext= new AnnotationConfigApplicationContext(MainConfigProfile.class);
//2.设置激活的环境
applicationContext.getEnvironment().setActiveProfiles("test","product");//设置了两个环境
//3.注册住配置类
applicationContext.register(MainConfigProfile.class);
//4.刷新容器
applicationContext.refresh();
//获取beans的类名数组
String[] beanNamesForType = applicationContext.getBeanNamesForType(DataSource.class);
for (String name: beanNamesForType ) {
System.out.println(name);
}
}
}
测试结果
应该出现test和product两个组件,但在执行refresh的时候报错。GenericApplicationContext does not support multiple refresh attempts: just call ‘refresh’ once
3)不仅可以写在bean上还可以写在类上文章来源:https://www.toymoban.com/news/detail-628840.html
@Profile("development")
@PropertySource("classpath:/dbConfig.properties")
@Configuration
public class MainConfigProfile implements EmbeddedValueResolverAware {
表示只有环境为development的时候,只有是指定的环境的时候,整个配置类里面的所有配置才生效文章来源地址https://www.toymoban.com/news/detail-628840.html
到了这里,关于spring注解驱动开发(二)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!