一,容器创建注解@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
Warning: Undefined variable $return_smiles in /www/wwwroot/wql_luoqin_ltd/wp-content/themes/Sakura/functions.php on line 1109