java教程 springIOC 基于注解

一、组件注册

给容器中注册组件:

  • 包扫描+组件标记注解( @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[],指定扫描的时候只需要包含哪些组件。
  1. @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(" " ) = > 使 p r o p e r t i e s , {配置文件的值}") => 使用properties配置文件中的值, {}
@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();
  }
  
发布了58 篇原创文章 · 获赞 34 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_36723759/article/details/104105939