一,容器创建注解@Configuration和@Bean
容器的创建和配置有两种中方式
- XML配置(文件配置):在SSM中经常使用这种方式
- 注解配置(配置类):在SpringBoot中很常用,并且SpringBoot的自动装配也依赖这种方式
注:文件配置和配置类配置只是操作上不一样,实现的作用是等价的
一,传统XML文件配置bean
① 实体类
public class config_annotation {
String name;
int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "config_annotation{" +
"name='" + name + '\'' +
", age=" + age +
'}'; }}
② Spring的XML配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean class="com.config.config_annotation" id="config_xml">
<property name="name" value="WQL"/>
<property name="age" value="100"/>
</bean>
</beans>
public static void main(String[] args) {
//ClassPathXmlApplicationContext这个类通过xml文件获取上下文
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("springconfig.xml");
//获取bean
Object bean = context.getBean("config_xml");
System.out.println(bean);
}
二,注解配置bean
注解配置合xml文件配置不一样,注解作用于类
注解配置bean有两个重要的注解:
- @Configuration:声明一个配置类(配置类等价于配置文件)
- @Bean:创建一个bean(和xml配置文件中的<bean>标签是一样的作用)
① 实体类(和上面是一样的)
② 配置类
//配置类注解
@Configuration
public class config_annotation {
//value为当前bean的名称
@Bean(value = "get_bean")
public bean_test get_bean(){
return new bean_test("FQ_WQL",100);
}}
③ main测试
public static void main(String[] args) {
//通过注解配置类方式获取上下文
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(config_annotation.class);
//获取bean对象
Object bean = applicationContext.getBean("get_bean");
System.out.println(bean);
}
二,包扫描注解@ComponentScan
包扫描:只要包中的类标注了@Controller,@Service,@Repository,@Component,都会被在载入到当前Bean中并可以被调用
一,XMl配置包扫描
<context:component-scan base-package="com"/>
二,注解配置包扫描
一,注解配置使用
① @ComponentScan:单扫描
@ComponentScan(value = "com.bean")
@ComponentScans(value = {@ComponentScan("com.bean"),@ComponentScan("com.bean")})
二,包扫描过滤
一,扫描过滤依赖于两个参数
① excludeFilters:扫描排除,不扫描哪些包或者类
//通过注解类型过滤,包含Service类型的进行过滤
@ComponentScan(value = "com.bean",excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = Service.class)})
//通过注解类型过滤,包含Coltroll类型的进行扫描
@ComponentScan(value = "com.bean",includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = Controller.class)})
二,扫描过滤的方式
通过Filter扫描过滤有五中方式:
- FilterType.ANNOTATION:指定注解的方式
- FilterType.ASSIGNABLE_TYPE:指定具体类的方式
- FilterType.ASPECTJ:使用ASPECTJ表达式
- FilterType.REGEX:正则表达式
- FilterType.CUSTOM:自定义规则
注:用的比较多的就是是ANNOTATION和ASSIGNABLE_TYPE两种方式
1,指定注解的方式FilterType.ANNOTATION
可以指定四中注解:Service,Component,Controller,Repository
@ComponentScan(value = "com.bean",includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = Controller.class),
@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = ComponentScan.class)})
2,指定具体类的方式
@ComponentScan(value = "com.bean",includeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = service_bean.class),
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = bean_test.class)})
指定义过滤规则必须自定义一个过滤类,这个类必须实现TyprFilter接口
TyprFilter接口:只要一个match的实现方法(返回true表示匹配否则反之),这个方法里面有两个只要参数
- metadataReader:读取当前正在扫描类的信息
- MetadataReaderFactory:获取其他任何类的信息
① 自定义过滤类
public class custon_util implements TypeFilter {
//
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
//1,获取当前类注解信息(有获取注解名,注解类型等方法)
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
//2,获取当前类的类信息(有获取类的名称,实现接口,子类,继承类等方法)
ClassMetadata classMetadata = metadataReader.getClassMetadata();
//3,获取当前类资源路径(获取类的文件名称,文件路径,URL等方法)
Resource resource = metadataReader.getResource();
//打印类名称
String classname = classMetadata.getClassName();
System.out.println(classname);
//假如类名包含bean就返回true表示匹配
if(classname.contains("bean")){
return true;
}
return false;
}
}
② 假如到过滤中
@ComponentScan(value = "com",excludeFilters = {@ComponentScan.Filter(type = FilterType.CUSTOM,classes = custon_util.class)})
三,设置bean的作用域@Scope
Spring默认Bean都是单例的,但Scope可以配置单例和多例
scope两个重要的值:
- singleton:单例
- prototype:多例
一,xml配置scope
<bean class="com.bean.bean_test" id="config_xml" scope="singleton" >
<property name="name" value="WQL"/>
<property name="age" value="100"/>
</bean>
二,注解配置scope
@Bean(value = "get_bean")
@Scope(value = "prototype")
public bean_test get_bean(){
return new bean_test("FQ_WQL",100);
}
测试多例:
四,懒加载@Lazy
bean默认在容器启动的时候创建对象
懒加载:容器启动不创建对象,只有在第一次使用(获取)时才创建Bean对象,并初始化
一,xml配置lazy懒加载
<bean class="com.bean.bean_test" id="config_xml" lazy-init="true">
<property name="name" value="WQL"/>
<property name="age" value="100"/>
</bean>
二,注解配置lazy懒加载
@Bean(value = "get_lazy_bean")
@Lazy
public lazy_test get_lazy_bean(){
System.out.println("启动时初始化!");
return new lazy_test("FQ",10);
}
五,按照条件注册@Conditional
@Bean,@Controller,@Service,@Componter……都是直接在容器中进行注册,而@Conditional按照一定条件进行判断,满足条件才在容器中注册bean
一,@Conditional的实现动态装配
@Conditional格式:
@Conditional(value = {条件判断类})
实现Conditional条件判断,需要有一个条件判断类,这个类必须实现Condition接口
Condition接口只有一个matches方法
方法参数:
- ConditionContext:上下文,可以获取bean工厂,环境信息,加载器等信息
- metadata:注释信息
例:
① 条件判断类
public class condition_win_util implements Condition {
/*
* 匹配成功就返回true,失败就为false
* ConditionContext:上下文
* metadata:注释信息
* */
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
//1,获取bean工厂对象
ConfigurableListableBeanFactory factory = context.getBeanFactory();
//2,获取类加载器
ClassLoader classLoader = context.getClassLoader();
//3,获取当前环境信息
Environment environment = context.getEnvironment();
//4,获取到bean的注册类
BeanDefinitionRegistry registry = context.getRegistry();
//通过environment获取当前系统的类型
String os_name = environment.getProperty("os.name");
//判断当前系统是为linux还是windown
if(os_name.contains("Windows")){
System.out.println(os_name);
return true;
}
return false;
}}
②注解bean
@Conditional(value = condition_win_util.class)//只有条件通过才执行@Bean
@Bean(value = "get_windown")
public condition_test get_win_condition(){
return new condition_test("windown");
}
六,容器导入组件@Import
Spring往容器中注册组件有多种方式,它们适应于不同对的场景:
- 包扫描+组件标注注解(@Service,@Component,@Controller):适用于自己定义的类,无法作用第三方框架
- @Configuration+@Bean:适应于导入第三方框架组件并进行配置,一般SpringBoot整合其他框架比如RabbitMQ,Minio等都使用这种方式
- @import:适应于快速给容器中导入一个组件
- 使用Spring提供的FactoryBean接口,实现组件导入容器
import注解也有三种方式:
- @Import:快速导入单个或者多个组件
- ImportSelector:导入选择器类,返回需要导入的组件的全类名数组,即可导入
- ImportBeanDefinitionRegistrar:手动注册bean到容器中
一,import导入
一,@Import快速导入组件
格式:@import(value={组件全限定类名,……})
@Import(value = {condition_lin_util.class})
二,ImportSelector导入
importselector的实现,需要有实现类,这个类实现ImportSelector接口
ImportSelector接口有一个selectImports方法返回值为string数组,只有一个参数AnnotationMetadata它可以获取所有的注解和类信息
例:
① importselector实现类
//自定义逻辑返回需要导入的组件
public class importselect_util implements ImportSelector {
/*
* AnnotationMetadata:获取到当前标注@import注解类的全部注解信息
* */
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
//返回值就是要导入容器中的组件全类名数组
return new String[]{"com.util.condition_lin_util","com.util.condition_win_util"};
}
}
②导入(importselect它没有专门的注解,依赖于@import导入)
@Import(value = {importselect_util.class})
三,ImportBeanDefinitionRegistrar手动导入
ImportBeanDefinitionRegistrar手动注册实现依赖ImportBeanDefinitionRegistrar的实现类
这个类也只有一个registerBeanDefinitions方法
两个参数:
- AnnotationMetadata:当前类的注解信息
- BeanDefinitionRegistry:BeanDefinition注册类,通过这个类的方法进行手动注册
例:
① ImportBeanDefinitionRegistrar实现类
//手动注册组件
public class ImportBeanDefinitionRegistrar_util implements ImportBeanDefinitionRegistrar {
/*
*参数:
* 1,AnnotationMetadata:当前类的注解信息
* 2,BeanDefinitionRegistry:BeanDefinition注册类,通过这个类的方法进行手动注册
* registry.registerBeanDefinition():手动注册方法
* */
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
}
}
② 导入
@Import(value = {ImportBeanDefinitionRegistrar_util.class})
二,FactoryBean导入
使用Factory实现导入需要定义类并实现Factory接口
这个接口有三个方法:
- getObject():返回一个对象,并将对象添加到容器中
- getObjectType():设置返回对象的类型
- isSingleton():是否为单例,true为单例,反之为多例
例:
① 创建Factory实现类
public class factorybean_util implements FactoryBean {
//返回一个对象,这个对象会添加到容器中
@Override
public Object getObject() throws Exception {
//返回一个condition_test对象
return new condition_test("FactoryBean");
}
//返回对象的类型
@Override
public Class<?> getObjectType() {
//返回对象condition_test类型
return condition_lin_util.class;
}
//是否为单例,返回true为单例,返回flase为多例
@Override
public boolean isSingleton() {
//为单例
return true;
}
}
② 将FactoryBean放入配置类中声明
@Bean
public factorybean_util get_factory_bean(){
//返回的虽然是 factorybean_util对象,实际上是condition_test对象
return new factorybean_util();
}
③ 获取FactoryBean
获取时FactoryBean有两中情况:
- 带&开头的:获取FactoryBean本身
- 不带&:获取FactoryBean创建返回的对象
public static void main(String[] args)
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(config_annotation.class);
Object factoryBean = context.getBean("get_factory_bean");
Object factoryBean1 = context.getBean("&get_factory_bean");
System.out.println("FactoryBean生成的对象:"+factoryBean);
System.out.println("FactoryBean对象本身:"+factoryBean1);
}
七,注解方式配置生命周期
Spring生命周期有两种:
1,正常生命周期:五大过程
- 通过有参构造创建Bean对象
- 对属性进行DI依赖注入
- 调用Bean初始化方法
- 获取Bean对象
- 销毁bean,并调用bean销毁后需要执行的方法
2,带有前置后置处理器的生命周期:七步过程
- 通过有参构造创建Bean对象
- 对属性进行DI依赖注入
- 将bean传入前置处理器,调用前置处理器方法
- 调用Bean初始化方法,对bean进行初始化
- 将bean传入后置处理器,调用后置处理器方法
- 销毁bean,并调用bean销毁后需要执行的方法
Spring配置生命周期的方式:
- 通过initmethod和destroymethod指定初始化和销毁方法
- 通过bean实现InitialliazingBean定义初始化逻辑,实现DisposableBean定义销毁逻辑
- 使用JSR250实现,@Postconstruct在bean创建完成并属性注入完成执行初始化,@PreDestroy在容器销毁bean之前进行通知的回调方法
- 使用BeanPostProcessor定义前置处理器和后置处理器
注:方式1,2,3本质上是差不多的,只是写法配置上和含义上稍微有点
传统的XML配置不进行演示了以前有写过: Spring的IOC和AOP – 晴天 (luoqin.ltd)
一,initmethod和destroymethod实现初始化和销毁
注解initMethod和destroymethod的实现依赖于@Bean种的两个参数:
- initMethod:指定容器的初始化方法
- destroyMethod:指定容器销毁后调用的方法
① bean对象
public class init_dostroy_test {
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public init_dostroy_test(String name) {
this.name = name;
System.out.println("bean有参创建!");
}
//初始化方法
public void init(){
System.out.println("init_dostroy_test初始化!");
}
//销毁方法
public void destroy(){
System.out.println("init_dostroy_test销毁!");
}
}
② 配置类
@Configuration
public class life_annotation {
//把方法通过initMethod和destroyMethod进行加入
@Bean(value = "get_init_destroy",initMethod = "init",destroyMethod = "destroy")
public init_dostroy_test get_init_destroy(){
return new init_dostroy_test("initMethod和destroyMethod进行初始化和销毁!");
}
}
③ 测试
public class life_main {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(life_annotation.class);
System.out.println("容器创建完成,获取bean!");
applicationContext.getBean("get_init_destroy");
applicationContext.close();
}
}
二,通过InitialliazingBean和DisposableBean实现初始化和销毁
通过这种发生实现需要实现InitialliazingBean和DisposableBean两个接口,并重写两个接口的两个方法:
- InitialliazingBean接口中的afterPropertiesSet方法:定义初始化的逻辑
- DisposableBean接口中的destroy方法:定义销毁逻辑
① bean实例
@Component(value = "InitialliazingBean_test")
//实现InitializingBean和DisposableBean接口
public class InitialliazingBean_test implements InitializingBean, DisposableBean {
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean初始化!");
}
@Override
public void destroy() throws Exception {
System.out.println("DisposableBean销毁!");
}
public InitialliazingBean_test() {
System.out.println("有参构建bean对象!");
}
}
② 配置类
//不使用@Bean的方式,直接使用ComponentScan包扫描的方式加入bean对象到容器
@ComponentScan(value = "com.bean")
@Configuration
public class life_annotation {
}
③ 测试
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(life_annotation.class);
System.out.println("容器创建完成!");
applicationContext.getBean("InitialliazingBean_test");
applicationContext.close();
}
三,使用@Postconstruct和@PreDestroy实现初始化和销毁
@Postconstruct和@PreDestroy与上面两种初始化和销毁是有点区别的:
- @Postconstruct:在容器创建完成之后调用
- @PreDestroy:在容器销毁之前调用
① bean实例
@Component(value = "postconstruct_test")
public class postconstruct_test {
public postconstruct_test() {
System.out.println("无参构造创建对象!");
}
@PostConstruct
public void init(){
System.out.println("PostConstruct在对象创建完成之后调用!");
}
@PreDestroy
public void destroy(){
System.out.println("PostConstruct在对象销毁之前调用!");
}
}
② 配置类
//不使用@Bean的方式,直接使用ComponentScan包扫描的方式加入bean对象到容器
@ComponentScan(value = "com.bean")
@Configuration
public class life_annotation {}
③ 测试
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(life_annotation.class);
System.out.println("容器创建完成!");
applicationContext.getBean("postconstruct_test");
applicationContext.close();
}
四,通过BeanPostProcessor加入前置和后置处理器
实现BeanPostProcessor需要实现该接口,并重写两个方法:
- postProcessBeforeInitialization:前置处理器
- postProcessAfterInitialization:后置处理器
① BeanPostProcessor接口实现
@Component
public class BeanPostProcessor_test implements BeanPostProcessor {
@Override
/*前置处理器
* 参数:
* 1,Object bean:容器中传入的bean实例
* 2,String beanName:bean名称
* 处理完成后需要将bean进行返回
* */
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessBeforeInitialization——>前置处理器:"+beanName);
return bean;
}
@Override
//后置处理器
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessAfterInitialization——>后置处理器:"+beanName);
return bean;
}
}
② 扫描该类加入容器
@ComponentScan(value = "com.bean")
@Configuration
public class life_annotation {}
注:BeanPostProcessor接口实现类加入容器后,默认就会为所有bean对象提供前置和后置
八,注解方式属性赋值
一,@Value属性赋值
属性赋值,String在xml中提供value参数,在注解提供了@value注解
value赋值有三种形式:
- 基本数值:比如基本类型和String都可以直接赋值
- SPEL(spring表达式):#{}表示,它支持选择,比较,正则表达式,赋值计算,集合引用等操作
- 取外部配置文件中的值:通过${},通过propertysource引入,任何在通过${}调用即可
@value注解即可以作用于属性也可以作用于参数,效果是一样的
一,在xml中通过value进行属性赋值
<bean class="com.bean.bean_test" id="config_xml" lazy-init="true">
<property name="name" value="WQL"/>
<property name="age" value="100"/>
</bean>
二,注解@Value赋值
① bean实例
@Component
public class value_test {
@Value("WQL")
String name;
@Value("20")
int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "value_test{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
② 加入bean容器
@ComponentScan(value = "com.bean")
@Configuration
public class life_annotation {}
二,@PropertySource加载外部配置文件
一,xml加载外部配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--引入外部配置文件-->
<context:property-placeholder location="config.properties"/>
<bean class="com.bean.bean_test" id="config_xml" lazy-init="true">
<!--${}引用-->
<property name="name" value="${name}"/>
<property name="age" value="${age}"/>
</bean>
<context:component-scan base-package="com.bean" />
</beans>
二,注解@PropertySource加载外部配置文件
@PropertySource将外部配置文件中的K-V保存到bean运行时的环境中
① bean实例
@Component
public class value_test {
@Value("${name}")
String name;
@Value("${age}")
int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "value_test{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
② 加载bean
@ComponentScan(value = "com.bean")
@PropertySource("classpath:/config.properties")//加载外部配置文件
@Configuration
public class life_annotation {}
九,注解方式自动装配
Spring的自动装配有多种:
- Spring提供的@Autowried,它可以结合@Qualifire或者@Primary一起使用
- java提供的JSR250标准提供的@Resource和@Inject
- 使用spring较为的底层的ApplicationAwarm接口进行装配
一,@Autowried进行装配
@Autowried注入分两种情况:
- 默认优先按照类型去容器中寻找组件装配
- 如果寻找到多个相同类型时,将属性的名称作为组件的id去容器中查找
@Autowried重要参数:
- required:为true表示autowried必须装配完成否则会报异常,为flase假如无法进行装配,则会返回空
@Autowried标注的位置:它可以标注在属性,测试,构造器,方法上,实现的功能都是一样的
- 标注在方法上:方法的参数就会从容器中获取装配,@Bean加+方法参数参数也是从容器中取和不加autowrite是一样的
- 标注在构造上:构造的参数也从容器中获取,如果注解只有一个有参构造,可以省略autowrite,默认就会从容器中获取
- 标注在属性上:使用最多的方式,按照类型从容器中获取组件进行装配
- 标注在参数上:和标注在属性上是一样的
为了应对@Autwried的多个同类型问题,Spring提供两个注解(@Qualifire和@Primary)进行组合使用:
- @Qualifire:指定需要装配的组件id,不再使用属性命作为id
- @Primary:标注为首选Bean,在@Autwried装配时同类型时,会优先装配首选的bean
注:假如@Qualifire和@Primary同时存在,会优先@Qualifire注解
例:
① bean实例
public class bean_test {
String name;
int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "config_annotation{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public bean_test(String name, int age) {
this.name = name;
this.age = age;
}
}
② bean配置类
@Configuration
public class autowried_config {
//加载两相同类型的Bean
@Bean
public bean_test get_bean(){
return new bean_test("FQ_LOVE",21);
}
@Primary
@Bean
public bean_test get_bean1(){
return new bean_test("WQL_LOVE",21);
}
}
③ 测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = autowried_config.class)
public class autowried {
//required = false假如没有装配的bean就返回空,这样不会报错
@Qualifier(value = "get_bean")
@Autowired(required = false)
bean_test get_bean3;
@Test
public void test(){
System.out.println(get_bean3);
}
}
二,@Resource和@Inject进行装配
@Resource和@inject都是java提供的规范,它都是单都使用的,并没有依赖配合关系
@Resource的概念:
- 默认按照组件名称id进行装配
- 有name参数,可以指定ID进行装配
- 和@Autowried不一样,它不支持required和@Primary
@Inject的概念:
- 需要导入javax.Inject第三方包
- 它的使用和@Autowrited是一样的,优先按照类型进行装配,当它没有required=false属性
一,@Resource装配
① bean实例和上面一样
② 配置bean
@Configuration
public class resource_config {
@Bean("get_bean_test")
public bean_test get_bean_test(){
return new bean_test("EDG",1);
}
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {resource_config.class})
public class autowried {
@Resource(name = "get_bean_test")
bean_test bean;
@Test
public void test1(){
System.out.println(bean);
}
}
二,@Inject装配
导入inject的mave依赖:
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
① bean实例和上面一样
② 配置bean
@Configuration
public class inject_config {
@Bean
public bean_test get_bean4(){
return new bean_test("DK",2);
}
}
③ 测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {autowried_config.class, resource_config.class, inject_config.class})
public class autowried {
@Qualifier(value = "get_bean4")
@Inject
bean_test bean1;
@Test
public void test2(){
System.out.println(bean1);
}
}
三,使用ApplicationAwarm自定义装配
自定义组件可以使用Spring容器底层的一些组件,比如:ApplicationContext,BeanFactory等
实现ApplicationAwarm自定义装配,必须实现ApplicationAwarm接口,这个接口有很多子接口,它们分别有不同的应用场景,通过调用这些接口里面的方法就可以进行注入装配
例:
① 实现接口
@Component
public class RpcServer implements ApplicationContextAware{
private ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
// TODO Auto-generated method stub
context = applicationContext;
}
//获得applicationContext
public static ApplicationContext getApplicationContext() {
//assertContextInjected();
return context;
}
public static void clearHolder(){
context=null;
}
//获取Bean
public static <T> T getBean(Class<T> requiredType){
//assertContextInjected();
return (T) getApplicationContext().getBean(requiredType);
}
@SuppressWarnings("unchecked")
public static <T> T getBean(String name){
assertContextInjected();
return (T) getApplicationContext().getBean(name);
}
//判断application是否为空
public static void assertContextInjected(){
Validate.isTrue(context==null, "application未注入 ,请在springContext.xml中注入SpringHolder!");
}
}
② 扫描bean
@ComponentScan(value = "com.bean")
@Configuration
public class life_annotation {}
十,@Profile注解
@Profile可以根据环动态对的激活和切换一系列组件的功能,它标注在@Bean上那么假如没有激活profile,bean将不注入
应用场景:假如开发某个模块开发环境,测试环境,生成环境,各不相同,这时就可以使用@Profile写几套程序,在不同的环境下激活
@Profile的参数:
- value[]:指定组件在那个情况下才能激活被注册到容器中,不指定在任何情况下都能注册(默认default)
@Profile的作用域:
- 标注在方法上:只对单个方法的bean起效
- 标注在类上:对整个类都起效
@Profile激活的方式:
1,使用命令行动态参数:在虚拟机参数为加-Dspring.profiles.active=环境标识
2,使用代码的方式:
//1,通过注解配置类方式获取上下文
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
//2,设置需要激活的环境(比如下面就是激活dev和test环境)
applicationContext.getEnvironment().setActiveProfiles("dev","test");
//3,注册主配置类
applicationContext.register(c3p0_config.class);
//4,启动刷新容器
applicationContext.refresh();
username=root password=123 drive=com.mysql.jdbc.Driver
② 配置类
@PropertySource("classpath:/jdbc.properties")
@Configuration
public class c3p0_config {
@Value("${username}")
String username;
@Value("${password}")
String password;
@Value("${drive}")
String drive;
@Profile("test")
@Bean("testDataSource")
public DataSource devDataSource() throws PropertyVetoException {
ComboPooledDataSource comboPooledDataSource =new ComboPooledDataSource();
comboPooledDataSource.setUser(username);
comboPooledDataSource.setPassword(password);
comboPooledDataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
comboPooledDataSource.setDriverClass(drive);
return comboPooledDataSource;
}
@Profile("dev")
@Bean("devDataSource")
public DataSource proDataSource() throws PropertyVetoException {
ComboPooledDataSource comboPooledDataSource =new ComboPooledDataSource();
comboPooledDataSource.setUser(username);
comboPooledDataSource.setPassword(password);
comboPooledDataSource.setJdbcUrl("jdbc:mysql://localhost:3306/wql");
comboPooledDataSource.setDriverClass(drive);
return comboPooledDataSource;
}
@Profile("pro")
@Bean("proDataSource")
public DataSource dataSource2() throws PropertyVetoException {
ComboPooledDataSource comboPooledDataSource =new ComboPooledDataSource();
comboPooledDataSource.setUser(username);
comboPooledDataSource.setPassword(password);
comboPooledDataSource.setJdbcUrl("jdbc:mysql://localhost:3306/bookstrom");
comboPooledDataSource.setDriverClass(drive);
return comboPooledDataSource;
}
}
② 环境激活
public static void main(String[] args) {
//1,通过注解配置类方式获取上下文
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
//2,激活dev环境
applicationContext.getEnvironment().setActiveProfiles("dev");
//3,注册主配置类
applicationContext.register(c3p0_config.class);
//4,启动刷新容器
applicationContext.refresh();
//获取所有的bean
String[] names = applicationContext.getBeanDefinitionNames();
//打印所有的名称
for(String name:names){
System.out.println(name);
}}








Comments | NOTHING