日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

spring系列-注解驱动原理及源码-bean组件注册

發布時間:2025/3/19 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 spring系列-注解驱动原理及源码-bean组件注册 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

一、環境初始化

1、環境準備

二、bean的手動注入

1、xml方式注入bean

2、使用@Configuration&@Bean方式注入bean

三、自動掃描注冊組件及bean

1、使用xml方式掃描包

2、使用@ComponentScan掃描

3、包掃描的排除

四、組件注冊用到的其他注解

1、使用@Scope-設置組件作用域

2、@Lazy-bean懶加載

3、@Conditional-按照條件注冊bean

五、使用@Import給容器中快速導入一個組件

1、@Import導入組件

2、使用ImportSelector來導入bean

3、使用ImportBeanDefinitionRegistrar來導入bean

六、使用FactoryBean創建bean

1、使用FactoryBean創建bean

七、bean組件注冊小結


友情提示:此系列文檔不適宜springboot零基礎的同學~

一、環境初始化

1、環境準備

(1)新建maven項目。

(2)pom導入spring-bean有關的包,以及junit測試

<!--引入spring-bean有關的包--> <dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>4.3.12.RELEASE</version> </dependency> <!--junit測試--> <dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope> </dependency>

(3)環境包如下

?

二、bean的手動注入

1、xml方式注入bean

(1)定義Person類

package com.xiang.spring.bean;public class Person {private String name;private Integer age;……get set toString…… }

(2)在resources目錄下創建beans.xml配置文件

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!--使用xml配置bean--><bean id="person" class="com.xiang.spring.bean.Person"><property name="age" value="18"></property><property name="name" value="lisi"></property></bean> </beans>

(3)創建main方法來獲取ioc中的bean

