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();
}