SpringBoot bean的多種加載方式示例詳解
一、xml配置文件
配置文件spring-bean.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"> <!--xml方式聲明自己開發(fā)的bean--> <bean id="person" class="com.xc.entity.Person"/> <bean class="com.xc.entity.Person"/> <bean class="com.xc.entity.Person"/> <!--xml方式聲明第三方開發(fā)的bean--> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"/> </beans>
加載xml
public class App { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-bean.xml"); for (String beanDefinitionName : context.getBeanDefinitionNames()) { System.out.println(beanDefinitionName); } } }
輸出結(jié)果:
person
com.xc.entity.Person#0
com.xc.entity.Person#1
dataSource
二、注解定義bean
1、使用AnnotationConfigApplicationContext對象加載
public class App { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class); for (String beanDefinitionName : context.getBeanDefinitionNames()) { System.err.println(beanDefinitionName); } } }
public class MyConfig { }
使用AnnotationConfigApplicationContext
對象加載MyConfig,即使MyConfig類什么注解沒有,也會被注冊為bean。
2、加載本地類 使用的注解@Component
或其他衍生注解@Service
、@Controller
、@Repository
@Service public class BookServiceImpl implements BookService { }
3、加載第三方j(luò)ar類
由于我們無法在第三方提供的技術(shù)源代碼中去添加上述4個注解,因此當(dāng)你需要加載第三方開發(fā)的bean
的時候可以使用@Component
和@Configuration
都可以,一般引入第三方傾向于后者。
//@Component @Configuration public class DbConfig { @Bean public DruidDataSource dataSource(){ return new DruidDataSource(); } @Bean public Cat cat(){ Cat cat = new Cat(); cat.setDruidDataSource(dataSource()); return cat; } }
@Configuration(proxyBeanMethods = true)
:默認(rèn)設(shè)置,使用了cglib動態(tài)代理
,cat里的dataSource和@Bean創(chuàng)建的dataSource是同一個對象
,可以理解為單例
@Configuration(proxyBeanMethods = false)
:此時和@Component注解功能一樣,cat里的dataSource和@Bean創(chuàng)建的dataSource不是同一個對象
,可以理解為多例
- 如果配置中@Bean標(biāo)識的方法之間
不存在依賴調(diào)用
的話,可以設(shè)置為false,可以避免攔截方法進(jìn)行代理操作,提升性能
三、特殊方式
3.1、使用FactroyBean接口
- spring提供了一個接口
FactoryBean
,也可以用于聲明bean
- 實現(xiàn)了FactoryBean接口的類造出來的對象不是當(dāng)前類的對象,而是FactoryBean接口
泛型
指定類型的對象 - 一般用來創(chuàng)建復(fù)雜對象
public class DogFactoryBean implements FactoryBean<Dog> { //創(chuàng)建bean的復(fù)雜過程 @Override public Dog getObject() throws Exception { Dog d = new Dog(); //......... return d; } //bean的類型 @Override public Class<?> getObjectType() { return Dog.class; } //bean是否單例 @Override public boolean isSingleton() { return true; } }
配置類
public class MyConfig { @Bean public DogFactoryBean dog(){ return new DogFactoryBean(); } }
啟動類
public class App { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class); System.out.println(context.getBean("dog")); } }
3.2、注解導(dǎo)入XML格式配置的bean
- 場景:舊項目xml配置bean融入配置類項目中
@ImportResource
在配置類上直接寫上要被融合的xml配置文件名即可
@Configuration @ImportResource(locations = "spring-bean.xml") public class SpringConfig { }
3.3、通過上下文ApplicationContext注冊bean
在容器初始化完成后手動加載bean,創(chuàng)建方式很多
方式一:無參構(gòu)造
public class App { public static void main(String[] args) { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class); //上下文容器對象已經(jīng)初始化完畢后,手工加載bean ctx.register(Mouse.class); } }
方式二:多參構(gòu)造
public class App { public static void main(String[] args) { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class); //上下文容器對象已經(jīng)初始化完畢后,手工加載bean ctx.registerBean("tom", Cat.class,"花貓",3); } }
四、@Import注解注入bean
1、@Import導(dǎo)入普通類
- 場景:將一個無任何注解的類加載為bean
- 一個類@Improt只能用一次,想要導(dǎo)入多個使用{…,…}
- 只有MyConfig加載為bean,@Import才生效
@Configuration //@Import(Pig.class) @Import({Dog.class,Cat.class}) public class MyConfig { }
public class App { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class); for (String beanDefinitionName : context.getBeanDefinitionNames()) { System.err.println(beanDefinitionName); } } }
輸出結(jié)果:
myConfig
com.xc.springboot.bean.Dog
com.xc.springboot.bean.Cat
2、@Import導(dǎo)入實現(xiàn)了ImportSelector接口的類
- 可以通過添加
判斷語句
就可以實現(xiàn)對bean的加載控制
- 返回值為多個
全路徑類名字符串
- metadata為@Import注解類的元數(shù)據(jù),可以拿到MyConfig類上所有的注解,注解里的屬性,繼承的接口,父類等等信息
- 如下則是判斷MyCofig類上有@Configuration注解則加載Dog類,否則加載Cat類
public class MyImportSelector implements ImportSelector { @Override public String[] selectImports(AnnotationMetadata metadata) { System.out.println("元數(shù)據(jù)Class名稱:" + metadata.getClassName()); //各種條件的判定,判定完畢后,決定是否裝載指定的bean boolean flag = metadata.hasAnnotation("org.springframework.context.annotation.Configuration"); if(flag){ return new String[]{"com.xc.springboot.bean.Dog"}; } return new String[]{"com.xc.springboot.bean.Cat"}; } }
配置類
@Configuration @Import(MyImportSelector.class) public class MyConfig { }
啟動類
public class App { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class); for (String beanDefinitionName : context.getBeanDefinitionNames()) { System.err.println(beanDefinitionName); } } }
輸出結(jié)果:
元數(shù)據(jù)Class名稱:com.xc.springboot.bean.MyConfig
myConfig
com.xc.springboot.bean.Dog
3、@Import導(dǎo)入實現(xiàn)了ImportBeanDefinitionRegistrar接口的類
- 返回值為void,通過
Bean定義(beanDefinition)
注冊創(chuàng)建新的bean - 同樣可以通過添加判斷語句就可以實現(xiàn)bean的加載控制,更加細(xì)粒度判斷bean
public class MyRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(BookService.class).getBeanDefinition(); registry.registerBeanDefinition("bookService",beanDefinition); } }
4、@Import導(dǎo)入實現(xiàn)了BeanDefinitionRegistryPostProcessor接口的類
- BeanDefinitionRegistryPostProcessor接口,其中有兩個重要的方法:
postProcessBeanDefinitionRegistry
:用于注冊新的BeanDefinitionpostProcessBeanFactory
:用于在BeanFactory準(zhǔn)備好后
進(jìn)行自定義操作
- BeanDefinitionRegistryPostProcessor:bean定義注冊
最后
的處理器(在以上處理后執(zhí)行此操作),如果想bean最后確定一個值,可以在這里操作
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { // 通過 BeanDefinitionBuilder 創(chuàng)建一個新的 Bean 定義 BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MyCustomBean.class); // 注冊這個 bean 定義到 registry 中 registry.registerBeanDefinition("myCustomBean", builder.getBeanDefinition()); System.out.println("Bean definition registered: myCustomBean"); } @Override public void postProcessBeanFactory(org.springframework.beans.factory.config.ConfigurableListableBeanFactory beanFactory) throws BeansException { // 在這里可以對 BeanFactory 進(jìn)行進(jìn)一步的配置 System.out.println("Bean factory post-processing"); } }
注意:所有通過@Import導(dǎo)入的bean名稱為全路徑名
到此這篇關(guān)于SpringBoot基礎(chǔ)(四):bean的多種加載方式的文章就介紹到這了,更多相關(guān)SpringBoot bean加載方式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java?I/O?(Input/Output)文件字節(jié)流舉例詳解
Java的輸入輸出流(IO)是用于與外部設(shè)備(如文件、網(wǎng)絡(luò)連接等)進(jìn)行數(shù)據(jù)交互的機(jī)制,下面這篇文章主要給大家介紹了關(guān)于Java?I/O?(Input/Output)文件字節(jié)流的相關(guān)資料,需要的朋友可以參考下2024-08-08Java解析http協(xié)議字符串的方法實現(xiàn)
本文主要介紹了Java解析http協(xié)議字符串的方法實現(xiàn),我們探討了如何使用Java解析HTTP協(xié)議字符串,并將其封裝成了一個HttpRequest類,具有一定的參考價值,感興趣的可以了解一下2023-09-09獲取系統(tǒng)參數(shù)System.getProperties()與配置文件參數(shù)@Value(“${key}“)
這篇文章主要介紹了獲取系統(tǒng)參數(shù)System.getProperties()與配置文件參數(shù)@Value("${key}"),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-05-05Log4j2?重大漏洞編譯好的log4j-2.15.0.jar包下載(替換過程)
Apache?開源項目?Log4j?的遠(yuǎn)程代碼執(zhí)行漏洞細(xì)節(jié)被公開,由于?Log4j?的廣泛使用,該漏洞一旦被攻擊者利用會造成嚴(yán)重危害,下面小編給大家?guī)砹薒og4j2?重大漏洞編譯好的log4j-2.15.0.jar包下載,感興趣的朋友一起看看吧2021-12-12