package com.xiang.spring;import com.xiang.spring.bean.Person; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;public class MainTest {public static void main(String[] args) {// 使用xml配置文件獲取容器中的beanApplicationContext applicationContextXml = new ClassPathXmlApplicationContext("beans.xml");Person xmlPerson = (Person) applicationContextXml.getBean("person");System.out.println(xmlPerson);} }

2、使用@Configuration&@Bean方式注入bean

(1)定義Person類

同上

(2)創建配置類

package com.xiang.spring.config;import com.xiang.spring.bean.Person; import org.springframework.context.annotation.Bean;// 告訴spring這是一個配置類 @Configuration public class MainConfig {/*** 給容器中注冊一個bean,類型為返回值的類型,默認是用方法名作為id名稱* 使用@Bean("person") 可以給bean指定名稱,而不用方法名*///@Bean@Bean("person")public Person person01() {return new Person("zhangsan", 20);}}

(3)創建main方法來獲取ioc中的bean

package com.xiang.spring;import com.xiang.spring.bean.Person; import com.xiang.spring.config.MainConfig; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;public class MainTest {public static void main(String[] args) {// 使用xml配置文件獲取容器中的beanApplicationContext applicationContextXml = new ClassPathXmlApplicationContext("beans.xml");Person xmlPerson = (Person) applicationContextXml.getBean("person");System.out.println(xmlPerson);System.out.println("------------------------");// 創建IOC容器,加載配置類,獲取到容器中的PersonApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);// 多種方式獲取容器中的beanPerson bean = applicationContext.getBean(Person.class);Person bean2 = applicationContext.getBean("person", Person.class);System.out.println(bean);System.out.println(bean2);// 獲取指定class類型的bean的名字(默認為bean的方法名)String[] beanNamesForType = applicationContext.getBeanNamesForType(Person.class);for (String s : beanNamesForType) {System.out.println(s);}} }// 運行結果 Person{name='lisi', age=18} ------------------------ Person{name='zhangsan', age=20} Person{name='zhangsan', age=20} person

三、自動掃描注冊組件及bean

1、使用xml方式掃描包

(1)在beans.xml添加以下內容

<!--包掃描,只要標注了@Controller、@Service、@Repository、@Component的bean都會創建到容器中--> <!--use-default-filters禁用默認規則,才可以繼續設置掃描過濾規則--> <context:component-scan base-package="com.xiang.spring" use-default-filters="false"></context:component-scan>

2、使用@ComponentScan掃描

(1)定義Controller、Service、Dao類

package com.xiang.spring.controller; import org.springframework.stereotype.Controller; @Controller public class BookController { }package com.xiang.spring.service; import org.springframework.stereotype.Service; @Service public class BookService { }package com.xiang.spring.dao; import org.springframework.stereotype.Repository; @Repository public class BookDao { }

(2)設置配置類

package com.xiang.spring.config;import com.xiang.spring.bean.Person; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; import org.springframework.stereotype.Controller; import org.springframework.stereotype.Service;// 告訴spring這是一個配置類 @Configuration @ComponentScan(value = "com.xiang.spring") public class MainConfig {/*** 給容器中注冊一個bean,類型為返回值的類型,默認是用方法名作為id名稱* 使用@Bean("person") 可以給bean指定名稱,而不用方法名*///@Bean@Bean("person")public Person person01() {return new Person("zhangsan", 20);} }

(3)寫測試類獲取ioc容器中所有注冊的bean

package com.xiang.spring.test;import com.xiang.spring.config.MainConfig; import org.junit.Test; import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class IOCTest {@Testpublic void test01(){// 獲取IOC容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);// 獲取容器中的所有bean名稱String[] definitionNames = applicationContext.getBeanDefinitionNames();for (String definitionName : definitionNames) {System.out.println(definitionName);}} }// 運行結果 org.springframework.context.annotation.internalConfigurationAnnotationProcessor org.springframework.context.annotation.internalAutowiredAnnotationProcessor org.springframework.context.annotation.internalRequiredAnnotationProcessor org.springframework.context.annotation.internalCommonAnnotationProcessor org.springframework.context.event.internalEventListenerProcessor org.springframework.context.event.internalEventListenerFactory mainConfig bookController bookDao bookService person

3、包掃描的排除

(1)excludeFilters排除需要掃描的組件

修改配置類

package com.xiang.spring.config;import com.xiang.spring.bean.Person; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; import org.springframework.stereotype.Controller; import org.springframework.stereotype.Service;// 告訴spring這是一個配置類 @Configuration /** * 包掃描,只要標注了@Controller、@Service、@Repository、@Component的bean都會創建到容器中 * @ComponentScan :value:指定要掃描的包; * excludeFilters = Filter[]: 指定掃描的時候按照什么規則排除哪些組件 * includeFilters = Filter[]: 指定掃描的時候只需要包含哪些組件,還需要加useDefaultFilters = false * jdk8以上可以寫多個@ComponentScan,非jdk8以上也可以用@ComponentScans = {@ComponentScan},用來指定多個掃描的包 */ @ComponentScan(value = "com.xiang.spring", excludeFilters = {@Filter(type = FilterType.ANNOTATION, classes = {Controller.class, Service.class}) // 根據注解排除,排除Controller、Service }) public class MainConfig {/*** 給容器中注冊一個bean,類型為返回值的類型,默認是用方法名作為id名稱* 使用@Bean("person") 可以給bean指定名稱,而不用方法名*///@Bean@Bean("person")public Person person01() {return new Person("zhangsan", 20);} }// 運行結果 org.springframework.context.annotation.internalConfigurationAnnotationProcessor org.springframework.context.annotation.internalAutowiredAnnotationProcessor org.springframework.context.annotation.internalRequiredAnnotationProcessor org.springframework.context.annotation.internalCommonAnnotationProcessor org.springframework.context.event.internalEventListenerProcessor org.springframework.context.event.internalEventListenerFactory mainConfig bookDao person

(2)includeFilters只需要包含哪些組件

修改配置類

package com.xiang.spring.config;import com.xiang.spring.bean.Person; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; import org.springframework.stereotype.Controller; import org.springframework.stereotype.Service;// 告訴spring這是一個配置類 @Configuration /** * 包掃描,只要標注了@Controller、@Service、@Repository、@Component的bean都會創建到容器中 * @ComponentScan :value:指定要掃描的包; * excludeFilters = Filter[]: 指定掃描的時候按照什么規則排除哪些組件 * includeFilters = Filter[]: 指定掃描的時候只需要包含哪些組件,還需要加useDefaultFilters = false * jdk8以上可以寫多個@ComponentScan,非jdk8以上也可以用@ComponentScans = {@ComponentScan},用來指定多個掃描的包 */ @ComponentScan(value = "com.xiang.spring", includeFilters = {@Filter(type = FilterType.ANNOTATION, classes = {Controller.class, Service.class}) // 需要包含哪些組件:Controller、Service }, useDefaultFilters = false) public class MainConfig {/*** 給容器中注冊一個bean,類型為返回值的類型,默認是用方法名作為id名稱* 使用@Bean("person") 可以給bean指定名稱,而不用方法名*///@Bean@Bean("person")public Person person01() {return new Person("zhangsan", 20);} }// 運行結果 org.springframework.context.annotation.internalConfigurationAnnotationProcessor org.springframework.context.annotation.internalAutowiredAnnotationProcessor org.springframework.context.annotation.internalRequiredAnnotationProcessor org.springframework.context.annotation.internalCommonAnnotationProcessor org.springframework.context.event.internalEventListenerProcessor org.springframework.context.event.internalEventListenerFactory mainConfig bookController bookService person

(3)包掃描排除的枚舉類型詳解

public enum FilterType {ANNOTATION, // 注解類型ASSIGNABLE_TYPE, // 按照指定的類型ASPECTJ, // 按照Aspectj的表達式,基本不會用到REGEX, // 按照正則表達式CUSTOM; // 自定義規則private FilterType() {} }

(4)按照指定的類型排除

在配置類中配置:

@Filter(type = FilterType.ASSIGNABLE_TYPE, classes = BookService.class) // 排除規則,只有BookService會排除

(5)自定義排除規則

①?寫過濾規則類

package com.xiang.spring.config;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;import java.io.IOException;/** * 自定義包掃描排除規則類 */ public class MyTypeFilter implements TypeFilter {/*** MetadataReader :讀取到的當前正在掃描的類的信息* MetadataReaderFactory:可以獲取到其他任何類的信息*/public 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);if(className.contains("er")){return true;}// 返回true為匹配成功;返回false為匹配結束return false;} }

②?配置類中設置自定義過濾規則

// 告訴spring這是一個配置類 @Configuration @ComponentScan(value = "com.xiang.spring", includeFilters = {@Filter(type = FilterType.CUSTOM, classes = MyTypeFilter.class) // 自定義過濾規則 }, useDefaultFilters = false) public class MainConfig {

③?執行test類查看結果

package com.xiang.spring.test;import com.xiang.spring.config.MainConfig; import org.junit.Test; import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class IOCTest {@Testpublic void test01(){// 獲取IOC容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);// 獲取容器中的所有bean名稱String[] definitionNames = applicationContext.getBeanDefinitionNames();for (String definitionName : definitionNames) {System.out.println(definitionName);}} }// 打印結果 ----->com.xiang.spring.test.IOCTest ----->com.xiang.spring.bean.Person ----->com.xiang.spring.config.MyTypeFilter ----->com.xiang.spring.controller.BookController ----->com.xiang.spring.dao.BookDao ----->com.xiang.spring.MainTest ----->com.xiang.spring.service.BookService org.springframework.context.annotation.internalConfigurationAnnotationProcessor org.springframework.context.annotation.internalAutowiredAnnotationProcessor org.springframework.context.annotation.internalRequiredAnnotationProcessor org.springframework.context.annotation.internalCommonAnnotationProcessor org.springframework.context.event.internalEventListenerProcessor org.springframework.context.event.internalEventListenerFactory mainConfig person myTypeFilter bookController bookService

四、組件注冊用到的其他注解

1、使用@Scope-設置組件作用域

(1)定義配置類

package com.xiang.spring.config;import com.xiang.spring.bean.Person; import org.springframework.context.annotation.*; import org.springframework.context.annotation.ComponentScan.Filter;@Configuration public class MainConfig2 {/*** 默認是單例的,配置方式有四種(取自@Scope的value的注釋)* @see ConfigurableBeanFactory#SCOPE_PROTOTYPE* @see ConfigurableBeanFactory#SCOPE_SINGLETON* @see org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST* @see org.springframework.web.context.WebApplicationContext#SCOPE_SESSION** 解析:* prototype:多實例的:ioc容器啟動不會調用方法創建對象,每次獲取的時候才會調用方法創建對象,每次獲取都會調用方法獲取對象。* singleton:單實例的(默認值):ioc容器啟動,會調用方法創建對象放到ioc容器中,以后每次取就是直接從容器中拿。* request:同一次請求創建一個實例(web環境可用,但也不常用)* session:同一個session創建一個實例(web環境可用,但也不常用)*/@Scope("prototype")@Bean("person2")public Person person() {System.out.println("給容器中添加Person……");return new Person("zhangsan", 22);} }

(2)編寫測試方法

@Test public void test02(){// 獲取IOC容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);// 默認是單實例Object obj1 = applicationContext.getBean("person2");Object obj2 = applicationContext.getBean("person2");System.out.println(obj1 == obj2); }// 運行結果 給容器中添加Person…… 給容器中添加Person…… false

2、@Lazy-bean懶加載

(1)在bean加上@Lazy注解

/** * 單實例bean:默認在容器啟動的時候創建對象。 * 懶加載:容器啟動不創建對象,第一次使用(獲取)bean時才創建對象,并初始化。 * */ @Lazy @Bean("person2") public Person person() {System.out.println("給容器中添加Person……");return new Person("zhangsan", 22); }

(2)編寫測試方法

@Test public void test02(){// 獲取IOC容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);// 默認是單實例System.out.println("--------------");Object obj1 = applicationContext.getBean("person2"); }// 輸出結果 -------------- 給容器中添加Person……

3、@Conditional-按照條件注冊bean

(1)編寫兩個Condition

package com.xiang.spring.condition; 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系統 public class WindowsCondition implements Condition {public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {// 能獲取到環境信息Environment environment = context.getEnvironment();// 獲取操作系統String osName = environment.getProperty("os.name");if(osName.contains("Windows")){return true;}return false;} }package com.xiang.spring.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系統 public class LinuxCondition implements Condition {/*** ConditionContext:判斷條件能使用的上下文環境* AnnotatedTypeMetadata:當前標記了@Conditional的注釋信息*/public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {// 能獲取到ioc使用的beanFactory工廠ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();// 能獲取到類加載器ClassLoader classLoader = context.getClassLoader();// 能獲取到環境信息Environment environment = context.getEnvironment();// 獲取到bean定義的注冊類BeanDefinitionRegistry registry = context.getRegistry();// 可以判斷容器中是否包含bean的定義,也可以給容器中注冊beanregistry.containsBeanDefinition("person");// 獲取操作系統String osName = environment.getProperty("os.name");if(osName.contains("linux")){return true;}return false;} }

(2)配置類中添加bean

/** * @Conditional({}):按照一定的條件進行判斷,滿足條件給容器中注冊bean * 既可以放在方法上,也可以放在類上進行統一設置 */ @Conditional({LinuxCondition.class}) @Bean public Person linux() {return new Person("linux", 60); } @Conditional({WindowsCondition.class}) @Bean public Person windows() {return new Person("windows", 50); }

(3)測試方法測試一下

@Test public void test03(){// 獲取IOC容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);ConfigurableEnvironment environment = applicationContext.getEnvironment();System.out.println("當前運行環境" + environment.getProperty("os.name"));Map<String, Person> beansOfType = applicationContext.getBeansOfType(Person.class);System.out.println(beansOfType); }// 運行結果 當前運行環境Windows 10 {windows=Person{name='windows', age=50}}

五、使用@Import給容器中快速導入一個組件

1、@Import導入組件

(1)新增類

public class Color { }public class Red { }

(2)在配置類上添加注解

@Configuration // 導入組件,id默認是組件的全類名 @Import({Color.class, Red.class}) public class MainConfig2 {

(3)測試方法測試一下

@Test public void test04(){// 獲取IOC容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);String[] definitionNames = applicationContext.getBeanDefinitionNames();for (String name : definitionNames) {System.out.println(name);} }// 運行結果 org.springframework.context.annotation.internalConfigurationAnnotationProcessor org.springframework.context.annotation.internalAutowiredAnnotationProcessor org.springframework.context.annotation.internalRequiredAnnotationProcessor org.springframework.context.annotation.internalCommonAnnotationProcessor org.springframework.context.event.internalEventListenerProcessor org.springframework.context.event.internalEventListenerFactory mainConfig2 com.xiang.spring.bean.Color com.xiang.spring.bean.Red

2、使用ImportSelector來導入bean

(1)定義bean類

public class Blue { }public class Yellow { }

(2)編寫selector

package com.xiang.spring.condition;import org.springframework.context.annotation.ImportSelector; import org.springframework.core.type.AnnotationMetadata;/** * 自定義返回邏輯需要導入的組件 */ public class MyImportSelector implements ImportSelector {/*** 返回值就是導入到容器中的組件全類名* AnnotationMetadata:當前標注@Import的類的所有注解信息*/public String[] selectImports(AnnotationMetadata importingClassMetadata) {// 方法不要返回null值return new String[]{"com.xiang.spring.bean.Blue", "com.xiang.spring.bean.Yellow"};} }

(3)配置類添加

@Configuration // 導入組件,id默認是組件的全類名 @Import({Color.class, Red.class, MyImportSelector.class}) public class MainConfig2 {

(4)運行一下看結果

@Test public void test04(){// 獲取IOC容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);String[] definitionNames = applicationContext.getBeanDefinitionNames();for (String name : definitionNames) {System.out.println(name);} }//執行結果 org.springframework.context.annotation.internalConfigurationAnnotationProcessor org.springframework.context.annotation.internalAutowiredAnnotationProcessor org.springframework.context.annotation.internalRequiredAnnotationProcessor org.springframework.context.annotation.internalCommonAnnotationProcessor org.springframework.context.event.internalEventListenerProcessor org.springframework.context.event.internalEventListenerFactory mainConfig2 com.xiang.spring.bean.Color com.xiang.spring.bean.Red com.xiang.spring.bean.Blue com.xiang.spring.bean.Yellow

3、使用ImportBeanDefinitionRegistrar來導入bean

(1)編寫bean類

public class RainBow { }

(2)注冊類

package com.xiang.spring.condition;import com.xiang.spring.bean.RainBow; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.core.type.AnnotationMetadata;public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {/*** AnnotationMetadata:當前類注解信息* BeanDefinitionRegistry:BeanDefinition注冊類* 把所有需要添加到容器中的bean,調用BeanDefinitionRegistry.registerBeanDefinition手工注冊*/public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {boolean red = registry.containsBeanDefinition("com.xiang.spring.bean.Red");boolean blue = registry.containsBeanDefinition("com.xiang.spring.bean.Blue");if(red && blue) {// 指定bean的定義信息RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(RainBow.class);// 指定bean名,注冊一個beanregistry.registerBeanDefinition("rainBow", rootBeanDefinition);}} }

(3)配置類

@Configuration @Import({Color.class, Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class}) public class MainConfig2 {

(4)編寫測試方法看結果

@Test public void test04(){// 獲取IOC容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);String[] definitionNames = applicationContext.getBeanDefinitionNames();for (String name : definitionNames) {System.out.println(name);} }// 運行結果 org.springframework.context.annotation.internalConfigurationAnnotationProcessor org.springframework.context.annotation.internalAutowiredAnnotationProcessor org.springframework.context.annotation.internalRequiredAnnotationProcessor org.springframework.context.annotation.internalCommonAnnotationProcessor org.springframework.context.event.internalEventListenerProcessor org.springframework.context.event.internalEventListenerFactory mainConfig2 com.xiang.spring.bean.Color com.xiang.spring.bean.Red com.xiang.spring.bean.Blue com.xiang.spring.bean.Yellow rainBow

六、使用FactoryBean創建bean

1、使用FactoryBean創建bean

(1)定義FactoryBean

package com.xiang.spring.bean;import org.springframework.beans.factory.FactoryBean;/** * 創建一個spring定義的工廠bean */ public class ColorFactoryBean implements FactoryBean<Color> {/*** 返回一個Color對象,這個對象會添加到容器中* 假如說不是單例,每次獲取bean都會調用getObject方法*/public Color getObject() throws Exception {return new Color();}public Class<?> getObjectType() {return Color.class;}/*** 控制是否是單例的* true:單例,在容器中保存一份* false:不是單例,每次獲取都會創建新實例*/public boolean isSingleton() {return false;} }

(2)配置類添加FactoryBean

@Bean public ColorFactoryBean colorFactoryBean() {return new ColorFactoryBean(); }

(3)測試類查看輸出結果

@Test public void test04(){// 獲取IOC容器AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);String[] definitionNames = applicationContext.getBeanDefinitionNames();for (String name : definitionNames) {System.out.println(name);}// 默認獲取到的是工廠bean調用getObject創建的對象Object colorFactoryBean = applicationContext.getBean("colorFactoryBean");System.out.println("colorFactoryBean的類型:" + colorFactoryBean.getClass());// 要獲取工廠bean本身,我們需要給id前面加一個&符號:&colorFactoryBeanObject colorFactoryBean2 = applicationContext.getBean("&colorFactoryBean");System.out.println("colorFactoryBean2的類型:" + colorFactoryBean2.getClass()); }// 輸出結果 org.springframework.context.annotation.internalConfigurationAnnotationProcessor org.springframework.context.annotation.internalAutowiredAnnotationProcessor org.springframework.context.annotation.internalRequiredAnnotationProcessor org.springframework.context.annotation.internalCommonAnnotationProcessor org.springframework.context.event.internalEventListenerProcessor org.springframework.context.event.internalEventListenerFactory mainConfig2 colorFactoryBean colorFactoryBean的類型:class com.xiang.spring.bean.Color colorFactoryBean2的類型:class com.xiang.spring.bean.ColorFactoryBean

七、bean組件注冊小結

給容器中注冊組件

(1)、包掃描+組件標注注解(@Controller/@Service/@Repository/@Component)

(2)、@Bean[導入第三方包里面的組件]

(3)、@Import[快速給容器中導入一個組件]

?????① @Import(要導入到容器中的組件);容器中就會自動注冊這個組件,id默認是全類名。

?????② ImportSelector:返回需要導入的組件的全類名數組

?????③ ImportBeanDefinitionRegistrar:手動注冊bean到容器中

(4)、使用Spring提供的FactoryBean(工廠Bean)

?????① 默認獲取到的是工廠bean調用getObject創建的對象

?????② 要獲取工廠bean本身,我們需要給id前面加一個&符號:&colorFactoryBean

總結

以上是生活随笔為你收集整理的spring系列-注解驱动原理及源码-bean组件注册的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。