Spring注解开发

浅尝Spring注解开发,基于Spring 4.3.12

包含自定义扫描组件、自定义导入组件、手动注册组件、自动注入方法和参数、使用Spring容器底层组件等

配置

@Configuration配置类

告诉Spring这是一个配置类,代替以前的xml文件,配置类=配置文件

@Configuration
public class MainConfig { //给容器中注册一个Bean;类型为返回值的类型,id默认是用方法名作为id
@Bean("person")
public Person person01(){
return new Person("lisi", 20);
} }

注册组件

给容器中注册组件有以下方法:

  1. 包扫描+组件标注注解(@Controller/@Service/@Repository/@Component)[自己写的类]

  2. @Bean[导入的第三方包里面的组件]

  3. @Import[快速给容器中导入一个组件]

    1. @Import(要导入到容器中的组件);容器中就会自动注册这个组件,id默认是全类名
    2. ImportSelector:返回需要导入的组件的全类名数组;
    3. ImportBeanDefinitionRegistrar:手动注册bean到容器中
  4. 使用Spring提供的 FactoryBean(工厂Bean);

    1. 默认获取到的是工厂bean调用getObject创建的对象

    2. 要获取工厂Bean本身,我们需要给id前面加一个&

      如:&colorFactoryBean

@Bean注册

给容器中注册一个Bean,类型为返回值的类型,id默认是用方法名作为id,也可以指定id

	@Bean("person")//指定Bean id
public Person person01(){
return new Person("lisi", 20);
}

IoC容器

创建一个IoC容器AnnotationConfigApplicationContext,传入配置类,获取Bean

//创建IoC容器
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class); //获取Bean对象
Person bean = applicationContext.getBean(Person.class); //获取所以Person类型Bean的名字
String[] namesForType = applicationContext.getBeanNamesForType(Person.class);
for (String name : namesForType) {
System.out.println(name);
}

@ComponentScan扫描组件

@Component(包括@Controller@Service@Repository和@Bean目的一样)和@ComponentScan的区别

  • @Component:将普通JavaBean实例化到spring容器中,Spring容器统一管理,用起来不用自己new了,相当于配置文件中的<bean id="" class=""/>
  • @ComponentScan:一般用在核心配置类,由你来定义哪些包需要被扫描。
  • @Component标在类上,@Bean标在方法上,两者使用在普通类或方法上时,都不起作用,只有放在配置类中才能注册组件(@Bean可以在写在配置类中,@Component由于本身标在类上,所以不能写在类中),而@ComponentScan就是给了@Component一种注册进容器的办法,只要扫描到@Component标注的类就直接注册进容器
  • 自动扫描组件,可有多个@ComponentScan,或一个@ComponentScans

  • value:指定要扫描的包

    所有指定的包下的类都要进入扫描,是否能够通过,需要看下面使用了什么规则,有排除、包含、指定类型、正则、和自定义规则,自定义规则通过反射获取包中所有类,然后判断是否能够进入ioc容器中。

  • excludeFilters = Filter[] :指定扫描的时候按照什么规则排除那些组件

  • includeFilters = Filter[] :指定扫描的时候只需要包含哪些组件

    • ​ FilterType.ANNOTATION:按照注解
    • ​ FilterType.ASSIGNABLE_TYPE:按照给定的类型
    • ​ FilterType.ASPECTJ:使用ASPECTJ表达式
    • ​ FilterType.REGEX:使用正则指定
  • ​ FilterType.CUSTOM:使用自定义规则,需要TypeFilter实现类

  • useDefaultFilters:不使用默认的 Filter进行扫描。在includeFilters中使用,取消默认扫描,指定扫描对象,可以在SpringMVC中使用

@ComponentScan(value="com.atguigu",includeFilters = {

    //扫描指定注解
@Filter(type=FilterType.ANNOTATION,classes={Controller.class}), //扫描指定类型
@Filter(type=FilterType.ASSIGNABLE_TYPE,classes={BookService.class}), //扫描自定义
@Filter(type=FilterType.CUSTOM,classes={MyTypeFilter.class}) },useDefaultFilters = false)

