spring注解驱动开发(二)

这篇具有很好参考价值的文章主要介绍了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 {

  @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上还可以写在类上

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

表示只有环境为development的时候,只有是指定的环境的时候,整个配置类里面的所有配置才生效文章来源地址https://www.toymoban.com/news/detail-628840.html

到了这里,关于spring注解驱动开发(二)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java企业级开发学习笔记(4.4)Spring Boot加载自定义配置文件

    创建 Spring Boot 项目 单击【创建】按钮 在 resources 里创建 myconfig.properties 文件 设置文件编码 设置学生的四个属性值 在 cn.kox.boot 包里创建config子包,在子包里创建 StudentConfig 打开自带的测试类 ConfigDemo01ApplicationTests 注入学生配置实体,创建 testStudentConfig() 测试方法,在里面输

    2024年02月08日
    浏览(48)
  • JAVA后端开发面试基础知识(八)——Spring

    Spring是一个轻量级Java开发框架 我们一般说 Spring 框架指的都是 Spring Framework,它是很多模块的集合,使用这些模块可以很方便地协助我们进行开发,比如说 Spring 支持 IoC(Inverse of Control:控制反转) 和 AOP(Aspect-Oriented Programming:面向切面编程)、可以很方便地对数据库进行访问、

    2024年03月10日
    浏览(74)
  • Spring-2-深入理解Spring 注解依赖注入(DI):简化Java应用程序开发

      掌握纯注解开发依赖注入(DI)模式 学习使用纯注解进行第三方Bean注入 问题导入 思考:如何使用注解方式将Bean对象注入到类中 1.1 使用@Autowired注解开启自动装配模式(按类型) 说明:不管是使用配置文件还是配置类,都必须进行对应的Spring注解包扫描才可以使用。@Autowired默

    2024年02月14日
    浏览(58)
  • spring注解驱动开发(一)

    Spring常用注解(绝对经典) 1、需要导入的spring框架的依赖 2、@Configuration 设置类为配置类 3、AnnotationConfigApplicationContext 通过配置类获取上下文环境applicationContext 可以通过getBeanDefinitionNames()获得配置类中配置的各类Bean 也可以使用getBeanNamesForType()通过类型来获得bean的name(id)

    2024年02月14日
    浏览(38)
  • spring注解驱动开发(二)

    17、Bean的生命周期 bean的生命周期:bean的创建—初始化—销毁的过程 容器负责管理bean的生命周期 我们可以自定义初始化和销毁方法,容器在bean进行到当前生命周期的时候来调用我们自定义的初始化和销毁方法 构造(对象创建) 单实例:在容器启动时创建对象 多实例:在每

    2024年02月14日
    浏览(39)
  • Spring注解驱动开发(二)

    注:此笔记为尚硅谷Spring注解驱动教程(雷丰阳源码级讲解)学习笔记,并同时参考[https://blog.csdn.net/xjhqre/article/details/123264069]博主文章,其中包含个人的笔记和理解,仅做学习笔记之用。 简述: 1、实例化一个Bean--也就是我们常说的new; 2、按照Spring上下文对实例化的Bean进

    2024年02月03日
    浏览(40)
  • Java SE 学习笔记(十八)—— 注解、动态代理

    Java 注解(Annotation)又称Java标注,是JDK 5.0引入的一种注释机制,Java语言中的类、构造器、方法、成员变量、参数等都可以被注解进行标注,至于到底做何种处理由业务需求来决定。 例如: JUnit 框架中,标记了注解 @Test 的方法就可以被当成测试方法执行,而没有标记的就不

    2024年02月08日
    浏览(39)
  • Java企业级信息系统开发学习笔记(4.2)Spring Boot项目单元测试、热部署与原理分析

    该文章主要为完成实训任务,详细实现过程及结果见【http://t.csdn.cn/pG623】 1. 添加测试依赖启动器和单元测试 修改pom.xml文件,添加依赖 刷新项目依赖 2. 创建测试类与测试方法 在 src/test/java 里创建 cn.kox.boot 包,创建测试类 TestHelloWorld01 给测试类添加测试启动器注解与Spring

    2024年02月10日
    浏览(57)
  • spring注解驱动开发(BEAN注册方式与生命周期)

    目录 容器中注册BEAN的方式 BEAN生命周期 包扫描+组件标注注解 @ComponentScan(basePackages = {\\\"com.an.spring.condition\\\"}) @Service @Component @Controller @Repository @BEan方式【导入第三方包里面的组件】 @Import快速给容器中导入一个组件。 1)、@IMport(要导入到容器中的组件),容器就会注入这个组

    2024年02月07日
    浏览(55)
  • Spring注解驱动开发之常用注解案例_告别在XML中配置Bean

    注解驱动开发就是不再使用Spring的bean.xml文件,改为纯使用注解的方式开发 @Configuration 此注解为配置类注解,相当于spring.xml文件,即配置类==配置文件 @Bean 给容器中注册一个Bean;类型为返回值的类型,id默认是用方法名作为id 示例 Person类(后续注解配置类中都会以此类举例),

    2024年01月21日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包