最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring中的ImportBeanDefinitionRegistrar接口詳解

 更新時(shí)間:2023年09月20日 08:45:00   作者:信仰_273993243  
這篇文章主要介紹了Spring中的ImportBeanDefinitionRegistrar接口詳解,ImportBeanDefinitionRegistrar接口是也是spring的擴(kuò)展點(diǎn)之一,它可以支持我們自己寫的代碼封裝成BeanDefinition對象,注冊到Spring容器中,功能類似于注解@Service @Component,需要的朋友可以參考下

接口功能介紹

描述:ImportBeanDefinitionRegistrar接口是也是spring的擴(kuò)展點(diǎn)之一,它可以支持我們自己寫的代碼封裝成BeanDefinition對象,注冊到Spring容器中,功能類似于注解@Service @Component。

很多三方框架集成Spring的時(shí)候,都會(huì)通過該接口,實(shí)現(xiàn)掃描指定的類,然后注冊到spring容器中,比如Mybatis中的Mapper接口,springCloud中的FeignClient接口,都是通過該接口實(shí)現(xiàn)的自定義注冊邏輯。

1、ImportBeanDefinitionRegistrar接口實(shí)現(xiàn)類,只能通過@Import注解的方式來注入,通常把@Import修飾在啟動(dòng)類或配置類。

2、使用@Import,如果括號中的類是ImportBeanDefinitionRegistrar的實(shí)現(xiàn)類,啟動(dòng)時(shí)會(huì)觸發(fā)ImportBeanDefinitionRegistrar接口的方法,將其中要注冊的類注冊成bean。

3、實(shí)現(xiàn)該接口的類擁有注冊bean的能力。

//接口所有抽象方法,合并看就一個(gè)注冊BeanDefinition的方法
public interface ImportBeanDefinitionRegistrar {
	//把自定義的類封裝成BeanDefinition對象,注冊到Spring里面去
	default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) {
		registerBeanDefinitions(importingClassMetadata, registry);
	}
	//我們平時(shí)重寫這個(gè)就可以了
	default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
	}
}

使用案例

1、案例1

自定義業(yè)務(wù)類UserServiceTest,通過ImportBeanDefinitionRegistrar將注冊Spring容器中。在通過spring容器獲取Bean=UserServiceTest

//業(yè)務(wù)類
public class UserServiceTest {
	/**
	 * 獲取用戶名稱
	 * @return 用戶名稱
	 */
	public String getUserName(){
		return "測試";
	}
}

ImportBeanDefinitionRegistrar實(shí)現(xiàn)類

//注意這里不能加注解,要通過Import導(dǎo)入進(jìn)去。
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
	//業(yè)務(wù)類轉(zhuǎn)成bd,注冊到spring容器中注入
	@Override
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		//1、通過Bd工具類生成bd對象,只是這個(gè)Db對象比較純潔沒有綁定任何類
		BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition();
		GenericBeanDefinition beanDefinition = (GenericBeanDefinition) beanDefinitionBuilder.getBeanDefinition();
		//2、設(shè)置bd綁定的類型
		beanDefinition.setBeanClass(UserServiceTest.class);
		//3、注冊到spring容器中
		registry.registerBeanDefinition("userServiceTest",beanDefinition);
	}
}
@Configuration
@Import(MyImportBeanDefinitionRegistrar.class)
public class AppConfigClassTest {
	//在配置類導(dǎo)入ImportBeanDefinitionRegistrar實(shí)現(xiàn)類
}
//測試
public static void main(String[] args) {
	AnnotationConfigApplicationContext AnnotationConfigApplicationContext =
			new AnnotationConfigApplicationContext(AppConfigClassTest.class);
	UserServiceTest userServiceTest = AnnotationConfigApplicationContext.getBean("userServiceTest", UserServiceTest.class);
	String userName = userServiceTest.getUserName();
	System.out.println(userName);
}

如果只是把業(yè)務(wù)類注冊到Spring容器中我們通過其他注解就可以了,那么ImportBeanDefinitionRegistrar有沒有更高級的玩法。

2、案例2

public interface UserServiceTestInterface {
	public void list();
}
//因?yàn)槭墙涌?,但是spring的容器里面是不允許注入接口的,只能是接口的實(shí)現(xiàn)類。如果我們寫個(gè)去實(shí)現(xiàn)接口,那就沒有什么意義了,沒必要搞得那么復(fù)雜,這次我們通過代理類來完成對接口的實(shí)現(xiàn)。
public class MyInvocationHandler implements InvocationHandler {
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.println("代理類邏輯代碼");
		return null;
	}
}
//注意這里不能加注解,要通過Import導(dǎo)入進(jìn)去。
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
	 @Override
	 public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        //通過工具類生成一個(gè)bd,只是這個(gè)Db對象比較純潔沒有綁定任何類
		BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition();
		GenericBeanDefinition beanDefinition = (GenericBeanDefinition) beanDefinitionBuilder.getBeanDefinition();
		//設(shè)置Bean的類型MyInvocationHandler,類型是實(shí)現(xiàn)類的類型,不是接口類型。因?yàn)樵趯?shí)例化的時(shí)候,調(diào)用的是設(shè)置類型所以對應(yīng)的構(gòu)造方法。
		beanDefinition.setBeanClass(MyInvocationHandler.class);
		//注冊到Spring容器中進(jìn)去
		registry.registerBeanDefinition("userServiceTest",beanDefinition);
    }
}
//通過配置類,導(dǎo)入ImportBeanDefinitionRegistrar的實(shí)現(xiàn)類
@Configuration
@Import(MyImportBeanDefinitionRegistrar.class)
public class AppConfigClassTest {
}

