浅尝Spring注解开发_自定义注册组件、属性赋值、自动装配、环境标识

浅尝Spring注解开发,基于Spring 4.3.12
包含自定义扫描组件、自定义导入组件、手动注册组件、自动注入方法和参数、使用Spring容器底层组件等

告诉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[快速给容器中导入一个组件]
  4. @Import(要导入到容器中的组件);容器中就会自动注册这个组件,id默认是全类名
  5. ImportSelector:返回需要导入的组件的全类名数组;
  6. ImportBeanDefinitionRegistrar:手动注册bean到容器中
  7. 使用Spring提供的 FactoryBean(工厂Bean);
  8. 默认获取到的是工厂bean调用getObject创建的对象
  9. 要获取工厂Bean本身,我们需要给id前面加一个& 如:&colorFactoryBean

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

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

创建一个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);
}

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

  • @Component:将普通JavaBean实例化到spring容器中,Spring容器统一管理,用起来不用自己new了,相当于配置文件中的
  • @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;
    }

}

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

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

指定条件向容器中注入Bean

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

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

创建两个判断条件,判断系统是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 persons = applicationContext.getBeansOfType(Person.class);
        System.out.println(persons);

    }
}

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

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

  • @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);
        }
    }
}
  • 接口,可以选择注册指定的类,返回需要导入的组件的全类名数组;
//自定义逻辑返回需要导入的组件
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);
        }
    }
}

自定义注入组件,在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);
        }
    }
}

多用于第三方组件

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

  • 实现接口,创建工厂
//创建一个Spring定义的FactoryBean
public class ColorFactoryBean implements FactoryBean {

    //返回一个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);
        }
    }
}

属性赋值

public class Person {

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

    //使用@Value赋值;
    //1、基本数值
    //2、可以写SpEL; #{}

    @Value("张三")
    private String name;

    //计算后值为18
    @Value("#{20-2}")
    private Integer age;
}

读取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)

自动注入:

指定装配:

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

默认装配:

  • @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;
}
  • 可以和@Autowired一样实现自动装配功能,默认是按照组件名称进行装配的
  • 没有能支持@Primary和@Autowired(reqiured=false)的功能
  • *@Autowired跟spring强耦合,如果换成了JFinal等其他框架,功能就会失效。而@Resource是JSR-250提供的,它是Java标准,绝大部分框架都支持
    @Resource(name="bookDao2")
    private BookDao bookDao;
  • 需要导入javax.inject的包,和@Autowired的功能一样。没有@Autowired(reqiured=false)的功能
  • *@Autowired:Spring定义的, @Resource、@Inject都是java规范,@Autowried不能脱离Spring
    @Inject
    private BookDao bookDao;

@Autowired:构造器,参数,方法,属性都是从容器中获取参数组件的值
使用[@Bean+方法参数]的方式在SpringBoot中使用很多,在使用各种配置时,只配置方法,方法中的参数直接从容器中获取

方法上

  • @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;
    }
  • 自定义组件想要使用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:指定组件在哪个环境的情况下才能被注册到容器中,不指定,任何环境下都能注册这个组件

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