FilterType.CUSTOM:使用自定义规则,需要实现TypeFilter接口

public class MyTypeFilter implements TypeFilter {

	/**
* metadataReader:读取到的当前正在扫描的类的信息
* metadataReaderFactory:可以获取到其他任何类信息的
*/
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
throws IOException {
// TODO Auto-generated method stub
//获取当前类注解的信息
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
//获取当前正在扫描的类的类信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
//获取当前类资源(类的路径)
Resource resource = metadataReader.getResource(); String className = classMetadata.getClassName();
System.out.println("--->"+className);
//根据自定义规则,只让类名中包含er的类进入ioc容器。
if(className.contains("er")){
return true;
}
return false;
} }

@Scope作用域

调整作用域,单实例,多实例

  • prototype:多实例的:ioc容器启动并不会去调用方法创建对象放在容器中。每次获取的时候才会调用方法创建对象;
  • singleton:单实例的(默认值):ioc容器启动会调用方法创建对象放到ioc容器中。以后每次获取就是直接从容器(map.get())中拿
  • request:同一次请求创建一个实例。web环境中
  • session:同一个session创建一个实例。web环境中
	@Scope("singleton")
@Lazy
@Bean("person")
public Person person(){
System.out.println("给容器中添加Person....");
return new Person("张三", 25);
}

@Lazy懒加载

  • 在单实例bean应用:默认在容器启动的时候创建对象,配置懒加载后,容器启动不创建对象。第一次使用(获取)Bean创建对象,并初始化,仍是单实例。

@Conditional条件注册Bean

指定条件向容器中注入Bean

@Conditional({Condition}) : 按照一定的条件进行判断,满足条件才将Bean注册进容器,可以标在@Bean方法和@Configuration类上

  • 添加了@Conditional({Condition}) 的Bean方法或配置Bean的类,只有在满足Condition中的条件才能执行(装配Bean)
  • Condition:需要实现Condition接口的条件类,可以判断容器中的bean注册情况,也可以给容器中注册bean

Condition条件实现类

创建两个判断条件,判断系统是Windows还是Linux,自定义注册不同的Bean,注解可以标在方法上,也可以标在类上

  • 实现Condition接口
//判断是否linux系统
public class LinuxCondition implements Condition { /**
* ConditionContext:判断条件能使用的上下文(环境)
* AnnotatedTypeMetadata:注释信息
*/
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// TODO是否linux系统
//1、能获取到ioc使用的beanfactory
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
//2、获取类加载器
ClassLoader classLoader = context.getClassLoader();
//3、获取当前环境信息
Environment environment = context.getEnvironment();
//4、获取到bean定义的注册类
BeanDefinitionRegistry registry = context.getRegistry();
//5、获取系统名
String property = environment.getProperty("os.name"); //这里判断容器中的bean注册情况,也可以使用BeanDefinitionRegistry.registerBeanDefinition()给容器中注册bean
boolean definition = registry.containsBeanDefinition("person"); //判断系统名是否包含linux
if(property.contains("linux")){
return true;
}
return false;
}
}
//判断是否windows系统
public class WindowsCondition implements Condition { @Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
Environment environment = context.getEnvironment();
String property = environment.getProperty("os.name");
if(property.contains("Windows")){
return true;
}
return false;
} }

标在方法上

  • 标在注册Bean/组件的方法上
@Configuration
public class MainConfig2 {
/**
* @Conditional({Condition}) : 按照一定的条件进行判断,满足条件给容器中注册bean
*
* 如果系统是windows,给容器中注册Person类型("bill")
* 如果是linux系统,给容器中注册Person类型("linus")
*/
@Conditional(WindowsCondition.class)
@Bean("bill")
public Person person01(){
return new Person("Bill Gates",62);
} @Conditional(LinuxCondition.class)
@Bean("linus")
public Person person02(){
return new Person("linus", 48);
}
}

标在类上

//类中组件统一设置。满足当前条件,这个类中配置的所有bean注册才能生效;
@Conditional({WindowsCondition.class})
@Configuration
public class MainConfig2 {
//...
}

