spring基于注解
- 一、组件注册
- 1、java配置类注解@configuration和@bean
- 2、@ComponentScan自动扫描注解,@CompentScan.Filter使用
- 2.1、@ComponentScan使用
- 2.2、@CompentScan,excludeFilter, @Component.Filter的使用
- 2.3、@CompentScan, includeFilter, @Component.Filter的使用
- 3、@ComponentScan.Filter过滤规则 与自定义过滤规则
- 4、组件的作用域 @Scope注解
- 5、单实例懒加载 @Lazy
- 6、按照条件给容器注册Bean @Conditional注解
- 7、导入第三方组件
- 8、使用FactoryBean注册组件
- 二、 Bean的生命周期
- 1、使用@Bean的initMethod属性,destroyMethod属性,设置Bean初始化,和销毁管理。
- 2、javaBean对象实现initializingBean接口,DisposableBean接口
- 3、javaBean对象上标注@PostStruct表示容器初始化时调用,@PreDestroy表示容器移除对象之前调用。
- 4、BeanPostProcessor接口实现Bean的统一处理。
- 5、BeanPostProcessor的原理
- 6、BeanPostProcessor在IOC底层的使用
- 三、属性赋值与自动装配
- @Value注解使用
- @PreopertySource 读取properties配置文件中的key-value
- @Autowired , @Qualifier, @Primary属性自动注入
- @Resource, @Inject 注解
- @Autowired在构造器,方法,参数上的注解
- 自定义组件使用Spring容器底层的组件
- 四、@Profile
一、组件注册
给容器中注册组件:
- 包扫描+组件标记注解( @Controller, @Service,@Repository,@Component )。
- @Bean [快速导入第三方包里面的组件]。
- @Import [快速给容器中导入一个组件]。 直接标注在java配置文件的类上,快速引入第三方组件. @Import({ 要导入的组件类名.class }),bean的id默认为全类名。
- @ImportSelector 批量快速导入第三方组件。
- @@ImportBeanDefinitionRegister 手动批量导入第三方组件。
- FactoryBean注册Bean。
1、java配置类注解@configuration和@bean
- 基于注解的Spring容器的实例类为: AnnotationConfigApplicationContext
ApplicationContext context = new AnnotationConfigApplicationContext(JavaConfig.class, JavaConfig2.class);
- @configuration :
- 被标记的文件为java配置文件。相当于xml配置文件。
- spring允许多个@configuration标记的java配置文件同时存在且读取。
- @bean:
- 用于@configuration的java配置文件中的方法, 被@Bean标记的方法,被称为工厂方法。
- Bean创建时,如果不指定value属性,那么默认为工厂方法的名字作为bean的id属性值。
## java配置类1
@Configuration
public class JavaConfig {
@Bean
public HelloWorld helloWorld2(){
return new HelloWorld();
}
}
## java配置类2
@Configuration
public class JavaConfig2 {
@Bean
public HelloWorld helloWorld1(){
return new HelloWorld();
}
}
## 创建IOC容器,并获取bean
## 创建IOC容器,并且读取配置文件
ApplicationContext context = new AnnotationConfigApplicationContext(JavaConfig.class, JavaConfig2.class);
HelloWorld helloWorld1 = (HelloWorld) context.getBean("helloWorld1");
System.out.println(helloWorld1);
HelloWorld helloWorld2 = (HelloWorld) context.getBean("helloWorld2");
System.out.println(helloWorld2);
2、@ComponentScan自动扫描注解,@CompentScan.Filter使用
- @ComponentScan : value,指明要扫描的包;
- excludeFilters = Filter[],指定扫描的时候按照什么规则排除组件。
- includeFilters = Filter[],指定扫描的时候只需要包含哪些组件。
- @CompoentScan设置一个或者多个扫描路径。
(1)@ComponentScan 表示设置需要扫描的文件夹以及子文件夹。
(2) jdk1.8以后,允许设置多个@ComponentScan来设置需要扫描的多个文件夹路径。 如果不支持配置多个,可以用一下方式。@ComponentScans({ @ComponentScan("com.mz.controller"), @ComponentScan("com.mz.service") })
2.1、@ComponentScan使用
# java配置文件
# @Configuration 表示被修饰的类是java配置类。
# @ComponentScan 表示设置需要扫描的文件夹以及子文件夹。
# jdk1.8以后,允许设置多个@ComponentScan来设置需要扫描的多个文件夹路径。
@Configuration
@ComponentScan( value="com.mz" )
public class JavaConfig {
}
# @Controller
@Controller
public HelloController {
public void test(){
System.out.println("hello controller");
}
}
# @Service
@Service
public HelloService {
public void test(){
System.out.println("hello service");
}
}
2.2、@CompentScan,excludeFilter, @Component.Filter的使用
- excludeFilter表示扫描路径下,需要排除的类型。
# java配置类
@Configuration
@ComponentScan( value="com.mz", excludeFilter = {
@ComponentScan.Filter( type=FilterType.ANNOTATION, classes = { Controller.class } )
} )
2.3、@CompentScan, includeFilter, @Component.Filter的使用
- includeFilter表示扫描路径下,需要包含的类型;如果不是该类型,则排除。
- includeFilter的使用,必须要设置useDefaultFilters=false才能生效。
@Configuration
@ComponentScan( value="com.mz", includeFilter = {
@ComponentScan.Filter( type = FilterType.ANNOTATION, classes = { Controller.class , Service.class })
}, useDefaultFilters = false )
3、@ComponentScan.Filter过滤规则 与自定义过滤规则
- FilterType的类型
- FilterType. ANNOTATION : 按照标注的注解类型进行过滤。
- FilterType.ASSIGNABLE_TYPE : 按照标注的注解的类的实际类型进行过滤。
- FilterType.ASPECTJ : AspectJ表达式。(基本不使用)
- FilterType.REGEX : 按照正则表达式进行过滤。
- FilterType.CUSTOM : 自定义过滤规则。
3.1、TypeFilter接口实现:
- springIOC会扫描指定路径的所有文件,然后调用 MyTypeFilter的match方法,来判断当前扫描到的类是否需要创建实例。
- match方法的两个参数:metadataReader : 读取到的当前正在扫描的类的信息。metadataReaderFactory : 可以所有已经扫描到的类的信息。
- 可以通过metadataReader获取当前类的注解信息,获取当前类的类信息,获取当前类资源(指出当前文件所在的路径)。
# 关于type=FilterType.CUSTOM的使用
# java配置类
@Configuration
@ComponentScan( value="com.mz", includeFilters = {
@Component.Filter( type=FilterType.CUSTOM, classes = { MyTypeFilter.class } )
} )
public class JavaConfig {
}
# TypeFilter接口的实现
public class MyTypeFilter implements TypeFilter {
/**
* springIOC会扫描指定路径的所有文件,然后调用 MyTypeFilter的match方法,来判断当前扫描到的类是否需要创建实例。
* 如果是返回true,则创建;如果是返回false,则不创建。
*
* metadataReader : 读取到的当前正在扫描的类的信息。
* metadataReaderFactory : 可以所有已经扫描到的类的信息。
* */
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
//获取当前类的注解信息
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
//获取当前类的类信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
//获取当前类资源(指出当前文件所在的路径)
Resource resource = metadataReader.getResource();
System.out.println("=======================>");
System.out.println(annotationMetadata);
System.out.println(classMetadata);
System.out.println(resource);
System.out.println("<=======================");
return true;
}
}
4、组件的作用域 @Scope注解
-
@Scope注解: 控制对象创建的作用域
- @Scope(“prototype”)原型: 多实例,IOC容器启动并不会去调用方法创建对象放到容器中。每次获取都会调用方法去创建实例。
- @Scope(“singleton”)单例: 只有一个实例,IOC容器启动会调用方法创建对象放到IOC容器中,以后每次获取就直接从容器(map.get())中获取。
- @Scope(“request”):同一次request请求创建一个实例。
- @Scope(“session”): 同一个session创建一个实例。
-
@Scope注解不仅可以在 标注含有@Bean的工厂方法,也可以在@Controller, @Service注解的类上起作用。
@Configuration
public class JavaConfig {
@Bean
@Scope("prototype")
public Person person(){
return new Person("张三", 25);
}
}
#controller类
@controller
@Scope("prototype")
public HelloController {
}
#main方法中
ApplicationContext context = new AnnotationConfigApplicationContext(JavaConfig.class);
HelloController helloController = (HelloController) context.getBean("helloController");
HelloController helloController1 = (HelloController) context.getBean("helloController");
System.out.println(helloController == helloController1);
5、单实例懒加载 @Lazy
懒加载:单实例Bean,默认在容器启动的时候创建对象。而设置@Lazy的单实例,容器启动不会创建实例,而是在第一次使用(获取)Bean创建对象。
@Lazy
@bean("person")
public Person person(){
System.out.println("给容器中添加Person。。。");
return new Person("张三",25);
}
6、按照条件给容器注册Bean @Conditional注解
- @conditional :按照一定条件进行判断,满足条件则向容器中注册Bean,不满足则不注入。对需要进行条件注册的Bean添加 @Bean,@Conditional注解标记。实现Condition接口。为某个Bean是否要进行条件判断提供方法调用。
- @conditional注解也可以标记在类上,如果条件满足,则该java配置类上所有的Bean都注册到IOC容器中;如果Condition条件不满足,则该类所有的bea都不注册。
#java配置类中
@Configuration
public class JavaConfig {
@Conditional( { WindowsCondition.class } )
@Bean("bill")
public Person person(){
return new Person("bill");
}
@Conditional( {LinuxCondition.class} )
@Bean("linus")
public Person person2(){
return new Person("linus");
}
}
#实现Condition接口
public class LinuxCondition implements Condition {
#ConditionContext: ·判断条件·能使用的上下文环境。
#AnnotationedTypeMeta: 注解信息
public boolean matchs( ConditionContext context, AnnotationedTypeMetadata metadata ){
#1.能获取到IOC的beanFactory
ConfigurableListBeanFactory beanFactory = context.getBeanFactory();
#2.能获取类加载器
ClassLoader classLoader = context.getClassLoader();
#3.获取当前环境信息(运行时信息:虚拟机变量,环境变量等)
Environment environment = context.getEnvironment();
#4.获取bean定义的注解类
BeanDefinitionRegistry registry = context.getRegistry();
String osName = environment.getProperty("os.name");
if( osName.contains("Windows") ){
return false;
}
return true;
}
}
public class WindowsCondition implements Condition {
#ConditionContext: ·判断条件·能使用的上下文环境。
#AnnotationedTypeMeta: 注解信息
public boolean matchs( ConditionContext context, AnnotationedTypeMetadata metadata ){
#1.能获取到IOC的beanFactory
ConfigurableListBeanFactory beanFactory = context.getBeanFactory();
#2.能获取类加载器
ClassLoader classLoader = context.getClassLoader();
#3.获取当前环境信息(运行时信息:虚拟机变量,环境变量等)
Environment environment = context.getEnvironment();
#4.获取bean定义的注解类
BeanDefinitionRegistry registry = context.getRegistry();
String osName = environment.getProperty("os.name");
if( osName.contains("Windows") ){
return true;
}
return false;
}
}
7、导入第三方组件
7.1、@Import注解
# @Import快速引入第三方组件
# 使用@Import快速引入的第三方组件,bean的id默认为全类名。
@Configuration
@Import({Yellow.class, Red.class})
public class JavaConfig{
#其实也可以使用@Bean引入第三方组件。
#使用@Bean导入第三方库,可以指定对象在IOC中的名字。
@Bean
public HelloWorld helloWorld(){
return new HelloWorld();
}
}
7.2、 @ImportSelector注解
- 实现ImportSelector接口,可以在该实现类中批量导入第三方组件。(虽然@import也可以批量导入组件,但是如果有大量的第三方组件导入,java配置类顶部 显得太杂乱。)
#自定义逻辑返回需要导入的组件。
public class MyImportSelector implements ImportSelector {
//返回值就是要导入到容器中的组件全类名。
//AnnotaionMetadata: 当前标注@Import注解类的所有注解信息.
public Stirng[] seelctImports( AnnotationMetaData importClassName ){
//返回需要批量导入的第三方组件。
//返回要导入的第三方组件的全类名。
return new String[]{ "com.mz.Blue", "com.mz.Yellow" }
}
}
- 在java配置勒种,使用 @import 导入 MyImportSelector.
# MyImportSelector需要通过@import导入。通过@Bean形式导入失效。
@import({ Yellow.class, Red.class, MyImportSelector.class })
@Configuration
public class Test {
...
}
7.3、@ImportBeanDefinitionRegister : 手动注册bean到容器中
- 创建类,实现ImportBeanDefinitionRegister接口。
public class MyImportBeanDefinitionRegister implements ImportBeanDefinitionRegistrar {
//AnnotationMetadata : 当前类的注解信息
//BeanDefinitionRegistry : BeanDefinition注册类,把所有需要添加到容器中的Bean,通过BeanDefinitionRegistry添加到IOC容器中。
@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
//RootBeanDefinition: 指定Bean的定义信息(Bean类型,scope等信息)。相当于<bean>
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(RainBow.class);
beanDefinitionRegistry.registerBeanDefinition("rainBow", rootBeanDefinition);
}
}
- 在java配置类中,使用@import导入这个类。
@import({ MyImportBeanDefinitionRegister.class })
@Configuration
public class Test {
...
}
8、使用FactoryBean注册组件
使用Spring提供的Factorybean(工厂Bean)
-
默认获取到的是工厂bean调用getObject创建的对象。
-
要获取工厂Bean本身,我们需要在id前面加一个&符号即可。
-
-
java配置类中
根据colorFactoryBean这个id获取到的,实际上是Color的实例对象。
@Configuration
public class JavaConfig {
//根据colorFactoryBean这个id获取到的,实际上是Color的实例对象。
@Bean
public ColorFactoryBean colorFactoryBean(){
return new ColorFactoryBean();
}
}
- 创建FactoryBean的工厂实现类
public class ColorFactoryBean implements FactoryBean {
//返回一个Color对象,这个对象会添加到容器中。
public Color getObject() throws Exception {
return new Color();
}
//返回Color的类型,
public Class<?> getObjectType(){
return Color.class;
}
//告诉容器,是否是单例
public boolean isSingleton(){
return true;
}
}
- 在SpringIOC获取bean
# SpringIOC默认获取到的 FactoryBean,是FactoryBean实现类的getObject()方法返回的对象。
ApplicationContext context = new AnnotationConfigApplicationContext(JavaConfig.class);
RainBow rainBow = (RainBow) context.getBean("myFactoryBean");
System.out.println(rainBow);
#也可以通过&来指定获取FactoryBean对象本身。
MyFactoryBean factoryBean = (MyFactoryBean) context.getBean("&myFactoryBean");
System.out.println(factoryBean);
二、 Bean的生命周期
- bean的生命周期管理
- (1) 通过构造器或者工厂方法创建Bean实例。
- (2) 为Bean的属性设置值,以及其他Bean的引用。
- (3) 将Bean实例传递给Bean后置处理器的postProcessBeforeInitialization方法。
- (4) 调用Bean的初始化方法。 #@Bean的initMethod属性
- (5) 将Bean实例传递给BeanPostProcessor后置处理器的postProcessAfterInitialization方法。
- (6) Bean对象的获取,以及Bean对象方法的调用。
- (7) 当容器关闭时,调用Bean的销毁方法。 #@Bean的destroyMethod属性。
1、使用@Bean的initMethod属性,destroyMethod属性,设置Bean初始化,和销毁管理。
- 单实例Bean的销毁: 发生在容器关闭的时候。
- 多实例Bean的销毁: 容器不会管理这个bean,容器不会调用销毁方法。
#java配置文件
#通过指定@Bean的initMethod,destroyMethod来指定bean的初始化,销毁管理。
@Configuration
public class JavaConfig {
@Bean( value = "rainBow", initMethod = "init", destroyMethod = "destroy")
public RainBow rainBow(){
return new RainBow();
}
}
2、javaBean对象实现initializingBean接口,DisposableBean接口
实现initializingBean接口,DisposableBean接口的对象,不再需要@Bean的initMethod.,destroyMethod指定生命周期的初始化,销毁的方法。
public class RainBow implements InitializingBean, DisposableBean {
/**
* 当bean创建并且初始化完成之后,调用该方法
* */
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("Bean创建完成,并且初始化之后调用。");
}
/**
* 当单例bean被容器销毁时,会调用该方法。
* */
@Override
public void destroy() throws Exception {
System.out.println("单例Bean销毁时调用。多实例Bean不会被IOC管理生命周期。");
}
}
3、javaBean对象上标注@PostStruct表示容器初始化时调用,@PreDestroy表示容器移除对象之前调用。
public class RainBow {
/**
* @PostConstruct注解标注,当bean创建并且初始化完成之后,调用该方法
* */
@PostConstruct
public void init() throws Exception {
System.out.println("Bean创建完成,并且初始化之后调用。");
}
/**
* @PreDestroy注解标注,当单例bean被容器销毁时,会调用该方法。
* */
@PreDestroy
public void destroy() throws Exception {
System.out.println("单例Bean销毁时调用。多实例Bean不会被IOC管理生命周期。");
}
}
4、BeanPostProcessor接口实现Bean的统一处理。
- Bean后置管理器允许在调用"初始化方法前后"对Bean进行额外的处理。
- Bean后置管理器对SpringIOC容器里的所有Bean实例进行逐一处理,而非仅仅是针对某个实例。
- 对Bean后置处理器而言,需要实现Interface BeanPostProcessor接口,在初始化方法被调用前后。Spring将每个Bean实例分别递给上述接口的一下两个方法:
- (1) Object postProcessAfterInitialization( Object bean, String beanName );
- (2) Object postProcessBeforeInitialization( Object bean, String beanName );
- BeanPostProcessor后置管理器使用场景:
- 对bean对象的检查,替换;
- 对Bean对象属性的检查,替换;
#使用@Component对MyBeanPostProcessir注册到IOC容器即可。IOC容器能自动识别到BeanPostProcessor接口的实现类。当只要有bean实例创建,就会调用BeanPostProcessor接口的实现类中的before,after方法。
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
return null;
}
@Override
public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
return null;
}
}
5、BeanPostProcessor的原理
- 遍历得到容器中所有的BeanPostProcessor,挨个执行postProcessBeforeInitialization.一旦返回null,就跳出for循环,不会执行后面的postProcessAfterInitialization。
- BeanPostprocessor原理:
- 先给bean进行属性赋值. populateBean( beanName, mid, instanceWrapper );
- 再调用BeanPostProcessorsBeforeInitialization.(applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName));
- 再执行自定义初始化(initMethod).(invokeInitMethods(beanName, wrapperBean, mbd));
- 最后执行BeanPostProcessorsAfterInitialization( wrappedBean, beanName );
6、BeanPostProcessor在IOC底层的使用
spring底层对 BeanPostProcessor 的使用:
- bean赋值
- 注入其他组件
- @Autowired注解功能实现
- 声明周期注解功能
- @Async
- xxx BeanPostProcessor
三、属性赋值与自动装配
@Value注解使用
- @Value(“基本类型数值”) => 使用基本类型值。
- @Value("#{SpEL表达式}")。=>使用SpEL表达式,#{}
- @Value(" {}
@Data
public class Person {
@Value("张三")
private String name;
@Value("#{20-2}")
private Integer age;
@Value("${gender}")
private Integer gender;
}
@PreopertySource 读取properties配置文件中的key-value
- 使用@PropertySource读取外部配置文件中key-value保存到环境变量中; 加载完外部的配置文件以后,使用${}取出配置文件中的值。
- @PropertySource注解引入的properties配置文件,会将其值读取到environment环境变量中。
ConfigurableEnvironment environment = applicationContext.getEnvironment();
String property = environment.getProperty("name");
Systen.out.println(property);
#java配置类文件中
@Configuration
@PropertySource( value={ "classpath:/JavaConfig.properties" }, encoding = "utf-8")
public class JavaConfig {
@Bean
public Person person(){
return new Person();
}
}
#在javaBean中使用 ${} 获取properties中的key-value。
@Data
public class Person {
@Value("张三")
private String name;
@Value("${gender}")
private Integer gender;
}
@Autowired , @Qualifier, @Primary属性自动注入
- @Autowired注解标注的成员属性
- 容器中只存在一个该类型的bean实例,则直接用这个bean实例进行属性注入。
- 容器中存在多个该类型的bean实例,此时通过类型无法指定具体的Bean实例,但是IOC容器不会报错。IOC容器会根据属性名作为id去匹配IOC容器中的bean,如果匹配到,则进行属性注入。
- 如果容器中不存在该类型的bean实例,则SpringIOC容器会抛出异常。
- 可以使用@Autowired( required=false )来表示属性注入不是必须。
#java配置类
@Configuration
@ComponentScan( "com.mz" )
public JavaConfig {
}
#组件对象创建
@Controller
public HelloController {
@Autowired
private HelloService helloService;
public void sayHello(){
helloService.sayHello();
}
}
@Service
public HelloService {
public void sayHello(){
System.out.println("hello, service");
}
}
- @Qualifier(“name”)注解标注的属性成员
- 被标注的注解,不再先通过class类型去IOC容器中查找,而是直接使用id值去查找bean。
@Controller
public HelloController {
@Qualifier("helloService1")
@Autowired
private HelloService;
}
- @Primary注解标注的成员属性
当Spring进行自动装配的时候,可以使用@Primary来指定首选的bean。当然也可以继续使用@Qualifier指定需要装配的bean的名字。
#通过@Primary指定首选项。
@Service
@Primary
public class HelloService {
}
#或者在bean上指定@primary
@Configuration
public JavaConfig {
@Primary
@Bean
public HelloService helloService(){
return HelloService();
}
}
@Resource, @Inject 注解
- @Resource 注解:
- @Resource可以和@Autowired一样实现自动装配功能,默认是按照组件名称进行装配的。也可以通过@Resource(name=“id值”)来指定bean的id。
- @Resource没有能支持@Primary功能,没有能支持@Autowired(required=false);
@Controller
public class HelloController {
@Resource
private HelloService helloService;
}
-
@Inject 注解:
- 需要导入javax.inject的包,和Autowired的功能一样,但是不支持required=false的设置。
-
@Autowired是spring定义的,推荐使用@Autowired注解来进行自动装配。 @Resource.@Inject都是java规范。
@Autowired在构造器,方法,参数上的注解
- @Autowired 标注在构造器上
- 如果存在多个构造器函数,SpringIOC容器会自动调用被@Autowired标注的构造函数,构造器所需要的对象型参数,会从IOC容器中去查找。
- 如果存在多个构造器函数,都没有标注@Autowired或者有多个标注了@Autowired,那么IOC容器会抛出异常。
- 如果只存在一个构造函数,则无论标注不标注@Autowired,ICO容器在创建该实例的时候,都会调用该构造函数,且所需的参数对象,都从IOC中去查找。
- 如果不存在构造函数,则调用默认的无参构造器。
@Service
public HelloController {
private Rainbox rainbox;
private HelloService helloService;
#标注有@Autowired的方法,为IOC默认调用的构造方法。
@Autowired
public HelloController( HelloService helloService, Rainbox rainbow ){
this.helloService = helloService;
this.rainbox = rainbox;
}
public HelloController( HelloService helloService ){
this.helloService = helloService;
}
}
- @Autowired 标注在setter方法上
- @Autowired标注在setter方法上,则IOC容器会调用该setter方法,且方法上的参数,会从IOC容器中去查找。
#可以放在setter方法上
@Autowired
public void setHelloService( HelloService helloService ){
this.helloService = helloService;
}
#等同于放在成员属性上
@Autowired
private HelloService helloService;
- @Autowired 标注在工厂方法上
- java配置文件中,使用@Bean标注的工厂方法,将会自动从IOC容器中去查看方法中的参数对象进行注入。(也可以省略该@Autowired)
@Bean
@Autowired
public HelloController helloController( HelloService helloService, RainBow rainBow ){
System.out.println(helloService);
System.out.println(rainBow);
HelloController helloController = new HelloController();
helloController.setHelloService(helloService);
return helloController;
}
自定义组件使用Spring容器底层的组件
自定义组件想要使用spring容器底层的一些组件(ApplicationContext, BeanFactory,xxx)。自定义组件实现xxxAware,在创建对象的时候,会调用接口规定的方法注入相关组件:Aware。把Spring底层一些组件注入到自定义的Bean中。
- xxxxAware , 功能使用xxxProcessor,
- ApplicationContextAware ==> ApplicationContextAwareProcessor
四、@Profile
Spring为我们提供的可以根据当前环境 动态的激活和切换一系列组件的功能。
- @Profile("") 注解标注在类上,则表示如果是当前环境,那么就整个类中所有的bean都注册到IOC容器中,否则都不注册。
- @Profile("")注解标注在@Bean上,则表示当前的bean根据当前的环境是否注册到IOC容器中。
#@Profile可以标注在类上。
@Profile("test")
@Configuration
public class JavaConfig{
@Profile也可以标注在方法上。
@Profile("dev")
@Bean
public HelloController( HelloService helloService ){
`HelloController helloController = new HelloController();
helloController.setHelloService(helloService);
return helloController;
}
}
环境变量设置:
/**
* 1.使用命令行动态参数: 在虚拟就参数位置加载 -Dspring.profiles.active=test
* 2.代码的方式设置
* //创建容器
* ApplicationContext context = new AnnotationConfigApplicationContext(JavaConfig.class);
* //设置环境
* applicationContext.getEnvironment().setActiveProfiles("test", "dev");
* //注册配置类
* applicationContext.register(JavaConfig.class);
* //启动刷新容器
* applicationContext.refresh();
*
*/
public static void main( String[] args )
{
//1、创建IOC容器,并且读取配置文件
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
//2、设置环境
context.getEnvironment().setActiveProfiles("dev");
//3、注册配置类
context.register(JavaConfig.class);
//4、启动刷新容器
context.refresh();
}