SpringBoot加載bean的八種方式總結(jié)
第一種bean的加載方式-配置文件
先創(chuàng)建一個使用maven的spring工程
導(dǎo)入spring核心配置
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.3.9</version> </dependency>
創(chuàng)建一個類
public class Cat { }
public class Dog { }
創(chuàng)建一個名為applicationContext.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" xsi:schemaLocation= "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="cat" class="com.service.Cat"/> <bean id="dog" class="com.service.Dog"/> </beans>
創(chuàng)建一個啟動類
package com.app; import com.service.Dog; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class App1 { public static void main(String[] args) { ApplicationContext app=new ClassPathXmlApplicationContext("applicationContext.xml"); Object cat = app.getBean("cat");//根據(jù)id獲取 System.out.println(cat); Object dog = app.getBean(Dog.class);//根據(jù)類獲取,當(dāng)不唯一時會報錯 System.out.println(dog); } }
運行結(jié)果,這樣就可以得到bean的對象了
或者使用可以使用一次性獲取所有bean
public class App1 { public static void main(String[] args) { ApplicationContext app=new ClassPathXmlApplicationContext("applicationContext.xml"); String[] names = app.getBeanDefinitionNames(); for (String name : names) { System.out.println(name); } } }
運行結(jié)果
第二種加載bean方式-注解和掃描
使用注解,注解的作用就是替代配置文件的配置,注解有@Component @Service @Repository等
替換配置文件中的<bean id= class=..>
@Component("cat") //起的名 public class Cat { }
@Component public class Dog { }
使用完注解還得讓spring去掃描到這個注解,在配置文件中的寫
<?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 "> <!--告訴spring掃描哪個包component導(dǎo)入context命名空間--> <context:component-scan base-package="com"/> </beans>
運行結(jié)果
創(chuàng)建第三方的bean對象
先導(dǎo)入對應(yīng)的坐標(biāo)
<dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.24</version> </dependency>
創(chuàng)建一個類,返回你需要導(dǎo)入的對象即可,加入注解
package com.config; import com.alibaba.druid.pool.DruidDataSource; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Component; @Component public class DBconfig { @Bean public DruidDataSource dataSource(){ DruidDataSource ds =new DruidDataSource(); return ds; } }
運行結(jié)果
第三種加載bean方式-不使用配置文件
創(chuàng)建一個類代替配置文件
package com.config; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @Configuration//定義為配置類 @ComponentScan({"com.config","com.service"}) //注解掃描包 public class springConfig { }
運行類也得修改
package com.app; import com.config.springConfig; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class App2 { public static void main(String[] args) { ApplicationContext app=new AnnotationConfigApplicationContext(springConfig.class); String[] names = app.getBeanDefinitionNames(); for (String name : names) { System.out.println(name); } } }
運行結(jié)果
擴(kuò)展-bean的加載方式擴(kuò)展FactoryBean<>
初始化實現(xiàn)FactoryBean<>接口的類,實現(xiàn)對bean加載到容器之前的批處理操作。
實現(xiàn)了FactoryBean接口創(chuàng)建出來的對象不是本身而是里面的泛型。
創(chuàng)建一個類實現(xiàn)接口
package com.config; import com.service.Dog; import org.springframework.beans.factory.FactoryBean; import org.springframework.context.annotation.Bean; public class DogFactoryBean implements FactoryBean<Dog> { public Dog getObject() throws Exception { return new Dog(); } //返回對象的類型 public Class<?> getObjectType() { //這里可以做一系列的初始化工作 return Dog.class; } //是否是單例,單例則多次獲取都是一個對象 public boolean isSingleton() { return false; } }
@Component public class Dog { }
啟動的主類
import com.config.springConfig; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class App2 { public static void main(String[] args) { ApplicationContext app=new AnnotationConfigApplicationContext(springConfig.class); String[] names = app.getBeanDefinitionNames(); for (String name : names) { System.out.println(name); } System.out.println(app.getBean("dog1")); System.out.println(app.getBean("dog1")); } }
運行結(jié)果
產(chǎn)生的是泛型的對象
擴(kuò)展-@ImportResource導(dǎo)入配置文件
看源碼可知道,可以寫入多個string類型的數(shù)組,使用{}
@ImportResource({"applicationContext2.xml","applicationContext.xml"})
@Configuration @ComponentScan("com") @ImportResource({"applicationContext2.xml","applicationContext.xml"}) public class SpringConfig2 { @Bean public Cat cat(){ return new Cat(); } }
兩個配置文件中的bean,排在前面的首先加載,后面的之后加載,同的內(nèi)容以之后的為主,不同的內(nèi)容都加載。
擴(kuò)展-proxyBeanMethods屬性-產(chǎn)生代理對象
@Configuration注解中有一屬性proxyBeanMethod屬性,默認(rèn)值是true
值為false時
@Configuration(proxyBeanMethods = false) @ComponentScan("com") @ImportResource({"applicationContext2.xml","applicationContext.xml"}) public class SpringConfig2 { @Bean public Cat cat(){ return new Cat(); } }
主方法中
public class app3 { public static void main(String[] args) { ApplicationContext app=new AnnotationConfigApplicationContext(SpringConfig2.class); String[] names = app.getBeanDefinitionNames(); for (String name : names) { System.out.println(name); } System.out.println("--------"); System.out.println(app.getBean("springConfig2")); SpringConfig2 springConfig2 = app.getBean("springConfig2", SpringConfig2.class); System.out.println(springConfig2.cat()); System.out.println(springConfig2.cat()); System.out.println(springConfig2.cat()); } }
運行結(jié)果
產(chǎn)生的是普通對象,每一次調(diào)用方法都會new一個新的對象前提是這個方法是被bean管理的對象。
值為true時
不寫或?qū)憈rue時
@Configuration(proxyBeanMethods = true) @ComponentScan("com") @ImportResource({"applicationContext2.xml","applicationContext.xml"}) public class SpringConfig2 { @Bean public Cat cat(){ return new Cat(); } }
運行結(jié)果
會產(chǎn)生一個代理對象,這個代理對象讓我們每次調(diào)用方法是都是同一個,前提也是需要被bean容器管理
注:產(chǎn)生的bean對象沒指定名稱時,默認(rèn)是方法名或類名首字母小寫,如類名是SpringTest則產(chǎn)生的bean是springTest
第四種加載bean方式-使用@Import
翻看@Import源碼可知,需要一個類class字節(jié)碼對象
在類中
import com.service.TestBean1; import com.service.TestBean2; import org.springframework.context.annotation.Import; @Import({TestBean1.class, TestBean2.class}) public class springConfig4 { }
創(chuàng)建測試的類
public class TestBean1 { }
public class testBean2 { }
主類上
public class app4 { public static void main(String[] args) { ApplicationContext app=new AnnotationConfigApplicationContext(springConfig4.class); String[] names = app.getBeanDefinitionNames(); for (String name : names) { System.out.println(name); } } }
運行結(jié)果
全路徑名,加入的類即使沒有被spring管理也可以產(chǎn)生bean。
第五種加載bean方式-registerBean
使用上下文對象在容器初始化后注入bean
在創(chuàng)建完上下文對象的時候可以加載bean
只能使用 AnnotationConfigApplicationContext獲取上下文對象
public class app5 { public static void main(String[] args) { AnnotationConfigApplicationContext app=new AnnotationConfigApplicationContext(springConfig5.class); //加載完成后 app.registerBean("CaiDog", Dog.class,1 ); app.registerBean("CaiDog", Dog.class,2); app.registerBean("CaiDog", Dog.class,3 ); String[] names = app.getBeanDefinitionNames(); for (String name : names) { System.out.println(name); } System.out.println("------"); System.out.println(app.getBean(Dog.class)); } }
Dog類下
@Component public class Dog { int age; public Dog(){} public Dog(int age){ this.age=age; } @Override public String toString() { return "Dog{" + "age=" + age + '}'; } }
運行結(jié)果 ,當(dāng)有多個的時候,且bean的名字一致時,以最后的為準(zhǔn)。
或者直接使用
app.register(Cat.class);
也可以快速的加載一個bean
第六種加載bean方式-實現(xiàn)ImportSelector接口
這個接口有許多方法用來判定
導(dǎo)入實現(xiàn)了ImportSelector接口的類,實現(xiàn)對導(dǎo)入源的編程式處理
public class MyImportSelector implements ImportSelector { public String[] selectImports(AnnotationMetadata annotationMetadata) {//AnnotationMetadata 注解的源數(shù)據(jù) // 做判定條件,是否有這個注解 boolean flag = annotationMetadata.hasAnnotation("org.springframework.context.annotation.Configuration"); if (flag){ return new String[]{"com.service.Dog"}; } return new String[]{"com.service.Cat"}; } }
@Import({MyImportSelector.class}) public class SpringConfig6 { }
public class app6 { public static void main(String[] args) { ApplicationContext app=new AnnotationConfigApplicationContext(SpringConfig6.class); String[] names = app.getBeanDefinitionNames(); for (String name : names) { System.out.println(name); } } }
運行結(jié)果
第七種加載bean方式-實現(xiàn)ImportBeanDefinitionRegistrar
導(dǎo)入實現(xiàn)ImportBeanDefinitionRegistrar接口的類,通過BeanDefinition的注冊器注冊實名bean,實現(xiàn)對容器中bean的決定,例如對現(xiàn)有的bean的覆蓋,進(jìn)而達(dá)到
import com.service.Dog; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.core.type.AnnotationMetadata; public class MyRegistrar implements ImportBeanDefinitionRegistrar { public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { BeanDefinition beanDefinition= BeanDefinitionBuilder.rootBeanDefinition(Dog.class).getBeanDefinition(); registry.registerBeanDefinition("woDog", beanDefinition); } }
@Import({MyRegistrar.class}) public class SpringConfig7 { }
運行結(jié)果
第八種bean的加載方式-實現(xiàn)BeanDefinitionRegistryPostProcessor
導(dǎo)入實現(xiàn)了BeanDefinitionRegistryPostProcessor接口的類,通過BeanDefintion的注冊器注冊實名bean,實現(xiàn)對容器中bean的最終裁定.(以這個接口加載的bean為主)
@Component public class DBconfig { @Bean public DruidDataSource dataSource(){ DruidDataSource ds =new DruidDataSource(); return ds; } }
public class MyPostProcessor implements BeanDefinitionRegistryPostProcessor { public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(DBconfig.class).getBeanDefinition(); registry.registerBeanDefinition("dataSource",beanDefinition); } public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { } }
@Import({MyPostProcessor.class}) public class SpringConfig8 { }
運行結(jié)果
實現(xiàn)bean的方式總結(jié)
1.xml+<bean/>
2.xml:context+注解(@Component+4個@Bean
3.配置類+掃描+注解(@Component+4個@Bean)
@Bean定義FactoryBean接口@ImportResource@Configuration注解的proxyBeanMethods屬性
4.@Import導(dǎo)入bean的類
@Import導(dǎo)入配置類
5.AnnotationConfigApplicationContext調(diào)用register方法
6.@Import導(dǎo)入ImportSelector接口
7.@Import導(dǎo)入ImportBeanDefinitionRegistrar接口
8.@Import導(dǎo)入BeanDefinitionRegistryPostProcessor接口
到此這篇關(guān)于SpringBoot加載bean的八種方式的文章就介紹到這了,更多相關(guān)SpringBoot加載bean內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring Boot熱加載jar實現(xiàn)動態(tài)插件的思路
本文主要介紹在 Spring Boot 工程中熱加載 jar 包并注冊成為 Bean 對象的一種實現(xiàn)思路,在動態(tài)擴(kuò)展功能的同時支持在插件中注入主程序的 Bean 實現(xiàn)功能更強(qiáng)大的插件2021-10-10SpringBoot Controller返回圖片的三種方式
在互聯(lián)網(wǎng)的世界里,圖片無處不在,它們是信息傳遞的重要媒介,也是視覺盛宴的一部分,而在Spring Boot項目中,如何優(yōu)雅地處理和返回圖片數(shù)據(jù),則成為了開發(fā)者們不得不面對的問題,今天,就讓我們一起來探索Spring Boot Controller的神奇轉(zhuǎn)換,需要的朋友可以參考下2024-07-07jbuilder2006連接sqlserver2000的方法
xp jbuiler2006 連接SQL SERVER2000的問題2008-10-10Spring context:component-scan的使用及說明
這篇文章主要介紹了Spring context:component-scan的使用及說明,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-09-09