测试方法

  • 使用,可配置VM参数:-Dos.name=linux 测试

    public class IOCTest {
    
    	AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
    
    	@Test
    public void test03(){
    //获取所有Person类型的Bean名字
    String[] namesForType = applicationContext.getBeanNamesForType(Person.class);
    //获取运行时环境
    ConfigurableEnvironment environment = applicationContext.getEnvironment();
    //动态获取环境变量的值;Windows 10
    String property = environment.getProperty("os.name");
    System.out.println(property);
    for (String name : namesForType) {
    System.out.println(name);
    } //获取所有Person类型Bean的对象,名字是否是lunus或bill
    Map<String, Person> persons = applicationContext.getBeansOfType(Person.class);
    System.out.println(persons); }
    }

@Import注册

@Import的三种方法都是写在@Import注解中,都是向容器中导入组件

  • @Import(要导入到容器中的组件):容器中就会自动注册这个组件,id默认是全类名
  • ImportSelector:返回需要导入的组件的全类名数组
  • ImportBeanDefinitionRegistrar:手动注册bean到容器中

@Import

  • @Import(要导入到容器中的组件):容器中就会自动注册这个组件,id默认是全类名com.xxx.bean.Color

    @Configuration
    @Import({Color.class,Red.class})
    //@Import导入组件,id默认是组件的全类名
    public class MainConfig2 {
    /...
    }
  • 测试

    public class IOCTest {
    
    	AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
    
    	//输出:除了Spring自己的Bean还有Import的Color、Red
    @Test
    public void testImport(){
    printBeans(applicationContext);
    } //输出容器中所有的Bean名
    private void printBeans(AnnotationConfigApplicationContext applicationContext){
    String[] definitionNames = applicationContext.getBeanDefinitionNames();
    for (String name : definitionNames) {
    System.out.println(name);
    }
    }
    }

ImportSelector注册

  • 接口,可以选择注册指定的类,返回需要导入的组件的全类名数组;

    //自定义逻辑返回需要导入的组件
    public class MyImportSelector implements ImportSelector { //返回值,就是到导入到容器中的组件全类名
    //AnnotationMetadata:当前标注@Import注解的类的所有注解信息
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
    // TODO Auto-generated method stub
    //importingClassMetadata
    //方法不要返回null值,返回的值就是要注册的组件
    return new String[]{"com.atguigu.bean.Blue","com.atguigu.bean.Yellow"};
    } }
  • 配置

    @Configuration
    //@Import导入组件,MyImportSelector是自定义选择的Bean
    @Import({Color.class,Red.class,MyImportSelector.class})
    public class MainConfig2 {
    //...
    }
  • 测试

    public class IOCTest {
    
    	AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
    
    	//输出:除了Spring自己的Bean还有MyImportSelector选中的Bean
    @Test
    public void testImport(){
    printBeans(applicationContext);
    Blue bean = applicationContext.getBean(Blue.class);
    System.out.println(bean);
    } //输出容器中所有的Bean名
    private void printBeans(AnnotationConfigApplicationContext applicationContext){
    String[] definitionNames = applicationContext.getBeanDefinitionNames();
    for (String name : definitionNames) {
    System.out.println(name);
    }
    }
    }

ImportBeanDefinitionRegistrar