測試

public static void main(String[] args) {
	AnnotationConfigApplicationContext AnnotationConfigApplicationContext = new AnnotationConfigApplicationContext(AppConfigClassTest.class);
	//通過name獲取Bean,注意此時(shí)的bean類型不是UserServiceTestInterface類型,而是MyInvocationHandler
	Object userServiceTestInterface = AnnotationConfigApplicationContext.getBean("userServiceTest");
	if(userServiceTestInterface instanceof MyInvocationHandler){
		//代碼實(shí)際會(huì)走到這里,把object轉(zhuǎn)成帶代理類。
		MyInvocationHandler u = (MyInvocationHandler) userServiceTestInterface;
		//生成接口UserServiceTestInterface的代理對象
		UserServiceTestInterface o = (UserServiceTestInterface) Proxy.newProxyInstance(MainTest.class.getClassLoader(), new Class[]{UserServiceTestInterface.class}, u);
	}
}

3、案例3

定義一個(gè)業(yè)務(wù)接口,通過FactoryBean+InvocationHandler來生成該接口的代理類,無需手動(dòng)寫業(yè)務(wù)接口的實(shí)現(xiàn)類,很多底層框架就是這樣實(shí)現(xiàn)的。

  • InvocationHandler:主要是通過Invoke方法來攔截業(yè)務(wù)接口的方法
  • FactoryBean:主要是用來將生成的代理類。
  • ImportBeanDefinitionRegistrar:在這里的作用就是幫忙我們把自定義的FactoryBean注冊到Spring中
//業(yè)務(wù)接口
public interface UserServiceTestInterface {
	public void list();
}

自定義FactoryBean這樣我們控制Bean的創(chuàng)建的過程,實(shí)現(xiàn)InvocationHandler用來攔截業(yè)務(wù)接口的方法。

//創(chuàng)建代理類,代理UserServiceTestInterface接口,UserServiceTestInterface接口方法在執(zhí)行前后都會(huì)被invoke方法攔截
//FactoryBean可以生成某一個(gè)類型Bean實(shí)例,它最大的一個(gè)作用是:可以讓我們自定義Bean的創(chuàng)建過程
public class MyFactoryBean implements FactoryBean, InvocationHandler {
	//為了使這個(gè)類更好地?cái)U(kuò)展。創(chuàng)建更多的接口,我們定義一個(gè)參數(shù),讓他們通過參數(shù)傳遞進(jìn)來。
	private Class classs;
	//添加一個(gè)有參的構(gòu)造方法。
	public MyFactoryBean(Class classs){
		this.classs = classs;
	}
	//攔截Class的所有方法
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.println("diaoyonlejiekou123");
		return null;
	}
	//返回bean的對象。spring會(huì)自動(dòng)把它add到容器里面去。
	@Override
	public Object getObject() throws Exception {
		Class[] clazzs = new Class[]{classs};//目標(biāo)類集合。
		//通過proxy來得到代理對象。本來最有一個(gè)參數(shù)需要穿代理類對象,但因?yàn)楸绢悓?shí)現(xiàn)了InvocationHandler,所以只需傳this
		Object proxy = Proxy.newProxyInstance(this.getClass().getClassLoader(), clazzs, this);
		return proxy;//返回的這個(gè)對象,會(huì)把加到spring的容器中。
	}
	//返回要添加到容器里bean的類型
	@Override
	public Class<?> getObjectType() {
		return this.classs;
	}
}

自定義ImportBeanDefinitionRegistrar實(shí)現(xiàn)類,把我們自定義的FactoryBean注冊到Spring中。

//注意這里不能加注解,要通過Import導(dǎo)入進(jìn)去。
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
	@Override
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		//通過工具類生成一個(gè)bd,只是這個(gè)Db對象比較純潔沒有綁定任何類
		BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition();
		//為什么要轉(zhuǎn)成GenericBeanDefinition這種類型。因?yàn)镚enericBeanDefinition有更多修改bd屬性的方法。后面我會(huì)介紹為什么要修改屬性。
		GenericBeanDefinition beanDefinition = (GenericBeanDefinition) beanDefinitionBuilder.getBeanDefinition();
		//這里很重要。getConstructorArgumentValues是為了獲取該bd的所有構(gòu)造方法,因?yàn)槲覀冎貙懥擞袇?gòu)造方法,所有我們需要帶參數(shù)過去 
		//不然spring沒法幫我們實(shí)例化,addGenericArgumentValue是添加參數(shù),該代碼會(huì)執(zhí)行兩步
		//第一步是匹配對應(yīng)的構(gòu)造方法,第二步是實(shí)例化。
		beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(UserServiceTestInterface.class.getName());
		//因?yàn)榇韺ο箢愋偷?,?shí)例化的時(shí)候走的是代理類的構(gòu)造方法
		beanDefinition.setBeanClass(MyFactoryBean.class);
		//注冊bd
		registry.registerBeanDefinition("userServiceTest",beanDefinition);
	}
}

