Spring單元測試控制Bean注入的方式
通過xml文件進(jìn)行注入
在配置文件中指定要注入的bean
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="dog" class="com.ttpfx.entity.Dog"> <property name="name" value="旺財"/> <property name="age" value="18"/> </bean> </beans>
然后spring加載這個xml文件就可以實現(xiàn)注入
public class SpringTest1 { public static void main(String[] args) { ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml"); Arrays.stream(ioc.getBeanDefinitionNames()).forEach(System.out::println); } }
輸出為
dog
通過xml加注解方式進(jìn)行注入
編寫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 https://www.springframework.org/schema/context/spring-context.xsd"> <!-- 掃描 com.ttpfx.entity.t2 包下的所有bean--> <context:component-scan base-package="com.ttpfx.entity.t2"/> </beans>
然后在要注入的bean上加入Component注解即可(如果里面方法上面有@Bean,那么也會進(jìn)行處理)
@Component public class Cat { }
public class SpringTest2 { public static void main(String[] args) { ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext2.xml"); Arrays.stream(ioc.getBeanDefinitionNames()).forEach(System.out::println); } }
輸出為
cat
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
通過注解進(jìn)行注入
可以不使用xml文件,通過@ComponentScan注解來完成定義掃描路徑的功能
@ComponentScan(basePackages = "com.ttpfx.entity.t3") public class SpringConfig3 { }
public class SpringTest3 { public static void main(String[] args) { ApplicationContext ioc = new AnnotationConfigApplicationContext(SpringConfig3.class); Arrays.stream(ioc.getBeanDefinitionNames()).forEach(System.out::println); } }
使用@ComponentScan也會將自身加入到容器中。我們可以在方法上加入@Bean來進(jìn)行注入,具體如下
@Component和@Configuration的區(qū)別
二者用法基本一樣,只不過@Configuration可以控制注入的Bean是不是一個代理對象,如果是代理對象,那么調(diào)用@Bean方法返回的都是同一個對象,否則就不是同一個對象。
在默認(rèn)情況下,@Configuration注入的對象是一個代理對象
默認(rèn)情況,proxyBeanMethods = true
@Configuration(proxyBeanMethods = true) public class Cat { @Bean public Cat bigCat() { return new Cat(); } }
得到這個對象,然后調(diào)用bigCat這個方法
public class SpringTest2 { public static void main(String[] args) { ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext2.xml"); Cat cat = ioc.getBean("cat", Cat.class); System.out.println(cat); Cat bigCat1 = cat.bigCat(); Cat bigCat2 = cat.bigCat(); System.out.println("---------------------"); System.out.println(bigCat1); System.out.println(bigCat2); System.out.println(bigCat1 == bigCat2); } }
這時返回Cat已經(jīng)是一個代理對象了,bigCat返回的都是同一個對象,就是單例模式的。
com.ttpfx.entity.t2.Cat$$EnhancerBySpringCGLIB$$bc3ad26b@4c1d9d4b
---------------------
com.ttpfx.entity.t2.Cat@7b227d8d
com.ttpfx.entity.t2.Cat@7b227d8d
true
如果將proxyBeanMethods 改成false,情況如下
@Configuration(proxyBeanMethods = false) public class Cat { @Bean public Cat bigCat() { return new Cat(); } }
其他代碼不變,可以發(fā)現(xiàn)沒有進(jìn)行代理。
com.ttpfx.entity.t2.Cat@62fdb4a6
---------------------
com.ttpfx.entity.t2.Cat@11e21d0e
com.ttpfx.entity.t2.Cat@1dd02175
false
如果使用@Component,那么就相當(dāng)于@Configuration的proxyBeanMethods 設(shè)置為false
使用FactoryBean
我們可以讓一個類實現(xiàn)FactoryBean,這個接口有一個getObject方法,如果一個使用@Bean標(biāo)記的方法返回FactoryBean,那么最終返回的是FactoryBean的getObject方法返回的值
public class PeopleFactory implements FactoryBean<People> { @Override public People getObject() throws Exception { return new People(); } @Override public Class<?> getObjectType() { return People.class; } @Override public boolean isSingleton() { return FactoryBean.super.isSingleton(); } }
@Component public class People { @Bean public PeopleFactory peopleFactory(){ return new PeopleFactory(); } }
此時獲取peopleFactory,它的類型如下,是一個People類型
com.ttpfx.entity.t3.People@587c290d
通過@Import導(dǎo)入
可以使用@Import進(jìn)行導(dǎo)入
@Import({User.class}) public class SpringConfig4 { }
public class SpringTest4 { public static void main(String[] args) { ApplicationContext ioc = new AnnotationConfigApplicationContext(SpringConfig4.class); Arrays.stream(ioc.getBeanDefinitionNames()).forEach(System.out::println); } }
輸出如下,可以發(fā)現(xiàn)使用@Import標(biāo)注的類也會被注入。使用@Import導(dǎo)入的類,名稱為全類名,如果重復(fù)導(dǎo)入,那么后面覆蓋前面。要指定名稱,那么就在對應(yīng)的bean上面使用@Component即可
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
springConfig4
com.ttpfx.entity.t4.User
手動注入(registerBean)
可以直接通過GenericApplicationContext這個類的registerBean方法進(jìn)行注入
public class SpringTest5 { public static void main(String[] args) { AnnotationConfigApplicationContext ioc = new AnnotationConfigApplicationContext(SpringConfig5.class); Arrays.stream(ioc.getBeanDefinitionNames()).forEach(System.out::println); System.out.println("-----------------------"); ioc.registerBean("monster01", Monster.class); Arrays.stream(ioc.getBeanDefinitionNames()).forEach(System.out::println); } }
輸出如下
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
springConfig5
-----------------------
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
springConfig5
monster01
通過ImportSelector進(jìn)行注入
定義一個類實現(xiàn)ImportSelector
public class MyImportSelector implements ImportSelector { @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { return new String[]{"com.ttpfx.entity.t6.Pig"}; } }
@Import({MyImportSelector.class}) public class SpringConfig6 { }
public class SpringTest6 { public static void main(String[] args) { ApplicationContext ioc = new AnnotationConfigApplicationContext(SpringConfig6.class); Arrays.stream(ioc.getBeanDefinitionNames()).forEach(System.out::println); } }
輸出如下,可以發(fā)現(xiàn)selectImports返回的String字符串中的內(nèi)容會進(jìn)行注入
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
springConfig6
com.ttpfx.entity.t6.Pig
通過ImportBeanDefinitionRegistrar進(jìn)行注入
通過ImportBeanDefinitionRegistrar可以進(jìn)行注入,只需要在registerBeanDefinitions方法中使用BeanDefinitionRegistry的registerBeanDefinition方法即可
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) { ImportBeanDefinitionRegistrar.super.registerBeanDefinitions(importingClassMetadata, registry, importBeanNameGenerator); } @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Manager.class).getBeanDefinition(); registry.registerBeanDefinition("manager", beanDefinition); ImportBeanDefinitionRegistrar.super.registerBeanDefinitions(importingClassMetadata, registry); } }
public class SpringTest7 { public static void main(String[] args) { ApplicationContext ioc = new AnnotationConfigApplicationContext(SpringConfig7.class); Arrays.stream(ioc.getBeanDefinitionNames()).forEach(System.out::println); Manager bean = ioc.getBean(Manager.class); System.out.println(bean); } }
代碼輸出如下
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
springConfig7
manager
com.ttpfx.entity.t7.Manager@1d8d30f7
通過BeanDefinitionRegistryPostProcessor進(jìn)行注入
實現(xiàn)這個接口,通過方法上面的參數(shù)可以進(jìn)行注入
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Employee.class).getBeanDefinition(); registry.registerBeanDefinition("employee", beanDefinition); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { } }
@Import({MyBeanDefinitionRegistryPostProcessor.class}) public class SpringConfig8 { }
public class SpringTest8 { public static void main(String[] args) { ApplicationContext ioc = new AnnotationConfigApplicationContext(SpringConfig8.class); Arrays.stream(ioc.getBeanDefinitionNames()).forEach(System.out::println); System.out.println("-----------------"); Employee bean = ioc.getBean(Employee.class); System.out.println(bean); } }
輸出如下,可以發(fā)現(xiàn)實現(xiàn)BeanDefinitionRegistryPostProcessor的這個類也被注入了
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
springConfig8
com.ttpfx.entity.t8.MyBeanDefinitionRegistryPostProcessor
employee
-----------------
com.ttpfx.entity.t8.Employee@58c1670b
到此這篇關(guān)于Spring注入bean的方式詳細(xì)講解的文章就介紹到這了,更多相關(guān)Spring注入bean內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
啟動Springboot項目時找不到Mapper的問題及解決
這篇文章主要介紹了啟動Springboot項目時找不到Mapper的問題及解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-11-11SpringMVC實現(xiàn)Controller的三種方式總結(jié)
這篇文章主要介紹了SpringMVC實現(xiàn)Controller的三種方式總結(jié),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-02-02Java開發(fā)深入分析講解二叉樹的遞歸和非遞歸遍歷方法
樹是一種重要的非線性數(shù)據(jù)結(jié)構(gòu),直觀地看,它是數(shù)據(jù)元素(在樹中稱為結(jié)點)按分支關(guān)系組織起來的結(jié)構(gòu),很象自然界中的樹那樣。樹結(jié)構(gòu)在客觀世界中廣泛存在,如人類社會的族譜和各種社會組織機構(gòu)都可用樹形象表示,本篇介紹二叉樹的遞歸與非遞歸遍歷的方法2022-05-05學(xué)習(xí)SpringMVC——國際化+上傳+下載詳解
本篇文章主要介紹了學(xué)習(xí)SpringMVC——國際化+上傳+下載,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。2016-12-12mybatis-plus的selectById(或者selectOne)在根據(jù)主鍵ID查詢實體對象的時候偶爾會出現(xiàn)nul
這篇文章主要介紹了mybatis-plus的selectById(或者selectOne)在根據(jù)主鍵ID查詢實體對象的時候偶爾會出現(xiàn)null的問題記錄,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09Java SSM實現(xiàn)前后端協(xié)議聯(lián)調(diào)詳解上篇
首先我們已經(jīng)知道,在現(xiàn)在流行的“前后端完全分離”架構(gòu)中,前后端聯(lián)調(diào)是一個不可能避免的問題,這篇文章主要介紹了Java SSM實現(xiàn)前后端協(xié)議聯(lián)調(diào)過程2022-08-08Java無需解壓直接讀取ZIP壓縮包里的文件及內(nèi)容
最近開發(fā)的時候遇到要獲取到zip壓縮包里面的文件內(nèi)容,解決方案就是通過ZipInputStream來讀取,下面通過實例代碼介紹Java無需解壓直接讀取ZIP壓縮包里的文件及內(nèi)容,感興趣的朋友跟隨小編一起看看吧2024-03-03