自定义注入组件,在Spring注解源码中使用

  • 实现接口,指定规则,手动注入新的bean

    public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    
    	/**
    * AnnotationMetadata:当前类的注解信息
    * BeanDefinitionRegistry内有BeanDefinition注册类,所有Bean都在这里注册;
    * 把所有需要添加到容器中的bean
    * 调用方法BeanDefinitionRegistry.registerBeanDefinition手工注册进来
    */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { //判断是否有红色,蓝色
    boolean definition = registry.containsBeanDefinition("com.atguigu.bean.Red");
    boolean definition2 = registry.containsBeanDefinition("com.atguigu.bean.Blue");
    //如果存在
    if(definition && definition2){
    //指定Bean定义信息BeanDefinition类型;(Bean的类型,Bean作用域等...)
    RootBeanDefinition beanDefinition = new RootBeanDefinition(RainBow.class);
    //注册一个新Bean,指定bean名
    registry.registerBeanDefinition("rainBow", beanDefinition);
    }
    } }
  • 配置

    @Configuration
    //MyImportBeanDefinitionRegistrar是手动注册到Bean容器中,可以指定规则
    @Import({Color.class,Red.class,MyImportSelector.class,MyImportBeanDefinitionRegistrar.class})
    //@Import导入组件,id默认是组件的全类名
    public class MainConfig2 {
    //...
    }
  • 测试

    public class IOCTest {
    
    	AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
    
    	//输出:除了Spring自己的Bean还有手动定制规则新导入的rainBow
    @Test
    public void testImport(){
    printBeans(applicationContext);
    Blue bean = applicationContext.getBean(Blue.class);
    System.out.println(bean);
    } //输出容器中所有的Bean名
    private void printBeans(AnnotationConfigApplicationContext applicationContext){
    String[] definitionNames = applicationContext.getBeanDefinitionNames();
    for (String name : definitionNames) {
    System.out.println(name);
    }
    }
    }

FactoryBean注册

多用于第三方组件

接口,给容器中注入组件,使用Spring提供的 FactoryBean(工厂Bean)创建的Bean

  1. 默认获取到的是工厂bean调用getObject创建的对象,而不是工厂对象本身

  2. 要获取工厂Bean本身,我们需要给id前面加一个"&"如:context.getBean("&xxx")

  • 实现接口,创建工厂

    //创建一个Spring定义的FactoryBean
    public class ColorFactoryBean implements FactoryBean<Color> { //返回一个Color对象,这个对象会添加到容器中
    @Override
    public Color getObject() throws Exception {
    // TODO Auto-generated method stub
    System.out.println("ColorFactoryBean...getObject...");
    return new Color();
    } @Override
    public Class<?> getObjectType() {
    // TODO Auto-generated method stub
    return Color.class;
    } //是单例?
    //true:这个bean是单实例,在容器中保存一份
    //false:多实例,每次获取都会创建一个新的bean;
    @Override
    public boolean isSingleton() {
    // TODO Auto-generated method stub
    return false;
    } }
  • 配置

    @Configuration
    public class MainConfig2 { /**
    * 给容器中注册组件;
    * 4)、使用Spring提供的 FactoryBean(工厂Bean);
    * 1)、默认获取到的是工厂bean调用getObject创建的对象
    * 2)、要获取工厂Bean本身,我们需要给id前面加一个&
    * &colorFactoryBean
    */
    @Bean
    public ColorFactoryBean colorFactoryBean(){
    return new ColorFactoryBean();
    } }
  • 测试

    public class IOCTest {
    
    	AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
    
    	//直接使用输出的不是工厂本身,而是工厂内getObject创建的Bean
    @Test
    public void testImport(){ //工厂Bean获取的是调用getObject创建的Color对象
    Object bean2 = applicationContext.getBean("colorFactoryBean");
    Object bean3 = applicationContext.getBean("colorFactoryBean");
    //输出:com.xxx.bean.Color
    System.out.println("bean的类型:"+bean2.getClass());
    System.out.println(bean2 == bean3); //输出:com.xxx.bean.ColorFactoryBean
    Object bean4 = applicationContext.getBean("&colorFactoryBean");
    System.out.println(bean4.getClass());
    } //输出容器中所有的Bean名
    private void printBeans(AnnotationConfigApplicationContext applicationContext){
    String[] definitionNames = applicationContext.getBeanDefinitionNames();
    for (String name : definitionNames) {
    System.out.println(name);
    }
    }
    }

属性赋值

@Value赋值

基本数值

public class Person {

	//使用@Value赋值;
//1、基本数值
@Value("张三")
private String name;
}

SpEL表达式 #{}

public class Person {

	//使用@Value赋值;
//1、基本数值
//2、可以写SpEL; #{} @Value("张三")
private String name; //计算后值为18
@Value("#{20-2}")
private Integer age;
}

@PropertySource配置文件取值

读取properties配置文件的值,例如读取数据库连接信息

  • 读取文件
  • 取值

读取配置文件

使用@PropertySource读取外部配置文件

