spring注解驱动开发(二)

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 {@Beanpublic Car car(){return new Car();}
}

测试类


public class testLife {//创建ioc容器AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);@Testpublic 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);@Testpublic 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.....");}//销毁方法@Overridepublic void destroy() throws Exception {System.out.println("cat is destoried ......");}//初始化方法@Overridepublic 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);@Testpublic 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");}//对象创建并赋值之后调用@PostConstructpublic void init(){System.out.println("dog is constructed ......");}//容器移除对象之前@PreDestroypublic void destory(){System.out.println("dog is destoried ......");}
}

测试类

public class testLife {//创建ioc容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);@Testpublic 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 {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("初始化完成前工作调用"+beanName+"=>"+bean);return bean;}@Overridepublic 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);@Testpublic 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;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}
}

创建配置类

@Configuration
public class MainConfigOfPropertyValues {@Beanpublic Person person(){return new Person();}}

测试类

public class TestAno {AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext(MainConfigOfPropertyValues .class);@Testpublic 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 {@Beanpublic 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;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}
}

4、测试类

public class TestAno {AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext(MainConfigOfPropertyValues .class);@Testpublic 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 {@Autowiredprivate BookDAO bookDao;public void print(){System.out.println(bookDao);}
}

controller

@Controller
public class BookController {@Autowiredprivate BookService bookService;
}

配置类

@Configuration
@ComponentScan({"com.atguigu"})
public class MainConfigAutowired {
}

测试类

public class TestAuto {AnnotationConfigApplicationContext applicationContext= new AnnotationConfigApplicationContext(MainConfigAutowired.class);@Testpublic 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 {@Resourceprivate 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 {@Injectprivate 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容易中获取@Autowiredpublic void setCar(Car car){this.car=car;}@Overridepublic String toString() {return "Boss{" +"car=" + car +'}';}
}

Car类


@Component
public class Car {
}

测试 类

public class TestAuto {@Testpublic 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@198d6542ps:两个car对象的地址是一样的
  • 如果只有一个有参构造器,则参数上的@Autowired可以不写,可以从组件中自动获取

30、标注在构造器位置的自动装配

