标签:local autowire 上下文 close int throw proc linus sig
体系结构概述:
@Bean
之前时候,在xml配置文件使用:
<bean id="person" class="com.atguigu.bean.Person" scope="prototype" > <property name="age" value="${}"></property> <property name="name" value="zhangsan"></property> </bean>
实体类:
public class Person { private String name;private Integer 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; } public Person(String name, Integer age) { super(); this.name = name; this.age = age; } public Person() { super(); // TODO Auto-generated constructor stub } public String toString() { return "Person [name=" + name + ", age=" + age + ", nickName=" + nickName + "]"; } }
测试:
public class MainTest { public static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml"); Person bean = (Person) applicationContext.getBean("person"); System.out.println(bean); } }
注解方式:
写一个配置类:需要@Configuration注解
//配置类==配置文件 @Configuration //告诉Spring这是一个配置类 public class MainConfig { //给容器中注册一个Bean;类型为返回值的类型,id默认是用方法名作为id,也可以指定id名为什么 @Bean("person") public Person person01(){ return new Person("lisi", 20); } }
测试:
public class MainTest { @SuppressWarnings("resource") public static void main(String[] args) { ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class); Person bean = applicationContext.getBean(Person.class); System.out.println(bean); String[] namesForType = applicationContext.getBeanNamesForType(Person.class); for (String name : namesForType) { System.out.println(name); } } }
@ComponentScan
之前在xml配置文件里配置:
<context:component-scan base-package="com.atguigu" use-default-filters="false"></context:component-scan>
现在配置在类上:
//配置类==配置文件 @Configuration //告诉Spring这是一个配置类 @ComponentScan(value="com.atguigu") // value:指定要扫描的包 public class MainConfig { //给容器中注册一个Bean;类型为返回值的类型,id默认是用方法名作为id @Bean("person") public Person person01(){ return new Person("lisi", 20); } }
@ComponentScan 的一般配置项:
@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) //@ComponentScan value:指定要扫描的包 //excludeFilters = Filter[] :指定扫描的时候按照什么规则排除那些组件 //includeFilters = Filter[] :指定扫描的时候只需要包含哪些组件
// 过滤规则: //FilterType.ANNOTATION:按照注解 //FilterType.ASSIGNABLE_TYPE:按照给定的类型; //FilterType.ASPECTJ:使用ASPECTJ表达式 //FilterType.REGEX:使用正则指定 //FilterType.CUSTOM:使用自定义规则
可以修改默认的过滤规则,写一个类,实现FilterType
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); if(className.contains("er")){ return true; } return false; } }
@ComponentScan 可以在类上面写多个,也可以通过一个 @ComponentScans 注解来把多个 @ComponentScan 注解配置放在里面,两个写法都是一样的可以生效
@ComponentScans( value = { @ComponentScan(value="com.atguigu",includeFilters = { @Filter(type=FilterType.CUSTOM,classes={MyTypeFilter.class}) },useDefaultFilters = false) } )
Spring 的默认注册组件都是单例的,可以用@Scope 注解修改bean 的作用域
虽然Spring 是单例的,但它用的是饿汉式单例,在Spring 启动时候,就已经把对象注册到了Spring 容器里,可以用@Lazy 注解让它变成懒加载,不过不推荐修改
//默认是单实例的 /** * ConfigurableBeanFactory#SCOPE_PROTOTYPE * @see ConfigurableBeanFactory#SCOPE_SINGLETON * @see org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST request * @see org.springframework.web.context.WebApplicationContext#SCOPE_SESSION sesssion * @return * @Scope:调整作用域 * prototype:多实例的:ioc容器启动并不会去调用方法创建对象放在容器中。 * 每次获取的时候才会调用方法创建对象; * singleton:单实例的(默认值):ioc容器启动会调用方法创建对象放到ioc容器中。 * 以后每次获取就是直接从容器(map.get())中拿, * request:同一次请求创建一个实例 * session:同一个session创建一个实例 * * 懒加载: * 单实例bean:默认在容器启动的时候创建对象; * 懒加载:容器启动不创建对象。第一次使用(获取)Bean创建对象,并初始化; */ // @Scope("prototype") @Lazy @Bean("person") public Person person(){ System.out.println("给容器中添加Person...."); return new Person("张三", 25); }
@Conditional 按照条件给Spring 注册bean,
/** * @Conditional({Condition}) : 按照一定的条件进行判断,满足条件给容器中注册bean * * 如果系统是windows,给容器中注册("bill") * 如果是linux系统,给容器中注册("linus") */ @Bean("bill") public Person person01(){ return new Person("Bill Gates",62); } @Conditional(LinuxCondition.class) @Bean("linus") public Person person02(){ return new Person("linus", 48); }
获取是否是Linux系统的类:
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.env.Environment; import org.springframework.core.type.AnnotatedTypeMetadata; //判断是否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(); String property = environment.getProperty("os.name"); //可以判断容器中的bean注册情况,也可以给容器中注册bean boolean definition = registry.containsBeanDefinition("person"); if(property.contains("linux")){ return true; } return false; } }
获取是否是Windows系统的类:
//判断是否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; } }
测试:
@Test public void test03(){ 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); } Map<String, Person> persons = applicationContext.getBeansOfType(Person.class); System.out.println(persons); }
@Conditional 注解可以放在方法是,也可以放在类上
@Import
1、给容器导入一个组件
要导入的组件
public class Color { private Car car; public Car getCar() { return car; } public void setCar(Car car) { this.car = car; } @Override public String toString() { return "Color [car=" + car + "]"; } }
Car 类:
public class Car { }
导入:
@Import({Color.class}) //@Import导入组件,id默认是组件的全类名 public class MainConfig2 {
2、也可以导入多个:
添加两个颜色的类:
public class Blue { }
public class Yellow { }
要写一个类,实现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"}; } }
导入多个:虽然 MyImportSelector 看着 和导入一个组件是一样的,导入了一个类而已,但是这个类里添加了多个组件
@Import({Color.class,Red.class,MyImportSelector.class}) //@Import导入组件,id默认是组件的全类名 public class MainConfig2 {
3、通过ImportBeanDefinitionRegistrar 接口手动导入组件
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { /** * AnnotationMetadata:当前类的注解信息 * BeanDefinitionRegistry:BeanDefinition注册类; * 把所有需要添加到容器中的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定义信息;(Bean的类型,Bean。。。) RootBeanDefinition beanDefinition = new RootBeanDefinition(RainBow.class); //注册一个Bean,指定bean名 registry.registerBeanDefinition("rainBow", beanDefinition); } } }
新加的彩虹类:
public class RainBow { }
4、使用FactoryBean 注册组件
创建Bean 的工厂:
//创建一个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; } }
用的时候:
@Bean public ColorFactoryBean colorFactoryBean(){ return new ColorFactoryBean(); }
测试:
@Test public void testImport(){ printBeans(applicationContext); Blue bean = applicationContext.getBean(Blue.class); System.out.println(bean); //工厂Bean获取的是调用getObject创建的对象 Object bean2 = applicationContext.getBean("colorFactoryBean"); Object bean3 = applicationContext.getBean("colorFactoryBean"); System.out.println("bean的类型:"+bean2.getClass()); System.out.println(bean2 == bean3); // 虽然导入的是colorFactoryBean,但打印的还是color,如果非要获取的是工厂bean名字,就在前面加一个& 就好了 Object bean4 = applicationContext.getBean("&colorFactoryBean"); System.out.println(bean4.getClass()); }
总结:
/** * 给容器中注册组件; * 1)、包扫描+组件标注注解(@Controller/@Service/@Repository/@Component)[自己写的类] * 2)、@Bean[导入的第三方包里面的组件] * 3)、@Import[快速给容器中导入一个组件] * 1)、@Import(要导入到容器中的组件);容器中就会自动注册这个组件,id默认是全类名 * 2)、ImportSelector:返回需要导入的组件的全类名数组; (比较重要,在SpringBoot 里用的非常多) * 3)、ImportBeanDefinitionRegistrar:手动注册bean到容器中 * 4)、使用Spring提供的 FactoryBean(工厂Bean); * 1)、默认获取到的是工厂bean调用getObject创建的对象 * 2)、要获取工厂Bean本身,我们需要给id前面加一个& * &colorFactoryBean */ @Bean public ColorFactoryBean colorFactoryBean(){ return new ColorFactoryBean(); }
生命周期
要注册Bean 的类:
1、第一种方式需要的Bean
@Component public class Car { public Car(){ System.out.println("car constructor..."); } public void init(){ System.out.println("car ... init..."); } public void detory(){ System.out.println("car ... detory..."); } }
2、第二种方式的Bean
@Component public class Cat implements InitializingBean,DisposableBean { public Cat(){ System.out.println("cat constructor..."); } @Override public void destroy() throws Exception { // TODO Auto-generated method stub System.out.println("cat...destroy..."); } @Override public void afterPropertiesSet() throws Exception { // TODO Auto-generated method stub System.out.println("cat...afterPropertiesSet..."); } }
3、第三种方式的
@Component public class Dog implements ApplicationContextAware { //@Autowired private ApplicationContext applicationContext; // 实现上面类的接口,这样导入后,以后用的时候就可以拿到IOC容器 public Dog(){ System.out.println("dog constructor..."); } //对象创建并赋值之后调用 @PostConstruct public void init(){ System.out.println("Dog....@PostConstruct..."); } //容器移除对象之前 @PreDestroy public void detory(){ System.out.println("Dog....@PreDestroy..."); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { // TODO Auto-generated method stub this.applicationContext = applicationContext; } }
4、使用Bean 的后置处理器
/** * 后置处理器:初始化前后进行处理工作 * 将后置处理器加入到容器中*/ @Component public class MyBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { // TODO Auto-generated method stub System.out.println("postProcessBeforeInitialization..."+beanName+"=>"+bean); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { // TODO Auto-generated method stub System.out.println("postProcessAfterInitialization..."+beanName+"=>"+bean); return bean; } }
注册Bean
/** * bean的生命周期: * bean创建---初始化----销毁的过程 * 容器管理bean的生命周期; * 我们可以自定义初始化和销毁方法;容器在bean进行到当前生命周期的时候来调用我们自定义的初始化和销毁方法 * * 构造(对象创建) * 单实例:在容器启动的时候创建对象 * 多实例:在每次获取的时候创建对象 * * BeanPostProcessor.postProcessBeforeInitialization * 初始化: * 对象创建完成,并赋值好,调用初始化方法。。。 * BeanPostProcessor.postProcessAfterInitialization * 销毁: * 单实例:容器关闭的时候 * 多实例:容器不会管理这个bean;容器不会调用销毁方法; * * * 遍历得到容器中所有的BeanPostProcessor;挨个执行beforeInitialization, * 一但返回null,跳出for循环,不会执行后面的BeanPostProcessor.postProcessorsBeforeInitialization * * BeanPostProcessor原理 * populateBean(beanName, mbd, instanceWrapper);给bean进行属性赋值 * initializeBean * { * applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); * invokeInitMethods(beanName, wrappedBean, mbd);执行自定义初始化 * applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); *} * * * 创建Bean的4种方式 * 1)、指定初始化和销毁方法; * 通过@Bean指定init-method和destroy-method;分别指定初始化 或 销毁时候 调用的方法 * 2)、通过让Bean实现InitializingBean(定义初始化逻辑), * DisposableBean(定义销毁逻辑);
* 实现这两个接口,然后重写里面的两个方法 * 3)、可以使用JSR250; * @PostConstruct:在bean创建完成并且属性赋值完成;来执行初始化方法,定义在方法上 * @PreDestroy:在容器销毁bean之前通知我们进行清理工作,也在方法上定义 * 4)、BeanPostProcessor【interface】:bean的后置处理器; * 在bean初始化前后进行一些处理工作; * postProcessBeforeInitialization:在初始化之前工作 * postProcessAfterInitialization:在初始化之后工作 * * Spring底层对 BeanPostProcessor 的使用; * bean赋值,注入其他组件,@Autowired,生命周期注解功能,@Async, 。。。BeanPostProcessor; * */ @ComponentScan("com.atguigu.bean") @Configuration public class MainConfigOfLifeCycle { //@Scope("prototype") @Bean(initMethod="init",destroyMethod="detory") public Car car(){ return new Car(); } }
测试:
public class IOCTest_LifeCycle { @Test public void test01(){ //1、创建ioc容器 AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class); System.out.println("容器创建完成..."); //applicationContext.getBean("car"); //关闭容器 applicationContext.close(); } }
属性赋值
@Value
public class Person { //使用@Value赋值; //1、基本数值 //2、可以写SpEL; #{} //3、可以写${};取出配置文件【properties】中的值(在运行环境变量里面的值) @Value("张三") private String name; @Value("#{20-2}") // 18 private Integer age; @Value("${person.nickName}") // 导入的是配置文件的值 private String nickName;
person.nickName=\u5C0F\u674E\u56DB // 小张三
之前在xml 文件要配置的:
<context:property-placeholder location="classpath:person.properties"/>
现在可以在类上使用@PropertySource,如果要加入多个配置文件,可以点进去看源码,比较简单,可以放数组类型
//使用@PropertySource读取外部配置文件中的k/v保存到运行的环境变量中;加载完外部的配置文件以后使用${}取出配置文件的值 @PropertySource(value={"classpath:/person.properties"}) @Configuration public class MainConfigOfPropertyValues { @Bean public Person person(){ return new Person(); } }
自动装配
第一种:我们开发中对dao、service、controller 都要加上三个注解,然后互相之间调用时候使用@Autowired 把我们自定义的组件给自动装配进来,它是按照类型来注入的,默认的Bean是类的首字母小写,
如果找到了多个Bean,再按照属性名查找,如果要必须指定注入哪个,就用@Qualifier("指定的bean的名字"),@Autowired 可以指定是否一定要找spring 里的bean,加上required 属性就行,
还有一个注解@Primary首选去找到哪个bean,而@Qualifier 是必须要用哪个bean
@Autowired 可以在 构造器,参数,方法,属性,都可以使用
第二种:还可以使用@Resource 也可以完成自动装配,不同的是@Resource 是java里的注解,@Autowired 是spring里的注解,@Resource 默认是按照属性名装配的,
@Resource 不能和@Autowired 一样搭配着其他两个注解一块使用
@Inject 也可以自动装配,也是java的注解,但是需要导入javax.inject的包,和Autowired的功能一样。没有required=false的功能;
/** * 自动装配; * Spring利用依赖注入(DI),完成对IOC容器中中各个组件的依赖关系赋值; * * 1)、@Autowired:自动注入: * 1)、默认优先按照类型去容器中找对应的组件:applicationContext.getBean(BookDao.class);找到就赋值 * 2)、如果找到多个相同类型的组件,再将属性的名称作为组件的id去容器中查找 * applicationContext.getBean("bookDao") * 3)、@Qualifier("bookDao"):使用@Qualifier指定需要装配的组件的id,而不是使用属性名 * 4)、自动装配默认一定要将属性赋值好,没有就会报错; * 可以使用@Autowired(required=false); * 5)、@Primary:让Spring进行自动装配的时候,默认使用首选的bean; * 也可以继续使用@Qualifier指定需要装配的bean的名字 * BookService{ * @Autowired * BookDao bookDao; * } * * 2)、Spring还支持使用@Resource(JSR250)和@Inject(JSR330)[java规范的注解] * @Resource: * 可以和@Autowired一样实现自动装配功能;默认是按照组件名称进行装配的; * 没有能支持@Primary功能没有支持@Autowired(reqiured=false); * @Inject: * 需要导入javax.inject的包,和Autowired的功能一样。没有required=false的功能; * @Autowired:Spring定义的; @Resource、@Inject都是java规范 * * AutowiredAnnotationBeanPostProcessor:解析完成自动装配功能; * * 3)、 @Autowired:构造器,参数,方法,属性;都是从容器中获取参数组件的值 * 1)、[标注在方法位置]:@Bean+方法参数;参数从容器中获取;默认不写@Autowired效果是一样的;都能自动装配 * 2)、[标在构造器上]:如果组件只有一个有参构造器,这个有参构造器的@Autowired可以省略,参数位置的组件还是可以自动从容器中获取 * 3)、放在参数位置: * * 4)、自定义组件想要使用Spring容器底层的一些组件(ApplicationContext,BeanFactory,xxx); * 自定义组件实现xxxAware;在创建对象的时候,会调用接口规定的方法注入相关组件;Aware; * 把Spring底层一些组件注入到自定义的Bean中; * xxxAware:功能使用xxxProcessor; * ApplicationContextAware==》ApplicationContextAwareProcessor; * */ @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; } /** * @Bean标注的方法创建对象的时候,方法参数的值从容器中获取 * @param 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; //构造器要用的组件,都是从容器中获取 public Boss(Car car){ this.car = car; System.out.println("Boss...有参构造器"); } public Car getCar() { return car; } //@Autowired //标注在方法,Spring容器创建当前对象,就会调用方法,完成赋值; //方法使用的参数,自定义类型的值从ioc容器中获取 public void setCar(Car car) { this.car = car; } @Override public String toString() { return "Boss [car=" + car + "]"; } }
Aware 注入spring底层组件测试
@Component public class Red implements ApplicationContextAware,BeanNameAware,EmbeddedValueResolverAware { private ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { // TODO Auto-generated method stub System.out.println("传入的ioc:"+applicationContext); this.applicationContext = applicationContext; } @Override public void setBeanName(String name) { // TODO Auto-generated method stub System.out.println("当前bean的名字:"+name); } @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 指定,默认不管哪个环境都可以注册的,@Profile 也可以写在类上
/** * Profile: * Spring为我们提供的可以根据当前环境,动态的激活和切换一系列组件的功能; * * 开发环境、测试环境、生产环境; * 数据源:(/A)(/B)(/C); * * * @Profile:指定组件在哪个环境的情况下才能被注册到容器中,不指定,任何环境下都能注册这个组件 * * 1)、加了环境标识的bean,只有这个环境被激活的时候才能注册到容器中。默认是default环境 * 2)、写在配置类上,只有是指定的环境的时候,整个配置类里面的所有配置才能开始生效 * 3)、没有标注环境标识的bean在,任何环境下都是加载的; */ @PropertySource("classpath:/dbconfig.properties") @Configuration public class MainConfigOfProfile implements EmbeddedValueResolverAware{ @Value("${db.user}") private String user;
private StringValueResolver valueResolver; // 值解析器 private String driverClass; @Bean public Yellow yellow(){ return new Yellow(); } @Profile("test") @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}"); } }
配置文件 dbconfig.properties
db.user=root db.password=123456 db.driverClass=com.mysql.jdbc.Driver
测试:
public class IOCTest_Profile { //1、使用命令行动态参数: 在虚拟机参数位置加载 -Dspring.profiles.active=test //2、代码的方式激活某种环境; @Test public void test01(){ AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); //1、创建一个applicationContext //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); } Yellow bean = applicationContext.getBean(Yellow.class); System.out.println(bean); applicationContext.close(); } }
标签:local autowire 上下文 close int throw proc linus sig
原文地址:https://www.cnblogs.com/abiu/p/14152044.html