//使用@PropertySource读取外部配置文件中的k/v保存到运行的环境变量中;加载完外部的配置文件以后使用${}取出配置文件的值
@PropertySource(value={"classpath:/person.properties"})
@Configuration
public class MainConfigOfPropertyValues { @Bean
public Person person(){
return new Person();
}
}

配置文件person.properties

person.nickName=法外狂徒

配置文件取值${}

取出配置文件properties中的值

public class Person {

	//使用@Value赋值;
//1、基本数值
//2、可以写SpEL; #{}
//3、可以写${};取出配置文件【properties】中的值(在运行环境变量里面的值) @Value("张三")
private String name;
@Value("#{20-2}")
private Integer age; @Value("${person.nickName}")
private String nickName;
}

运行时环境变量取值

运行时properties配置文件加载进环境变量,可以直接取出

public class IOCTest_PropertyValue {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfPropertyValues.class);
@Test
public void test01(){
//直接从applicationContext容器中获取运行时环境变量ConfigurableEnvironment
ConfigurableEnvironment environment = applicationContext.getEnvironment();
//取值
String property = environment.getProperty("person.nickName");
System.out.println(property);
applicationContext.close();
}
}

自动装配

AutowiredAnnotationBeanPostProcessor:解析完成自动装配功能

几种自动装配:

  1. @Autowired:自动注入
  2. Spring还支持使用@Resource(JSR250)和@Inject(JSR330)[java规范的注解]
  3. @Autowired:构造器,参数,方法,属性,都是从容器中获取参数组件的值
  4. 自定义组件想要使用Spring容器底层的一些组件(ApplicationContext,BeanFactory,xxx)

@Autowired

自动注入:

  1. 默认优先按照类型去容器中找对应的组件,同applicationContext.getBean(BookDao.class),找到就赋值
  2. 如果找到多个相同类型的组件,再将属性的名称(@Bean的value或者方法名)作为组件的id去容器中查找,同applicationContext.getBean("bookDao")
  3. 如果都相同就会报错

@Qualifier

指定装配:

  • @Qualifier("bookDao"):使用@Qualifier指定需要装配的组件的id,而不是使用属性名自动装配,默认一定要将属性赋值好,没有就会报错;
  • 如果没有就不装配,可以使用@Autowired(required=false)表示

@Primary

默认装配:

  • @Primary:让Spring进行自动装配的时候,默认使用首选的bean;
  • 也可以继续使用@Qualifier指定需要装配的bean的名字

下面是两个Bean的情况

@Configuration
@ComponentScan({"com.atguigu.service","com.atguigu.dao",
"com.atguigu.controller","com.atguigu.bean"})
public class MainConifgOfAutowired { @Primary//首选装配
@Bean("bookDao2")
public BookDao bookDao(){
BookDao bookDao = new BookDao();
bookDao.setLable("2");
return bookDao;
}
}
@Service
public class BookService { @Qualifier("bookDao")//指定,大于首选
@Autowired(required=false)//可以不存在
private BookDao bookDao;
}

@Resource

  • 可以和@Autowired一样实现自动装配功能,默认是按照组件名称进行装配的

  • 没有能支持@Primary和@Autowired(reqiured=false)的功能

  • @Autowired跟spring强耦合,如果换成了JFinal等其他框架,功能就会失效。而@Resource是JSR-250提供的,它是Java标准,绝大部分框架都支持

	@Resource(name="bookDao2")
private BookDao bookDao;

@Inject

  • 需要导入javax.inject的包,和@Autowired的功能一样。没有@Autowired(reqiured=false)的功能

  • @Autowired:Spring定义的, @Resource、@Inject都是java规范,@Autowried不能脱离Spring

	@Inject
private BookDao bookDao;

@Autowired注入方法,参数

@Autowired:构造器,参数,方法,属性都是从容器中获取参数组件的值

使用[@Bean+方法参数]的方式在SpringBoot中使用很多,在使用各种配置时,只配置方法,方法中的参数直接从容器中获取

  1. [标注在方法位置]:@Bean+方法参数,参数从容器中获取,默认不写@Autowired效果是一样的,都能自动装配
  2. [标在构造器上]:如果组件只有一个有参构造器,这个有参构造器的@Autowired可以省略,参数位置的组件还是可以自动从容器中获取
  3. 放在参数位置

