當前位置:
首頁 >
前端技术
> javascript
>内容正文
javascript
Spring注解驱动之注册组件(spring的再回顾)
生活随笔
收集整理的這篇文章主要介紹了
Spring注解驱动之注册组件(spring的再回顾)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
一. 組件注冊
1. 給容器中注冊組件
xml方式
-
創建一個實體類(構造方法等省略)
public class Person {private String name;private Integer age;} -
resources資源目錄下創建xml文件
- 利用bean標簽注冊一個組件
- 得到id,方便從容器中獲取該bean
- 使用property進行屬性賦值
-
創建一個測試類
- 傳入配置文件的位置,返回IOC容器
- 根據id獲取值
-
控制臺輸出
Person{name='諸葛亮', age=18}
配置類方式
-
實體類不變
-
創建一個配置類
// 配置類==配置文件 @Configuration // 告訴Spring這是一個配置類 public class MainConfig {// 給容器注冊一個Bean,類型為返回值的類型,id默認是方法名(可以直接指定value方法值)@Beanpublic Person person() {return new Person("劉備",19);}} -
測試類(入口代碼省略)
@Testpublic void t2() {// new一個AnnotationConfigApplicationContext,傳入配置文件,得到IOC容器ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);// 根據類型獲取值Person bean = applicationContext.getBean(Person.class);System.out.println("根據類型獲取"+bean);// 根據Id獲取,默認Id就是方法名String[] namesForType = applicationContext.getBeanNamesForType(Person.class);for (String name : namesForType) {System.out.println("獲取該組件的id是"+name);}} -
控制臺
根據類型獲取Person{name='劉備', age=19} 獲取該組件的id是person
2. 自動掃描組件與指定掃描規則
xml文件掃描時
-
在配置文件中配置
- 只要指定包下的標注了Controller,Service,Repository,Component就會被掃描到
配置文件包掃描
-
在配置類上加上注解@ComponentScan
// 配置類==配置文件 @ComponentScan(value = "com.lcy") // 包掃描 @Configuration // 告訴Spring這是一個配置類 public class MainConfig {@Beanpublic Person person() {return new Person("劉備",19);} } -
測試
- 獲取當前IOC中所有組件的名字
-
控制臺
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 personController personDao personService person -
excludeFilters(排除)
-
排除Controller和Service標注的組件
-
控制臺
- 與上次輸出比較,過濾規則起作用了
-
includeFilters(只包含)
-
恰恰相反,需要禁用掉默認過濾規則才能生效
- useDefaultFilters = false
-
只要Controller和Service標注的組件
-
控制臺
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 personController personService person
-
掃描規則
@ComponentScan(value = "com.lcy",includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class, Service.class}),@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = PersonDao.class)},useDefaultFilters = false) // @ComponentScan value:指定要掃描的包 // includeFilters = Filter[]:指定掃描時只需要包含哪些組件 // excludeFilters = Filter[]:指定掃描時按照規則排除組件 // FilterType.ANNOTATION:按照注解(常用) // FilterType.ASSIGNABLE_TYPE:按照類型(常用)所有的其子類實現類都會被加載進來 // FilterType.ASPECTJ:按照ASPECTJ表達式 // FilterType.REGEX:按照正ava則 // FilterType.CUSTOM:按照自定義規則(需要TypeFilter的實現類)-
自定義過濾規則
-
創建一個類實現TypeFilter接口
public class MyTypeFilter implements TypeFilter {/**** @param metadataReader 讀取到的當前正在掃描類的信息* @param metadataReaderFactory 可以讀取到其他任何類的信息* @return* @throws IOException*/@Overridepublic boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {// 獲取當前類注解的信息AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();// 獲取當前正在掃描類的類信息(比如實現了什么接口,什么類型)ClassMetadata classMetadata = metadataReader.getClassMetadata();// 獲取當前類資源(類的路徑)Resource resource = metadataReader.getResource();// 獲取當前正在處理類的類名String className = classMetadata.getClassName();System.out.println("----->類名"+className);// 如果類名中包含Dao,則返回true,匹配成功放行if (className.contains("Dao")) {return true;}return false;}} -
配置類進行設置
@Configuration @ComponentScan(value = "com.lcy",includeFilters = {@ComponentScan.Filter(type = FilterType.CUSTOM,classes = MyTypeFilter.class)}, // 自定義規則useDefaultFilters = false) public class MainConfig {@Beanpublic Person person() {javareturn new Person("劉備",19);} } -
控制臺
----->類名com.lcy.bean.Person ----->類名com.lcy.config.MyTypeFilter ----->類名com.lcy.controller.PersonController ----->類名com.lcy.dao.PersonDao ----->類名com.lcy.service.PersonService 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 personDao personProcess finished with exit code 0
-
3. @Scope設置作用域
默認單例
-
配置類
@Configuration public class MainConfig2 {// 默認為單例/*** prototype:多實例的* singleton:單實例的(默認值)ioc容器每次調用方法創建對象放到ioc容器中* 之后的每一次獲取都是直接從容器中拿* request: 同一次請求創建一個實例(需要web環境)* session: 同一個Session創建一個實例(需要web環境)*/@Scope@Beanpublic Person person() {System.out.println("給容器添加Person");return new Person("周瑜",20);}} -
測試類
@Test public void t4() {ApplicationContext ioc = new AnnotationConfigApplicationContext(MainConfig2.class);// 根據Id來獲取Person bean1 = (Person) ioc.getBean("person");Person bean2 = (Person) ioc.getBean("person");// 默認單例,判斷兩個對象是否相等System.out.println(bean1 == bean2); // true} -
控制臺
給容器添加Person IOC容器創建完成 true
多例
-
配置類
@Configuration public class MainConfig2 {@Bean/*** prototype:多實例的:ioc啟動并不會創建對象放在容器* 每次獲取時才會調用方法創建對象*/@Scope("prototype")public Person person() {System.out.println("給容器添加Person");return new Person("周瑜",20);} } -
測試類
@Testpublic void t4() {ApplicationContext ioc = new AnnotationConfigApplicationContext(MainConfig2.class);System.out.println("IOC容器創建完成");// 根據Id來獲取Person bean1 = (Person) ioc.getBean("person");Person bean2 = (Person) ioc.getBean("person");// 修改為prototype,判斷兩個對象是否相等System.out.println(bean1 == bean2); // false} -
控制臺
IOC容器創建完成 給容器添加Person 給容器添加Person false
懶加載
-
配置類(未啟動懶加載)
@Configuration public class MainConfig2 {// 默認為單例@Bean/*** singleton:單實例的(默認值)ioc容器每次調用方法創建對象放到 ioc容器中* 懶加載:* 單實例Bean:默認在容器啟動時創建對象* 懶加載:容器啟動時不創建對象,第一次(使用)獲取Bean創建 對象并初始化**/@Scopepublic Person person() {System.out.println("給容器添加Person");return new Person("周瑜",20);} } -
測試類
@Testpublic void t4() {ApplicationContext ioc = new AnnotationConfigApplicationContext(MainConfig2.class);System.out.println("IOC容器創建完成");} -
控制臺
- 在IOC啟動的時候就創建完成了
-
啟用懶加載@Lazy
-
配置類
@Configuration public class MainConfig2 {@Bean@Scope@Lazypublic Person person() {System.out.println("給容器添加Person");return new Person("周瑜",20);} } -
測試類與控制臺(未使用Bean)
@Testpublic void t4() {ApplicationContext ioc = new AnnotationConfigApplicationContext(MainConfig2.class);System.out.println("IOC容器創建完成");} IOC容器創建完成 -
測試類與控制臺(使用Bean)
- 使用Bean時才會創建,并且只會創建一次
-
4. @Conditional按照條件注冊bean
-
若放在類上,必須滿足條件,此類中的bean注冊才能生效
-
條件:
- 如果是windows,給容器中注冊windows
- 如果是Linux,給容器中注冊Linux
-
配置類
/*** @return* @Conditional({}) :按照一定條件進行判斷,滿足條件給容器中注冊 bean*/ @Conditional({WindowsCondition.class}) // 放在類上,必須滿足條件,此類中的bean注冊才能生效 @Bean("Windows") public Person person1() {return new Person("Windows", 22); }@Bean("Linux") @Conditional({LinuxCondition.class}) public Person person2() {return new Person("Linux", 20); } -
分別創建兩個類實現Condition接口
// 判斷是否為Linux系統 public class LinuxCondition implements Condition {@Overridepublic boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {Environment environment = conditionContext.getEnvironment();String property = environment.getProperty("os.name");if (property.contains("Linux")) {return true;}return false;}java } // 判斷是否為Windows系統 public class WindowsCondition implements Condition {/**** @param conditionContext 判斷條件能使用的上下文環境* @param annotatedTypeMetadata 注釋信息* @return*/@Overridepublic boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {// 1.能獲取到IOC使用的beanfactoryConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();// 2.獲取類加載器ClassLoader classLoader = conditionContext.getClassLoader();// 3.獲取當前環境信息Environment environment = conditionContext.getEnvironment();// 4.獲取到bean定義的注冊類BeanDefinitionRegistry registry = conditionContext.getRegistry();// 可以判斷容器中的bean注冊情況,也可以給容器中注冊beanboolean person = registry.containsBeanDefinition("person");// 獲取操作系統String property = environment.getProperty("os.name");// 判斷是否為Windows系統if (property.contains("Windows")){return true;}return false;} } -
測試類
@Test public void t5() {ApplicationContext ioc = new AnnotationConfigApplicationContext(MainConfig2.class);String[] beanNamesForType = ioc.getBeanNamesForType(Person.class);for (String name : beanNamesForType) {System.out.println(name);}Map<String, Person> personMap = ioc.getBeansOfType(Person.class);System.out.println(personMap);} -
控制臺
- 因為是Windows操作系統,所以Linux并沒有注冊進來
- person是之前已注冊的
5. @Import導入組件
@Import
-
創建一個實體類
public class Color {} -
配置類加入類名@Import
@Configuration @Import(Color.class) //@Import({Color.class, Person.class}) 也可以導多個類 public class MainConfig3 {/*** 給容器中注冊組件:* 1.包掃描+組件標注注解(@Controller,@Service,@Repository,@Component)[局限于自己創建的類]* 2.@Bean[導入的第三方包里面的組件]* 3.@Import[快速給容器中導入一個組件]* 1.@Improt(要導入容器的組件),容器會自動注冊這個組件,id默認是全類名*/} -
測試類
@Test public void t6() {ApplicationContext ioc = new AnnotationConfigApplicationContext(MainConfig3.class);String[] names = ioc.getBeanDefinitionNames();for (String name : names) {System.out.println(name);}} -
控制臺
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 mainConfig3 com.lcy.bean.Color
ImportSelector接口
-
創建一個類實現ImportSelector接口
// 自定義邏輯返回需要導入的組件 public class MyImportSelector implements ImportSelector {/*** 返回值就是要導入到容器中的組件全類名* @param annotationMetadata :當前標注@Import注解類的所有注解信息* @return*/@Overridepublic String[] selectImports(AnnotationMetadata annotationMetadata) {// 放入需要注冊組件的全類名return new String[]{"com.lcy.bean.Red","com.lcy.bean.Blue"};} } -
配置類
@Configuration @Import({Color.class, MyImportSelector.class}) public class MainConfig3 {/*** ImportSelector:返回需要導入的組件的全類名數組* 創建一個類實現ImportSelector接口,在@Import上導入*/} -
測試(代碼如上不變)控制臺
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 mainConfig3 com.lcy.bean.Color com.lcy.bean.Red com.lcy.bean.Blue
ImportBeanDefinitionRegistrar接口
-
創建新的實體類
public class RainBow { } -
配置類
@Configuration @Import({Color.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class}) public class MainConfig3 {/*** ImportBeanDefinitionRegistrar:手動注冊bean到容器*/} -
創建一個類實現ImportBeanDefinitionRegistrar接口
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {/**** @param importingClassMetadata:當前類的注解信息* @param registry : 把所有需要添加到容器中的bean,* 調用registry.registerBeanDefinition手工注冊進來*/@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {// 指定bean的定義信息(Bean的類型)RootBeanDefinition beanDefinition = new RootBeanDefinition(RainBow.class);// 注冊一個bean,指定bean名registry.registerBeanDefinition("rainBow",beanDefinition);} } -
測試類(代碼不變)與控制臺
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 mainConfig3 com.lcy.bean.Color com.lcy.bean.Red com.lcy.bean.Blue rainBow
FactoryBean工廠Bean
-
配置類
/*** .使用Spring提供的FactoryBean(工廠Bean)* 1.默認獲取到的是工廠Bean調用getObject創建的對象* 2.要獲取工廠Bean本身,則在id前加一個&*/ @Bean // 雖然注冊的是YellowFactoryBean,但實際上是Yellow public YellowFactoryBean yellowFactoryBean() {return new YellowFactoryBean(); } -
創建一個實體類
public class Yellow { } -
創建一個類實現FactoryBean接口
public class YellowFactoryBean implements FactoryBean<Yellow> {// 返回一個Yellow對象,這個對象會添加到容器中@Overridepublic Yellow getObject() throws Exception {System.out.println("YellowFactoryBean。。。。。getObject");return new Yellow();}// 返回對象的類型@Overridepublic Class<?> getObjectType() {return Yellow.class;}// 控制是否單例:true為單例; 在容器中保存一份// false:多例;每次獲取都會創建一個新的bean,獲取的時候會調用getObject@Overridepublic boolean isSingleton() {return true;} } -
測試類
@Test public void t6() {ApplicationContext ioc = new AnnotationConfigApplicationContext(MainConfig3.class);// 工廠Bean獲取的是調用gerObject創建的對象Object bean = ioc.getBean("yellowFactoryBean");System.out.println("bean的類型="+bean.getClass());// 若想獲取工廠Bean的本身則加&Object bean1 = ioc.getBean("&yellowFactoryBean");System.out.println("bean的類型="+bean1);} -
控制臺
YellowFactoryBean。。。。。getObject bean的類型=class com.lcy.bean.Yellow bean的類型=com.lcy.condition.YellowFactoryBean@1f0f1111
總結
以上是生活随笔為你收集整理的Spring注解驱动之注册组件(spring的再回顾)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: layui table 复选框跳页后再回
- 下一篇: SpringBoot消息转换器:Http