測試

public static void main(String[] args) {
	AnnotationConfigApplicationContext AnnotationConfigApplicationContext = new AnnotationConfigApplicationContext(AppConfigClassTest.class);
	//通過name獲取Bean
	Object userServiceTestInterface = AnnotationConfigApplicationContext.getBean("userServiceTest");
	//針對這種場景Bean的類型是,通過FactoryBean的getObjectType方法返回的。
	UserServiceTestInterface u = (UserServiceTestInterface) userServiceTestInterface;
	u.list();
}

?到此這篇關(guān)于Spring中的ImportBeanDefinitionRegistrar接口詳解的文章就介紹到這了,更多相關(guān)ImportBeanDefinitionRegistrar接口內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 淺談HashMap中7種遍歷方式的性能分析

    淺談HashMap中7種遍歷方式的性能分析

    本文先從HashMap的遍歷方法講起,然后再從性能、原理以及安全性等方面,來分析HashMap各種遍歷方式的優(yōu)勢與不足
    2021-06-06
  • Linux服務(wù)器如何部署java項(xiàng)目

    Linux服務(wù)器如何部署java項(xiàng)目

    這篇文章主要介紹了Linux服務(wù)器如何部署java項(xiàng)目問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • JAVA遍歷一個(gè)文件夾中的所有文件的小例子

    JAVA遍歷一個(gè)文件夾中的所有文件的小例子

    在實(shí)際項(xiàng)目中給定一文件夾,得到這個(gè)文件夾下所有的文件這樣的需求并不是很多,更多的是查找或是刪除某一具體的文件
    2013-10-10
  • springboot使用mybatis開啟事務(wù)回滾

    springboot使用mybatis開啟事務(wù)回滾

    本文主要介紹了springboot使用mybatis開啟事務(wù)回滾,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • SpringBoot?MongoCustomConversions自定義轉(zhuǎn)換方式

    SpringBoot?MongoCustomConversions自定義轉(zhuǎn)換方式

    這篇文章主要介紹了SpringBoot?MongoCustomConversions自定義轉(zhuǎn)換方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • java編程題之順時(shí)針打印矩陣

    java編程題之順時(shí)針打印矩陣

    這篇文章主要為大家詳細(xì)介紹了java編程題之順時(shí)針打印矩陣,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-03-03
  • pagehelper踩坑記之分頁亂套問題解決

    pagehelper踩坑記之分頁亂套問題解決

    這篇文章主要為大家介紹了pagehelper踩坑記之分頁亂套問題解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • Java結(jié)構(gòu)型模式之代理模式詳解

    Java結(jié)構(gòu)型模式之代理模式詳解

    這篇文章主要介紹了Java結(jié)構(gòu)型模式之代理模式,代理模式是常用的java設(shè)計(jì)模式,他的特征是代理類與委托類有同樣的接口,代理類主要負(fù)責(zé)為委托類預(yù)處理消息、過濾消息、把消息轉(zhuǎn)發(fā)給委托類,以及事后處理消息等
    2023-02-02
  • 一文詳解springboot中的熱啟動(dòng)配置方案

    一文詳解springboot中的熱啟動(dòng)配置方案

    SpringBoot的熱啟動(dòng)主要通過 **`spring-boot-devtools`** 模塊實(shí)現(xiàn),能在代碼修改后自動(dòng)重啟應(yīng)用,大幅提升開發(fā)效率,下面小編就來和大家講講詳細(xì)配置和使用指南
    2025-07-07
  • Java之Springcloud Gateway內(nèi)置路由案例講解

    Java之Springcloud Gateway內(nèi)置路由案例講解

    這篇文章主要介紹了Java之Springcloud Gateway內(nèi)置路由案例講解,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08

最新評論

阳原县| 玛多县| 沂源县| 文安县| 潜江市| 遂昌县| 潮安县| 金寨县| 汽车| 沙河市| 新源县| 舞阳县| 托克逊县| 体育| 贡山| 林口县| 博客| 垣曲县| 洞头县| 佳木斯市| 和政县| 黔南| 琼中| 天镇县| 永清县| 甘泉县| 滨海县| 介休市| 青河县| 突泉县| 天峨县| 麟游县| 科技| 汉阴县| 桃园县| 山西省| 定陶县| 莫力| 宁明县| 汉沽区| 广州市|