  • 也可以把@Autowried放在有参构造器上
@Component
public class Boss {private Car car;@Autowiredpublic Boss(Car car) {this.car = car;}public Car getCar(){return car;}//标注在方法上,Spring容器 创建当前对象,就会调用方法,完成赋值//方法使用的参数,自定义类型的值从ioc容易中获取//@Autowiredpublic void setCar(Car car){this.car=car;}@Overridepublic 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容易中获取//@Autowiredpublic void setCar(@Autowired Car car){this.car=car;}@Overridepublic 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;//获得一个注解的环境@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext=applicationContext;System.out.println(applicationContext);}//可以设置bean的名字@Overridepublic void setBeanName(String name) {System.out.println(name);}//传入String值的解析器@Overridepublic void setEmbeddedValueResolver(StringValueResolver stringValueResolver) {String osName = stringValueResolver.resolveStringValue("你好${os.name}");System.out.println(osName);}
}

测试类


public class TestAuto {@Testpublic 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");//使用值解析器解析driverdataSource.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;}@Overridepublic void setEmbeddedValueResolver(StringValueResolver stringValueResolver) {this.valueResolver=stringValueResolver;this.driverClass=this.valueResolver.resolveStringValue("${db.driverClass}");}
}

测试类

public class TestAuto {@Testpublic 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")@Beanpublic 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");//使用值解析器解析driverdataSource.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;}@Overridepublic void setEmbeddedValueResolver(StringValueResolver stringValueResolver) {this.valueResolver=stringValueResolver;this.driverClass=this.valueResolver.resolveStringValue("${db.driverClass}");}
}

测试类

public class TestAuto {@Testpublic void testAutowired(){//1.获取一个applicationContextAnnotationConfigApplicationContext 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上还可以写在类上

@Profile("development")
@PropertySource("classpath:/dbConfig.properties")
@Configuration
public class MainConfigProfile implements EmbeddedValueResolverAware {

表示只有环境为development的时候,只有是指定的环境的时候,整个配置类里面的所有配置才生效

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/21806.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【更新】119所院校考研重点勾画更新预告!

截至目前&#xff0c;我已经发布了47篇不同院校的择校分析。发布了87套名校信号考研真题以及119所不同院校的考研知识点重点勾画。 另外为了更好服务已经报名的同学&#xff0c;24梦马全程班也到了收尾的阶段。即将封班&#xff01;需要报名的同学抓紧啦&#xff01; 去年开始…

从excel中提取嵌入式图片的解决方法

1 发现问题 我的excel中有浮动图片和嵌入式图片&#xff0c;但是openpyxl的_image对象只提取到了浮动图片&#xff0c;通过阅读其源码发现&#xff0c;这是因为openpyxl只解析了drawing文件导致的&#xff0c;所以确定需要自己解析 2 解决思路 1、解析出media资源 2、解析…

LeetCode 热题 100 JavaScript--20. 有效的括号

给定一个只包括 ‘(’&#xff0c;‘)’&#xff0c;‘{’&#xff0c;‘}’&#xff0c;‘[’&#xff0c;‘]’ 的字符串 s &#xff0c;判断字符串是否有效。 有效字符串需满足&#xff1a; 左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合。每个右括号都有…

React 路由使用-详细介绍

路由初使用 抽象路由模块 src\page\Article\index.js const Article () > {return (<div><p>文章页</p></div>); };export default Article;src\router\index.js // 导入页面 import Article from "../page/Article"; import Login fr…

MySQL第六七弹,自连接等复杂查询,索引部分知识

一、&#x1f49b; 自连接&#xff1a;自己和自己笛卡尔积&#xff08;奇淫巧技&#xff0c;特殊场景很牛逼&#xff09; SQL&#xff1a;编写条件都是列和列之间的比较&#xff0c;但是SQL无法进行&#xff0c;行与行之间的比较。 如&#xff1a;显示所有java比计算机原理高的…

WebGL系列教程:WebGL基础知识

下面我们来正式学习WebGL开发中的一些基本的概念和知识。 一、HTML画布 为了在 Web 上创建图形应用程序,HTML5 提供了一组丰富的功能,例如 2D Canvas、WebGL、SVG、3D CSS 转换和 SMIL。要编写 WebGL 应用程序,就需要用到 HTML5 的画布元素。 1.1 HTML5 画布 HTML5 的标…

服务端高并发分布式结构演进之路

目录 一、常见概念 1.1基本概念 二、架构演进 2.1单机架构 2.2应用数据分离架构 2.3应用服务集群架构 2.4读写分离 / 主从分离架构 2.5引入缓存 —— 冷热分离架构 2.6垂直分库 2.7业务拆分 —— 微服务 一、常见概念 1.1基本概念 应用&#xff08;Application&am…

问题记录 1 页面初始化触发el-form必填校验

bug: 先编辑table某条数据,然后关闭,再去新增的时候就会触发el-form必填校验, 网上搜了一下是因为 rules里触发的方式为change时,赋值数据的格式不一致导致触发校验, 最后也没找到正确的解决方法, 只能用很low方式去解决了 方案1. 把trigger改为 blur 失焦后触发 方案2. 初始化…

2023华数杯数学建模C题思路分析 - 母亲身心健康对婴儿成长的影响

# 1 赛题 C 题 母亲身心健康对婴儿成长的影响 母亲是婴儿生命中最重要的人之一&#xff0c;她不仅为婴儿提供营养物质和身体保护&#xff0c; 还为婴儿提供情感支持和安全感。母亲心理健康状态的不良状况&#xff0c;如抑郁、焦虑、 压力等&#xff0c;可能会对婴儿的认知、情…

硬件串口通信协议学习(UART、IIC、SPI、CAN)

0.前言 学习资料&#xff1a;江协科技的个人空间-江协科技个人主页-哔哩哔哩视频 通信的目的&#xff1a;将一个设备的数据传送到另一个设备&#xff0c;扩展硬件系统通信协议&#xff1a;制定通信的规则&#xff0c;通信双方按照协议规则进行数据收发 全双工&#xff1a;通信…

腾讯云COS+PicGO+截图工具+Obsidian+Typora+蚁小二:打造丝滑稳定的Markdown写作和分发环境

目录 背景 工具说明 腾讯云COS PicGO图片上传工具 截图工具 Obsidian Typora 蚁小二 首次配置完整演示步骤 腾讯云COS PicGO图片上传工具 截图工具 Obsidian Typora 蚁小二 使用总结&#xff08;简单又丝滑的编辑步骤&#xff09; 背景 很久很久以前&#xff…

【蓝图】p47下车减速功能

p47下车减速功能 p47下车减速功能加速功能下车减速功能 p47下车减速功能 加速功能 上图是ue自带的加速功能&#xff0c;检测到按w时输入轴会传1给设置油门输入&#xff0c;就会加速 所以&#xff0c;减速也可以通过蓝图反方向制作 下车减速功能 打开Sedan蓝图类的上下车图表…

Java网络编程

目录 1.网络编程 2.Echo模型&#xff08;服务器与客户端实现通信&#xff09; 3.BIO处理模型(实现多用户访问同个服务器) 4.UDP程序 1.网络编程 有两种通信模型 C/S(Client/Server)基于客户端和服务器端&#xff0c;实现代码时候需要实现客户端与服务器端 B/S(Browser/S…

QtWebApp开发https服务器,完成客户端与服务器基于ssl的双向认证

引言&#xff1a;所谓http协议&#xff0c;本质上也是基于TCP/IP上服务器与客户端请求和应答的标准&#xff0c;web开发中常用的http server有apache和nginx。Qt程序作为http client可以使用QNetworkAccessManager很方便的进行http相关的操作。Qt本身并没有http server相关的库…

【算法第十四天7.28】二叉树的最大深度,二叉树的最小深度 ,完全二叉树的节点个数

链接力扣104-二叉树的最大深度 思路 class Solution {public int maxDepth(TreeNode root) {if(root null) return 0;if(root.left null) return maxDepth(root.right) 1;if(root.right null) return maxDepth(root.left) 1;int max Math.max(maxDepth(root.left),maxD…

使用Git在GitHub上部署静态页面

在GitHub中&#xff0c;我们可以将自己的静态页面部署到GitHub中&#xff0c;它会给我们提供一个地址使得我们的页面变成一个真正的网站&#xff0c;可以供用户访问。 一、在GitHub下创建仓库 二、将项目部署到GitHub上 1. 初始化Git仓库 2. 提交代码 3. 关联远程仓库 在Gi…

【java安全】原生反序列化利用链JDK7u21

文章目录 【java安全】原生反序列化利用链JDK7u21前言原理equalsImpl()如何调用equalsImpl()&#xff1f;HashSet通过反序列化间接执行equals()方法如何使hash相等&#xff1f; 思路整理POCGadget为什么在HashSet#add()前要将HashMap的value设为其他值&#xff1f; 【java安全】…

WSL1升级为WSL2

首先需要启用组件 使用管理员打开Powershell并运行 Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform启用后会要求重启计算机 从https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi获取WSL2 Linux内核更新包&#xff0c;…

HTML 是什么?它的全称是什么?

聚沙成塔每天进步一点点 专栏简介HTML是什么&#xff1f;HTML的全称是什么&#xff1f;写在最后 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff01;这个专栏是为那些对We…

ad+硬件每日学习十个知识点(16)23.7.27 (总线保持、lin报文、逻辑器件手册解读)

文章目录 1.总线保持是怎么实现的&#xff1f;有什么需要注意的&#xff08;驱动电流和电阻&#xff09;&#xff1f;2.LIN报文3.芯片datasheet的features、applications、description看完&#xff0c;应该能大致判断逻辑器件能否满足我们的要求。4.什么是逻辑器件的传输延时&a…