方法上

  • @Autowired直接标在方法上

    	@Autowired
    //标注在方法,Spring容器创建当前对象,就会调用方法,完成赋值;
    //方法使用的参数,自定义类型的值从ioc容器中获取
    public void setCar(Car car) {
    this.car = car;
    }
  • 如果是@Bean标注的方法,参数位置不标@Autowired,参数也可以自动装配,都是从容器中获取

    	/**
    * @Bean标注的方法创建对象的时候,方法参数的值从容器中获取
    * @param car car也是从容器中获取的值,前提是car已经注入容器
    * @return
    */
    @Bean
    public Color color(Car car){
    Color color = new Color();
    color.setCar(car);
    return color;
    }

构造器

  • 标在构造器上

  • 如果组件只有一个有参构造器,这个有参构造器的@Autowired可以省略,参数位置的组件还是可以自动从容器中获取

    //默认加在ioc容器中的组件,容器启动会调用无参构造器创建对象,再进行初始化赋值等操作
    @Component
    public class Boss { private Car car; //构造器要用的组件,都是从容器中获取
    //@Autowired
    public Boss(Car car){
    this.car = car;
    System.out.println("Boss...有参构造器");
    }
    }

参数上

  • 标在参数前

    	public void setCar(@Autowired  Car car) {
    this.car = car;
    }

Aware使用Spring底层组件

  • 自定义组件想要使用Spring容器底层的一些组件(如:ApplicationContext,BeanFactory,xxx)只要自定义组件实现xxxAware

  • 在创建对象的时候,会调用接口规定的方法注入相关组件,把Spring底层一些组件注入到自定义的Bean中

  • xxxAware:对应功能使用xxxProcessor

    ApplicationContextAware==>ApplicationContextAwareProcessor

    实现过程在BeanPostProcessor后置处理器中

使用不同的底层组件

@Component
public class Red implements ApplicationContextAware,BeanNameAware,EmbeddedValueResolverAware { private ApplicationContext applicationContext; //使用IOC
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
// TODO Auto-generated method stub
System.out.println("传入的ioc:"+applicationContext);
this.applicationContext = applicationContext;
} //使用BeanName
@Override
public void setBeanName(String name) {
// TODO Auto-generated method stub
System.out.println("当前bean的名字:"+name);
} //使用EmbeddedValueResolve解析组件
@Override
public void setEmbeddedValueResolver(StringValueResolver resolver) {
// TODO Auto-generated method stub
String resolveStringValue = resolver.resolveStringValue("你好 ${os.name} 我是 #{20*18}");
System.out.println("解析的字符串:"+resolveStringValue);
} }

@Profile环境标识

@Profile:Spring为我们提供的可以根据当前环境,动态的激活和切换一系列组件的功能;

环境:开发环境、测试环境、生产环境,分别对应:

数据源:devDataSource、testDataSource、prodDataSource

@Profle:指定组件在哪个环境的情况下才能被注册到容器中,不指定,任何环境下都能注册这个组件

  • 标注

    1. 加了环境标识的bean,只有这个环境被激活的时候才能注册到容器中。默认是default环境
    2. 写在配置类上,只有是指定的环境的时候,整个配置类里面的所有配置才能开始生效
    3. 没有标注环境标识的bean,在任何环境下都是加载的;
  • 使用
    1. 如果对Bean标注了@Profile("default"),即使不激活,也默认使用此环境。即使标注了,如果没有对应的环境则都不激活,除了"default"
    2. 在启动时添加VM参数-Dspring.profiles.active=test,会使用此环境
    3. 不使用有参的AnnotationConfigApplicationContext创建ioc,使用无参构造器,在注册配置类之前设置激活环境。
    4. [SpringBoot]在类上使用注解@ActiveProfiles("test")激活

创建多种数据源环境匹配不同数据库

