Spring單元測試控制Bean注入的方式
通過xml文件進行注入
在配置文件中指定要注入的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加注解方式進行注入
編寫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,那么也會進行處理)
@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
通過注解進行注入
可以不使用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來進行注入,具體如下
@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)沒有進行代理。
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進行導(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方法進行注入
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進行注入
定義一個類實現(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)容會進行注入
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進行注入
通過ImportBeanDefinitionRegistrar可以進行注入,只需要在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進行注入
實現(xiàn)這個接口,通過方法上面的參數(shù)可以進行注入
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-11
SpringMVC實現(xiàn)Controller的三種方式總結(jié)
這篇文章主要介紹了SpringMVC實現(xiàn)Controller的三種方式總結(jié),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-02-02
Java開發(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-12
mybatis-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-09
Java 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-08
Java無需解壓直接讀取ZIP壓縮包里的文件及內(nèi)容
最近開發(fā)的時候遇到要獲取到zip壓縮包里面的文件內(nèi)容,解決方案就是通過ZipInputStream來讀取,下面通過實例代碼介紹Java無需解壓直接讀取ZIP壓縮包里的文件及內(nèi)容,感興趣的朋友跟隨小編一起看看吧2024-03-03

