Spring?Bean的8種加載方式總結(jié)
前言
以前學(xué)習(xí)Spring框架的時(shí)候,總結(jié)了幾種Bean的加載方式,不過老師說還有其它的加載方式,以下八種并不是全部,但也足以用來做很多事情了。
注意以下是Spring中Bean的加載方式,不是SpringBoot,但其中的很多東西是相通的,尤其是Bean的注入方式、適用場景等,在本文中也有介紹的。
分享給大家一起學(xué)習(xí),如有錯(cuò)誤的地方,麻煩各位在評論區(qū)幫我指出。
1.xml+<bean>
被配置的bean需要有無參數(shù)的構(gòu)造函數(shù)
<?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"> <!-- xml方式聲明自己開發(fā)的bean --> <bean id="user" class="cn.sticki.blog.pojo.domain.User" /> <!-- xml方式聲明第三方bean --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"/> </beans>
2.xml:context+注解(@Component+4個(gè)@Bean)
使用組件掃描,指定加載bean的位置,spring會自動(dòng)掃描這個(gè)包下的文件。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" 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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd "> <!-- 組件掃描,指定加載bean的位置 --> <context:component-scan base-package="cn.sticki.bean,cn.sticki.config"/> </beans>
然后在需要被加載的類名上添加@Component注解。也可以使用@Controller、@Service、@Repository定義bean。
@Service publice class UserServiceImpl implements UserService { }
使用@Bean定義第三方bean,并將所在類定位為配置類或Bean
@Configuration // 或使用@Component public class DBConfig { @Bean public DruidDataSource dataSource(){ DruidDataSource ds = new DruidDataSource(); return ds; } }
3.配置類+掃描+注解(@Component+4個(gè)@Bean)
使用 AnnotationConfigApplicationContext(SpringConfig.class);
來獲取 ApplicationContext
public class AppObject { public static void main() { ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class); SpringConfig config = ctx.getBean("Config", SpringConfig.class); // 兩次獲取的是同一個(gè)對象 config.user(); config.user(); } }
和上面的第二種有點(diǎn)類似,就是包的掃描方式有所改變。
@ComponentScan({"cn.sticki.bean","cn.sticki.config"}) public class SpringConfig { @Bean public DogFactoryBean dog(){ return new DogFactoryBean(); } }
3.1FactoryBean接口
初始化實(shí)現(xiàn)FactoryBean接口的類,實(shí)現(xiàn)對bean加載到容器之前的批處理操作。
public class DogFactoryBean implements FactoryBean<Dog> { @Override public Dog getObject() throws Exception { return new Dog(); } @Override public Class<?> getObjectType() { return Dog.class; } }
在下面的bean中,顯示的表示為配置DogFactoryBean
,但實(shí)際上配置的是 Dog
。
@Component public class SpringConfig { @Bean public DogFactoryBean dog(){ return new DogFactoryBean(); } }
3.2@ImportResource注解
用于加載配置類并加載配置文件(系統(tǒng)遷移)
@Configuration @ComponentScan("cn.sticki.bean") @ImportResource("applicationContext.xml") public class SpringConfig { }
3.3proxyBeanMethods屬性
使用 proxyBeanMethods = true
可以保障調(diào)用此類中的方法得到的對象是從容器中獲取的,而不是重新創(chuàng)建的,但要求必須是通過此類調(diào)用方法獲得的bean。
@Configuration(proxyBeanMethods = true) public class SpringConfig { @Bean public User user() { System.out.println("user init..."); return new User(); } }
4.@Import導(dǎo)入bean的類
使用@Import注解導(dǎo)入要注入的bean對應(yīng)的字節(jié)碼
@Import(User.class) public class SpringConfig { }
而被導(dǎo)入的bean無需使用注解聲明為bean
public class User{ }
這種形式可以有效的降低源代碼與spring技術(shù)的耦合度(無侵入),在spring技術(shù)底層及諸多框架的整合中大量使用。
使用這種方法可以加在配置類,且也可以加在配置類當(dāng)中的bean。
5.AnnotationConfigApplicationContext調(diào)用register方法
在容器初始化完畢后使用容器對象手動(dòng)注入bean
public class App { public static void main() { ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class); ctx.register(User.class); // 打印容器中當(dāng)前的所有bean String[] names = ctx.getBeanDefinitionNames(); for (String name: names) { System.out.println(name); } } }
必須在容器初始化之后才能使用這種方法。如果重復(fù)加載同一個(gè)bean,后面加載的會覆蓋前面加載的。
6.@Import導(dǎo)入ImportSelector接口
導(dǎo)入實(shí)現(xiàn)了ImportSelector接口的類,實(shí)現(xiàn)對導(dǎo)入源的編程式處理
public class MyImportSelector implements ImportSelector { public String selectImports(AnnotationMetadata metadata) { // 使用metadata可以獲取到導(dǎo)入該類的元類的大量屬性,通過對這些屬性進(jìn)行判斷,可以達(dá)到動(dòng)態(tài)注入bean的效果 boolean flag = metadata.hasAnnotation("org.springframework.context.annotation.Import"); if(flag) { return new String[]{"cn.sticki.pojo.User"}; } return new String[]{"cn.sticki.pojo.Dog"}; } }
調(diào)用處:
@Import(MyImportSelector.class) public class SpringConfig { }
7.@Import導(dǎo)入ImportBeanDefinitionRegistrar接口
導(dǎo)入實(shí)現(xiàn)了ImportBeanDefinitionRegistrar接口的類,通過BeanDefinition的注冊器注冊實(shí)名bean,實(shí)現(xiàn)對容器中bean的綁定,例如對現(xiàn)有bean的覆蓋,進(jìn)而達(dá)成不修改源代碼的情況下更換實(shí)現(xiàn)的效果。
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { public String registrarBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { // 使用元數(shù)據(jù)去做判定,然后再決定要注入哪些bean BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(User.class).getBeanDefinition(); registry.registerBeanDefinition("user",beanDefinition); } }
調(diào)用處和上面第六種方式差不多。
8.@Import導(dǎo)入BeanDefinitionRegistryPostProcessor接口
導(dǎo)入實(shí)現(xiàn)了BeanDefinitionRegistryPostProcessor接口的類,通過BeanDefinition的注冊器注冊實(shí)名bean,實(shí)現(xiàn)對容器中bean的最終裁定。其在@Import中的加載順序?yàn)樽詈笠粋€(gè)加載,可以用來做bean覆蓋的最終裁定。
public class MyPostProcessor implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { // 注意這里注冊的是BookServiceImpl4 BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(BookServiceImpl4.class).getBeanDefinition(); registry.registerBeanDefinition("bookService",beanDefinition); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { } }
調(diào)用處:
// 按照先后順序加載,但 MyPostProcessor.class 最后才加載 @Import(BookServiceImpl1.class,MyPostProcessor.class, BookServiceImpl.class, MyImportSelector.class) public class SpringConfig { }
后記
這八種加載方式幾乎可以滿足我們所需要的全部場景了,但一般場景下,我們用的其實(shí)也就只有那兩三種,真正掌握這八種加載方式的朋友,肯定是大佬了。
到此這篇關(guān)于Spring Bean的8種加載方式總結(jié)的文章就介紹到這了,更多相關(guān)Spring Bean加載方式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot+Mybatis使用Enum枚舉類型總是報(bào)錯(cuò)No enum constant&n
這篇文章主要介紹了SpringBoot+Mybatis使用Enum枚舉類型總是報(bào)錯(cuò)No enum constant XX問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12解決Request.getParameter獲取不到特殊字符bug問題
這篇文章主要介紹了解決Request.getParameter獲取不到特殊字符bug問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07Hibernate Validator實(shí)現(xiàn)更簡潔的參數(shù)校驗(yàn)及一個(gè)util
這篇文章主要介紹了Hibernate Validator實(shí)現(xiàn)更簡潔的參數(shù)校驗(yàn)及一個(gè)util,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-05-05Mybatis配置之<properties>屬性配置元素解析
這篇文章主要介紹了Mybatis配置之<properties>屬性配置元素解析,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07Jmeter 中 CSV 如何參數(shù)化測試數(shù)據(jù)并實(shí)現(xiàn)自動(dòng)斷言示例詳解
這篇文章主要介紹了Jmeter 中 CSV 如何參數(shù)化測試數(shù)據(jù)并實(shí)現(xiàn)自動(dòng)斷言,本文通過示例給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07java實(shí)現(xiàn)順序結(jié)構(gòu)線性列表的函數(shù)代碼
java實(shí)現(xiàn)順序結(jié)構(gòu)線性列表的函數(shù)代碼。需要的朋友可以過來參考下,希望對大家有所幫助2013-10-10使用apache 的FileUtils處理文件的復(fù)制等操作方式
這篇文章主要介紹了使用apache 的FileUtils處理文件的復(fù)制等操作方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07