//使用多种方法读取properties配置文件信息
//第一种方法读取配置文件
@PropertySource("classpath:/dbconfig.properties")
@Configuration
public class MainConfigOfProfile implements EmbeddedValueResolverAware{ //第二种方法读取配置文件
@Value("${db.user}")
private String user; private StringValueResolver valueResolver; private String driverClass; //普通的Bean,任何时候都可以加载进容器
@Bean
public Yellow yellow(){
return new Yellow();
} //测试环境标识
@Profile("test")
//@Profile("default")
@Bean("testDataSource")
public DataSource dataSourceTest(@Value("${db.password}")String pwd) throws Exception{
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser(user);
dataSource.setPassword(pwd);
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
dataSource.setDriverClass(driverClass);
return dataSource;
} //开发环境标识
@Profile("dev")
@Bean("devDataSource")
public DataSource dataSourceDev(@Value("${db.password}")String pwd) throws Exception{
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser(user);
dataSource.setPassword(pwd);
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/ssm_crud");
dataSource.setDriverClass(driverClass);
return dataSource;
} //生产环境标识
@Profile("prod")
@Bean("prodDataSource")
public DataSource dataSourceProd(@Value("${db.password}")String pwd) throws Exception{
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser(user);
dataSource.setPassword(pwd);
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/scw_0515"); dataSource.setDriverClass(driverClass);
return dataSource;
} //第三种方法读取配置文件,解析组件读取配置文件
@Override
public void setEmbeddedValueResolver(StringValueResolver resolver) {
// TODO Auto-generated method stub
this.valueResolver = resolver;
driverClass = valueResolver.resolveStringValue("${db.driverClass}");
} }

测试

//激活环境
public class IOCTest_Profile { //1、使用命令行动态参数: 在虚拟机参数位置加载 -Dspring.profiles.active=test
//2、代码的方式激活某种环境;
@Test
public void test01(){
//1、创建一个applicationContext
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext();
//2、设置需要激活的环境
applicationContext.getEnvironment().setActiveProfiles("dev");
//3、注册主配置类
applicationContext.register(MainConfigOfProfile.class);
//4、启动刷新容器
applicationContext.refresh(); //获取被激活注册容器的数据源名字
String[] namesForType = applicationContext.getBeanNamesForType(DataSource.class);
for (String string : namesForType) {
System.out.println(string);
} //普通Bean不受影响,一直可用
Yellow bean = applicationContext.getBean(Yellow.class);
System.out.println(bean);
applicationContext.close();
}
}

输出

devDataSource
com.atguigu.bean.Yellow@1ab3a8c8

最新文章

  1. PHP系统声明式事务处理
  2. MyBatis持久层框架使用总结
  3. PHP 模拟POST请求
  4. System V进程间通信
  5. w3m浏览器 for Linux
  6. winform插入sql的事务处理
  7. eclipse快速收缩展开代码
  8. 怎么修改电脑MAC地址 电脑MAC地址修改图文教程
  9. xml使用系统整理
  10. passwnger
  11. JDK Linux环境配置
  12. MySQL的用户密码过期功能详解
  13. thymeleaf模板引擎入门
  14. 自定义省市选择器 微信小程序多列选择器
  15. 新手级配置 react react-router4.0 redux fetch sass
  16. gevent程序员指南
  17. 第五节: Quartz.Net五大构件之Trigger的四大触发类
  18. 将pucharm与anaconda配合使用
  19. FATAL Fatal error during KafkaServerStable startup. Prepare to shutdown (kafka.server.KafkaServerStartable) java.io.FileNotFoundException: /tmp/kafka-logs/.lock (Permission denied)
  20. Quartz2D简单图形

热门文章

  1. JDBC操作数据库的步骤 ?
  2. spring cloud 断路器的作用是什么?
  3. JRE、JDK、JVM 及 JIT 之间有什么不同?
  4. Pandas数据统计函数
  5. WordPress 网站开发“微信小程序“实战(三)
  6. POP3:基于命令行的电子邮件(EMail)在线查看和批量下载工具
  7. DOM节点的使用(常用方法+代码)
  8. Spring Security 一键接入验证码登录和小程序登录
  9. 面试官:Zookeeper集群怎么搭建?
  10. SSM实现个人博客-day03