Spring注解驅(qū)動開發(fā)之常用注解案例
注解驅(qū)動開發(fā)就是不再使用Spring的bean.xml文件,改為純使用注解的方式開發(fā)
1. 組件注冊注解
1.1 @Configuration和@Bean注解
-
@Configuration
此注解為配置類注解,相當(dāng)于spring.xml文件,即配置類==配置文件
-
@Bean
給容器中注冊一個Bean;類型為返回值的類型,id默認是用方法名作為id
- 示例
package com.yuan.annotation.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import com.yuan.annotation.bean.Person;
//配置類==配置文件
@Configuration //告訴Spring這是一個配置類
public class MainConfig {
//給容器中注冊一個Bean;類型為返回值的類型,id默認是用方法名作為id
@Bean("person")
public Person personA() {
return new Person(1,"張三",33);
}
}
Person類(后續(xù)注解配置類中都會以此類舉例),Person.java
package com.yuan.annotation.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
@NoArgsConstructor
@AllArgsConstructor
@Data
@ToString
public class Person {
private Integer id;
private String name;
private Integer age;
}
測試類
package com.yuan.annotation;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.yuan.annotation.bean.Person;
import com.yuan.annotation.config.MainConfig;
public class MainTest {
private static ApplicationContext applicationContext;
public static void main(String[] args) {
applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
/*
* Person person = applicationContext.getBean(Person.class);
* System.out.println(person);
*/
String [] nameTypes = applicationContext.getBeanNamesForType(Person.class);
for(String s : nameTypes) {
System.out.println(s);
}
Person person = (Person) applicationContext.getBean("person");
System.out.println(person);
}
}
1.2 自動掃描組件和指定掃描規(guī)則
- @ComponentScan 自動掃描組件注解,jdk8+版本,此注解可以在同一個類上多寫幾次,jdk8以下版本可以使用@ComponentScans注解
jdk8+版本示例
//配置類==配置文件
@Configuration //告訴Spring這是一個配置類
@ComponentScan(value = "com.yuan.annotation",includeFilters= {
@Filter(type = FilterType.ANNOTATION,classes = {Controller.class})
},useDefaultFilters=false) //指定要掃描的包
@ComponentScan(.....)
@ComponentScan(.....)
@ComponentScans(value = { @ComponentScan(value="xx.xxx") })
public class MainConfig {
//給容器中注冊一個Bean;類型為返回值的類型,id默認是用方法名作為id
@Bean("person")
public Person personA() {
return new Person(1,"張三",33);
}
}
jdk8以下版本示例
//配置類==配置文件
@Configuration //告訴Spring這是一個配置類
@ComponentScans(value = { @ComponentScan(value="xx.xxx") })
public class MainConfig {
...
}
-
value:數(shù)組類型,指定要掃描的包
-
includeFilters:Filter數(shù)組類型,指定掃描時包含哪些組件,使用此屬性時,@ComponentScan的useDefaultFilters屬性值設(shè)置false才能起作用,即useDefaultFilters=false;useDefaultFilters=true為默認值,掃描所有
-
excludeFilters:Filter數(shù)組類型,指定掃描時排除哪些組件
package com.yuan.annotation.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
import org.springframework.context.annotation.ComponentScan.Filter;
import com.yuan.annotation.bean.Person;
//配置類==配置文件
@Configuration //告訴Spring這是一個配置類
//@ComponentScan(value= {"com.yuan.annotation.bean","com.yuan.annotation.dao","com.yuan.annotation.service"})
@ComponentScan(value = "com.yuan.annotation",includeFilters= {
@Filter(type = FilterType.ANNOTATION,classes = Controller.class)
}) //指定要掃描的包
public class MainConfig {
//給容器中注冊一個Bean;類型為返回值的類型,id默認是用方法名作為id
@Bean("person")
public Person personA() {
return new Person(1,"張三",33);
}
}
1.3 自定義TypeFilter指定過濾規(guī)則
- FilterType.ANNOTATION:按照注解(常用)
- FilterType.ASSIGNABLE_TYPE:按照指定的類型(常用)
- FilterType.ASPECTJ:使用ASPECTJ表達式
- FilterType.CUSTOM:使用用戶自定義規(guī)則
- FilterType.REGEX:使用正則表達式
- 自定義規(guī)則類,如:MyTypeFilter.java
- 自定義過濾規(guī)則類需要實現(xiàn)TypeFilter接口
package com.yuan.annotation.config;
import java.io.IOException;
import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;
public class MyTypeFilter implements TypeFilter {
/*
* metadataReader:讀取到的當(dāng)前正在掃描的類
* metadataReaderFactory:可以獲取到其他任何類信息的
*/
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
throws IOException {
//獲取當(dāng)前類注解的信息
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
//獲取當(dāng)前正在掃描的類的信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
//獲取當(dāng)前類資源(類的路徑)
Resource resource = metadataReader.getResource();
String className = classMetadata.getClassName();
System.out.println("--->"+className);
//如果className中包含er,表示匹配成功
if(className.contains("er")) {
return true;
}
return false;
}
}
- 配置類,MainConfig.java
package com.yuan.annotation.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.ComponentScans;
import com.yuan.annotation.bean.Person;
import com.yuan.annotation.service.BookService;
//配置類==配置文件
@Configuration //告訴Spring這是一個配置類
@ComponentScan(value = "com.yuan.annotation",includeFilters= {
@Filter(type = FilterType.CUSTOM,classes = {MyTypeFilter.class})
},useDefaultFilters=false) //指定要掃描的包
@ComponentScans(value = { @ComponentScan(value="xx.xxx") })
public class MainConfig {
//給容器中注冊一個Bean;類型為返回值的類型,id默認是用方法名作為id
@Bean("person")
public Person personA() {
return new Person(1,"張三",33);
}
}
- 測試類IOCTest.java
package com.yuan.annotation.test;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.yuan.annotation.config.MainConfig;
public class IOCTest {
private AnnotationConfigApplicationContext applicationContext;
@Test
public void test01() {
applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
String [] definitionNames = applicationContext.getBeanDefinitionNames();
for(String beanName : definitionNames) {
System.out.println(beanName);
}
}
}
- 打印結(jié)果:
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
person
myTypeFilter
bookController
bookService
1.4 @Scope設(shè)置組件的作用域
- 配置類,ScopeConfig.java
package com.yuan.annotation.config;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import com.yuan.annotation.bean.Person;
@Configuration
public class ScopeConfig {
/**
* @see ConfigurableBeanFactory#SCOPE_PROTOTYPE
* @see ConfigurableBeanFactory#SCOPE_SINGLETON
* @see org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST
* @see org.springframework.web.context.WebApplicationContext#SCOPE_SESSION
*
* singleton: 單實例(默認),IOC容器啟動時會調(diào)用方法創(chuàng)建對象放到IOC容器中
* prototype: 多實例的,IOC啟動時不會去調(diào)用方法創(chuàng)建對象放在容器中,每次獲取的時候才會調(diào)用方法創(chuàng)建對象
* request: 同一次請求創(chuàng)建一個實例
* session: 同一次會話創(chuàng)建一個實例
*
*/
@Scope("prototype")
@Bean("person")
public Person person() {
System.out.println("給容器中添加Person對象....");
return new Person(1,"張三",22);
}
}
- 測試類,IOCTest.java
package com.yuan.annotation.test;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.yuan.annotation.bean.Person;
import com.yuan.annotation.config.MainConfig;
import com.yuan.annotation.config.ScopeConfig;
public class IOCTest {
private AnnotationConfigApplicationContext applicationContext;
@Test
public void test02() {
applicationContext = new AnnotationConfigApplicationContext(ScopeConfig.class);
/*
* String [] definitionNames = applicationContext.getBeanDefinitionNames();
* for(String beanName : definitionNames) { System.out.println(beanName); }
*/
//默認為單實例的
Person person = (Person) applicationContext.getBean("person");
Person person2 = (Person) applicationContext.getBean("person");
System.out.println(person == person2);
}
}
1.5 @Lazy注解,bean懶加載注解
package com.yuan.annotation.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import com.yuan.annotation.bean.Person;
@Configuration
public class LazConfig {
/**
* @Lazy:懶加載,針對scope為單實例的bean而言
* 單實例bean,默認容器啟動的時候創(chuàng)建
* 懶加載:容器啟動時不創(chuàng)建對象,第一次使用(獲取)Bean對象,并初始化
* @return
*/
@Lazy
@Bean
public Person person() {
return new Person(1,"張三",22);
}
}
1.6 @Conditional-按照條件注冊bean
@Conditional({Condation}) : 按照一定的條件進行判斷,滿足條件給容器中注冊bean
案例:根據(jù)操作系統(tǒng)的創(chuàng)始人來實例對應(yīng)的Person
- 需要定義兩個Condition類,如LinuxCondition.java和WindowsCondition.java
-
LinuxCondition.java和WindowsCondition.java必須實現(xiàn)Condition接口
-
WindowsCondition.java
package com.yuan.annotation.condition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
/**
* 判斷是否為Windows系統(tǒng)
* @author jinshengyuan
*
*/
public class WindowsCondition implements Condition{
/**
* ConditionContext : 判斷條件能使用的上下文(環(huán)境)
* AnnotatedTypeMetadata : 注解信息
*/
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
//判斷是否Linux系統(tǒng)
//1.能獲取到IOC使用的beanFactory
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
//2.獲取類加載器
ClassLoader classLoader = context.getClassLoader();
//3.獲取當(dāng)前環(huán)境信息
Environment environment = context.getEnvironment();
//4.獲取bean定義的注冊類
BeanDefinitionRegistry registry = context.getRegistry();
//可以判斷容器中的bean注冊情況,也可以給容器中注冊bean
boolean beanDefinition = registry.containsBeanDefinition("person");
String property = environment.getProperty("os.name");
//如果property中包含Windows,則返回true
if(property.contains("Windows")) {
return true;
}
return false;
}
}
- LinuxCondition.java
package com.yuan.annotation.condition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
/**
* 判斷是否為Linux系統(tǒng)
* @author jinshengyuan
*
*/
public class LinuxCondition implements Condition {
/**
* ConditionContext : 判斷條件能使用的上下文(環(huán)境)
* AnnotatedTypeMetadata : 注解信息
*/
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
//判斷是否Linux系統(tǒng)
//1.能獲取到IOC使用的beanFactory
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
//2.獲取類加載器
ClassLoader classLoader = context.getClassLoader();
//3.獲取當(dāng)前環(huán)境信息
Environment environment = context.getEnvironment();
//4.獲取bean定義的注冊類
BeanDefinitionRegistry registry = context.getRegistry();
//可以判斷容器中的bean注冊情況,也可以給容器中注冊bean
boolean beanDefinition = registry.containsBeanDefinition("person");
String property = environment.getProperty("os.name");
//如果property中包含Linux,則返回true
if(property.contains("Linux")) {
return true;
}
return false;
}
}
- @Conditional注解配置類
package com.yuan.annotation.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import com.yuan.annotation.bean.Person;
import com.yuan.annotation.condition.LinuxCondition;
import com.yuan.annotation.condition.WindowsCondition;
@Configuration
public class ConditionalConfig {
/**
* @Conditional({Condation}) : 按照一定的條件進行判斷,滿足條件給容器中注冊bean
* @Conditional可以標(biāo)注在類上,也可以標(biāo)注在方法上
* 標(biāo)注在類上:類中組件統(tǒng)一設(shè)置,滿足當(dāng)前條件,這個類中配置的所有bean才能生效
* 需求:
* 如果系統(tǒng)是Windows,給容器中注冊("bill")
* 如果是Linux系統(tǒng),給容器中注冊("linus")
*/
//如果為Windows系統(tǒng)則實例化bill類
@Conditional({WindowsCondition.class})
@Bean("bill")
public Person person() {
return new Person(1,"Bill Gates",65);
}
//如果為Linx系統(tǒng)則實例化linus類
@Conditional({LinuxCondition.class})
@Bean("linus")
public Person person1() {
return new Person(1,"linus",48);
}
}
- 測試類
package com.yuan.annotation.test;
import java.util.Map;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import com.yuan.annotation.bean.Person;
import com.yuan.annotation.config.ConditionalConfig;
import com.yuan.annotation.config.MainConfig;
import com.yuan.annotation.config.ScopeConfig;
public class IOCTest {
private AnnotationConfigApplicationContext applicationContext;
@Test
public void test03() {
applicationContext = new AnnotationConfigApplicationContext(ConditionalConfig.class);
ConfigurableEnvironment environment = applicationContext.getEnvironment();
//動態(tài)獲取環(huán)境變量的值:Windows 10
String osName = environment.getProperty("os.name");
System.out.println(osName);
//獲取已定義的bean
String [] definitionNames = applicationContext.getBeanDefinitionNames();
for(String beanName : definitionNames) {
System.out.println(beanName);
}
Map<String, Person> map = applicationContext.getBeansOfType(Person.class);
System.out.println(map);
}
}
- 輸出結(jié)果
由于是Windows 10,則只有bill類被實例化
Windows 10
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
conditionalConfig
bill
{bill=Person(id=1, name=Bill Gates, age=65)}
2. 給容器中注冊組件的方式
2.1 包掃描+組件標(biāo)注注解
@Controller/@Service/@Repository/@Component)[只適用于自己寫的類]
2.2 @Bean
[導(dǎo)入的第三方包里面的組件]
2.3 @Import[快速給容器中導(dǎo)入一個組件]
2.3.1 @Import(要導(dǎo)入到容器中的組件)
容器中就會自動注冊這個組件,id默認是全類名(如下面的com.yuan.bean.Color)文章來源:http://www.zghlxwxcb.cn/news/detail-811121.html
- 定義一個Color.java類
package com.yuan.bean;
/**
* color 類
*/
public class Color {
}
- 在ColorMainConfig.java中使用@Import注解向容器中注入Color類
package com.yuan.config;
import com.yuan.bean.Color;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* @Author: Jinsheng·yuan
* @CreateDate: 2020/1/14 21:59
* @Description: 使用@Import 注冊組件
*/
@Configuration
@Import(Color.class) //注入單個組件
//@Import({Color.class,Red.class}) //注入多個組件
public class ColorMainConfig {
}
- 單元測試
package com.yuan.test;
import com.yuan.config.ColorMainConfig;
import com.yuan.config.MainConfig;
import com.yuan.config.MyConfigTwo;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* @Author: Jinsheng·yuan
* @CreateDate: 2020/1/14 21:59
* @Description: 使用@Import 注冊組件
*/
public class IOCTest {
private AnnotationConfigApplicationContext applicationContext;
/**
* 使用@Import注解向容器注入組件測試
*/
@Test
public void testImport(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ColorMainConfig.class);
printBeans(applicationContext);
}
/**
* 打印IOC中注入的所有組件
* @param applicationContext
*/
public void printBeans(AnnotationConfigApplicationContext applicationContext ){
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println(beanDefinitionName);
}
}
}
- 測試打印結(jié)果
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
colorMainConfig #自定義配置類bean
com.yuan.bean.Color #注入組件(bean)的全類名
2.3.2 ImportSelector:返回需要導(dǎo)入的組件的全類名數(shù)組;
- 自定義邏輯返回要導(dǎo)入的組件,需要實現(xiàn)ImportSelector接口,結(jié)合@Import注解一起使用
- 自定義MyImportSelector.java
package com.yuan.condition;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
/**
* @Author: Jinsheng·yuan
* @CreateDate: 2020/1/14 22:15
* @Description: 實現(xiàn)ImportSelector接口來自定義邏輯返回要導(dǎo)入的組件
*/
public class MyImportSelector implements ImportSelector {
/**
*
* @param importingClassMetadata 當(dāng)前標(biāo)注@Import注解的類的所有注解信息
* @return 返回值就是導(dǎo)入容器中的組件的全類名
*/
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
//可獲取標(biāo)注@Import注解類的所有注解信息
System.out.println("importingClassMetadata.getClassName():"+importingClassMetadata.getClassName());
System.out.println("importingClassMetadata.getAnnotations():"+importingClassMetadata.getAnnotations());
//return new String[0]; //這里不能返回null,可以返回一個空數(shù)組
return new String[]{"com.yuan.bean.Blue","com.yuan.bean.Yellow"};//導(dǎo)入容器中的組件的全類名
}
}
- 配置類
package com.yuan.config;
import com.yuan.bean.Color;
import com.yuan.condition.MyImportSelector;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* @Author: Jinsheng·yuan
* @CreateDate: 2020/1/14 21:59
* @Description: 使用@Import 注冊組件
*/
@Configuration
@Import({Color.class, MyImportSelector.class})
public class ColorMainConfig {
}
- IOCTest.java測試結(jié)果
mportingClassMetadata.getClassName():com.yuan.config.ColorMainConfig
importingClassMetadata.getAnnotations():org.springframework.core.annotation.TypeMappedAnnotations@36b4fe2a
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
colorMainConfig
com.yuan.bean.Color
com.yuan.bean.Blue
com.yuan.bean.Yellow
2.3.3 ImportBeanDefinitionRegistrar:手動注冊bean到容器中
通過實現(xiàn)ImportBeanDefinitionRegistrar接口,手動注冊bean到容器中,需要結(jié)合**@Import注解使用**文章來源地址http://www.zghlxwxcb.cn/news/detail-811121.html
- MyImportBeanDefinitionRegistrar.java
package com.yuan.condition;
import com.yuan.bean.Student;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
/**
* @Author: Jinsheng·yuan
* @CreateDate: 2020/1/14 22:48
* @Description: 通過實現(xiàn)ImportBeanDefinitionRegistrar接口,手動注冊bean到容器中
*/
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
/**
*
* @param importingClassMetadata 當(dāng)前類的注解信息
* @param registry BeanDefinition注冊類
* @param importBeanNameGenerator
*/
/* @Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) {
//此方法還未理解透
}*/
/**
*
* @param importingClassMetadata 當(dāng)前類的注解信息
* @param registry BeanDefinition注冊類,
* 把所有需要添加到容器中的Bean,用 registry.registerBeanDefinition()手工注冊進來
*
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//registry.registerBeanDefinition();
boolean red = registry.containsBeanDefinition("com.yuan.bean.Red");
boolean blue = registry.containsBeanDefinition("com.yuan.bean.Blue");
//如果存在Red與Blue類,則注冊自定義的student類
if(red && blue){
//指定bean的定義信息(就是Bean的類型)
RootBeanDefinition beanDefinition = new RootBeanDefinition(Student.class);
//自定義bean的名字為student
registry.registerBeanDefinition("student",beanDefinition);
}
}
}
- 配置類ColorMainConfig.java
package com.yuan.config;
import com.yuan.bean.Color;
import com.yuan.bean.Red;
import com.yuan.condition.MyImportBeanDefinitionRegistrar;
import com.yuan.condition.MyImportSelector;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import javax.swing.text.rtf.RTFEditorKit;
/**
* @Author: Jinsheng·yuan
* @CreateDate: 2020/1/14 21:59
* @Description: 使用@Import 注冊組件
*/
@Configuration
@Import({Color.class, Red.class,MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class ColorMainConfig {
}
- 測試結(jié)果
importingClassMetadata.getClassName():com.yuan.config.ColorMainConfig
importingClassMetadata.getAnnotations():org.springframework.core.annotation.TypeMappedAnnotations@574b560f
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
colorMainConfig
com.yuan.bean.Color
com.yuan.bean.Red
com.yuan.bean.Blue
com.yuan.bean.Yellow
student #手工注冊到容器的bean
3.使用Spring提供的 FactoryBean(工廠Bean);
3.1 默認獲取到的是工廠bean調(diào)用getObject創(chuàng)建的對象
3.2 要獲取工廠Bean本身,要獲取工廠Bean本身,我們需要給id前面加一個&,如:&colorFactoryBean
- 自定義ColorFactorBean.java,實現(xiàn)FactoryBean接口
package com.yuan.bean;
import org.springframework.beans.factory.FactoryBean;
/**
* @Author: Jinsheng·yuan
* @CreateDate: 2020/1/14 23:15
* @Description: 創(chuàng)建一個Spring定義的FactoryBean
*/
public class ColorFactorBean implements FactoryBean<Color> {
/**
* 是單例么?
* true:是,這個bean在容器中只會保留一份;
* false: 多實例,每次都會創(chuàng)建一個新的bean
* @return
*/
@Override
public boolean isSingleton() {
return false;
}
/**
*
* @return
* @throws Exception
*/
@Override
public Color getObject() throws Exception {
return new Color();
}
/**
* 返回一個Color對象,這個對象會創(chuàng)建到容器中
* @return
*/
@Override
public Class<?> getObjectType() {
return Color.class;
}
}
- 主配置類中注冊ColorFactorBean
package com.yuan.config;
import com.yuan.bean.Color;
import com.yuan.bean.ColorFactorBean;
import com.yuan.bean.Red;
import com.yuan.condition.MyImportBeanDefinitionRegistrar;
import com.yuan.condition.MyImportSelector;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import javax.swing.text.rtf.RTFEditorKit;
/**
* @Author: Jinsheng·yuan
* @CreateDate: 2020/1/14 21:59
* @Description: 使用@Import 注冊組件
*/
@Configuration
@Import({Color.class, Red.class,MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class ColorMainConfig {
/**
* 注入ColorFactorBean對象
* @return
*/
@Bean
public ColorFactorBean colorFactorBean(){
return new ColorFactorBean();
}
}
- 測試
package com.yuan.test;
import com.yuan.config.ColorMainConfig;
import com.yuan.config.MainConfig;
import com.yuan.config.MyConfigTwo;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* @Author: Jinsheng·yuan
* @CreateDate: 2020/1/14 21:59
* @Description: 使用@Import 注冊組件
*/
public class IOCTest {
private AnnotationConfigApplicationContext applicationContext;
/**
* 使用@Import注解向容器注入組件測試
*/
@Test
public void testImport(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ColorMainConfig.class);
Object colorFactorBean = applicationContext.getBean("colorFactorBean");
Object colorFactorBean1 = applicationContext.getBean("colorFactorBean");
System.out.println(colorFactorBean == colorFactorBean1); //是否為同意對象
//1. 獲取Bean的類型,默認獲取的的是工廠bean調(diào)用 getObject()對象創(chuàng)建的bean,如下獲取的為:com.yuan.bean.Color
System.out.println("colorFactorBean的類型:"+colorFactorBean.getClass());
//2. 若要獲取工廠bean本身,則需要給bean的id前面加一個 & ,如&colorFactorBean
Object factoryBean = applicationContext.getBean("&colorFactorBean");
System.out.println("colorFactorBean本身的類型:"+factoryBean.getClass());
printBeans(applicationContext);
}
/**
* 打印IOC中注入的所有組件
* @param applicationContext
*/
public void printBeans(AnnotationConfigApplicationContext applicationContext ){
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println(beanDefinitionName);
}
}
}
- 測試結(jié)果
importingClassMetadata.getClassName():com.yuan.config.ColorMainConfig
importingClassMetadata.getAnnotations():org.springframework.core.annotation.TypeMappedAnnotations@574b560f
false
colorFactorBean的類型:class com.yuan.bean.Color
colorFactorBean本身的類型:class com.yuan.bean.ColorFactorBean
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
colorMainConfig
com.yuan.bean.Color
com.yuan.bean.Red
com.yuan.bean.Blue
com.yuan.bean.Yellow
colorFactorBean
student
到了這里,關(guān)于Spring注解驅(qū)動開發(fā)之常用注解案例_告別在XML中配置Bean的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!