Original: https://www.cnblogs.com/wei-ran/p/16203112.html
Author: 蔚然丶丶
Title: 浅尝Spring注解开发_自定义注册组件、属性赋值、自动装配、环境标识

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/569872/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • springboot整合mybatis-plus代码生成器遇到bug

    一、生成的实体类没有ID主键 二、生成的mapper不能自动注入 在mapper中添加@Mapper注解,(如果有自定义的mapper.xml,在application.prope…

    Java 2023年6月13日
    076
  • hibernate and spring links

    http://blog.itpub.net/post/329/1756 http://blog.itpub.net/category/11/76 http://domaindriv…

    Java 2023年5月29日
    087
  • Nginx作为静态文件服务器

    Nginx 服务器的一个主要任务是提供静态HTML页面、图像或文件访问。 根据请求的不同,文件将从不同的本地目录提供。 /http/www 包含HTML文件 /http/data1…

    Java 2023年5月29日
    072
  • pycharm可以运行但无法debug的解决方法

    错误信息:pydev debugger: process 4588 is connecting 如果您尝试了网上的很多方法如防火墙设置,去掉 “.idea”…

    Java 2023年6月9日
    085
  • 线程让位与线程合并

    一、线程让位 Thread.yield();/是让当前线程赞停回到就绪状态,让给其他线程先执行,等执行之结束再继续执行 我们写个例子,一个t线程一个main线程,我们分别让两个线程…

    Java 2023年6月9日
    068
  • CSS速学!!

    padding:内边距 缩写:缩写: padding:值; 上下左右的内边距一样 padding:值1 值2; 值1代表上下内边距,值2代表左右内边距 padding:值1 值2 …

    Java 2023年6月9日
    073
  • Kotlin学习快速入门(10)—— 重载运算符使用

    Kotlin中提供了基础的运算符,但是只是针对基础的数据类型,如Int,Double等 如果我们想让两个对象可以相加的功能,这个时候可以使用重载运算符的功能来实现 首先,先介绍下什…

    Java 2023年6月13日
    078
  • SpringCloudAlibaba项目之Seata分布式事务

    SpringCloudAlibaba随笔目录 一、SpringCloudAlibaba项目之父工程搭建 二、 SpringCloudAlibaba项目之Nacos搭建及服务注册 三…

    Java 2023年6月5日
    0106
  • 求求你们,别再刷 Star 了!这跟“爱国”没关系!

    这几年,随着几大互联网公司的强大,纷纷投入云计算产业的建设,开源项目作为维护潜在客户群体(开发者)的重要手段,是各大云计算厂商都在努力做的事。 这几年也诞生了很多真正优秀和看似优秀…

    Java 2023年6月9日
    085
  • SpringBoot+SpringSecurity+SpringSession实现一个前后端分离的权限管理系统

    https://blog.csdn.net/qq_27948811/article/details/89840329 Original: https://www.cnblogs.c…

    Java 2023年5月30日
    079
  • GBase 8t触发器

    触发器是一个特殊的存储过程。在对表进行insert、delete或update操作时,可以通过以定义一些触发器使数据库服务器自动调用存储过程或SQL语句。触发器通过维持不同表中逻辑…

    Java 2023年6月9日
    071
  • 在Nginx下部署SSL证书并重定向至HTTPS

    步骤一:下载 Nginx 版证书文件,解压以后可以看到一个 .key 文件和 .crt/.pem 文件 步骤二:上传证书。把上面的 .key 文件和 .crt/.pem 文件上传到…

    Java 2023年5月30日
    087
  • 工程师什么时机最合适选择跳槽?

    先聊一下跳槽这个事。在 Java 工程师的职业生涯中,跳槽几乎是我们每一位工程师都会经历的事情。但在面试前需要考虑清楚:现在到底应不应该跳槽? class Resume { pub…

    Java 2023年6月13日
    075
  • Java 泛型擦除

    泛型擦除概念 Java的泛型是伪泛型,这是因为Java在 编译期间,所有的泛型信息都会被擦掉,正确理解泛型概念的首要前提是理解类型擦除。Java的泛型基本上都是在编译器这个层次上实…

    Java 2023年5月29日
    093
  • 设计模式之组合模式

    本文通过老王和小王探讨书房、书架、各类书的管理问题,引出结构型设计模式家族中的一个重要成员——组合模式,本文会给予两种组合模式的典型代码实现,为了加深理解会在第三部分应用中介绍组合…

    Java 2023年6月8日
    099
  • MySQL基础

    DQL 查询完整语法 select 字段列表 from 表名列表 where 条件列表 group by 分组字段 having 分组后条件 order by 排序字段 limit…

    Java 2023年6月14日
    087
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球