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("")=>使properties,{配置文件的值}") => 使用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();
  }
  
發佈了49 篇原創文章 · 獲贊 34 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章