SpringBoot加載bean的八種方式總結(jié)
第一種bean的加載方式-配置文件
先創(chuàng)建一個(gè)使用maven的spring工程
導(dǎo)入spring核心配置
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.9</version>
</dependency>創(chuàng)建一個(gè)類
public class Cat {
}public class Dog {
}創(chuàng)建一個(gè)名為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)建一個(gè)啟動(dò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)不唯一時(shí)會報(bào)錯(cuò)
System.out.println(dog);
}
}運(yùn)行結(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);
}
}
}運(yùn)行結(jié)果

第二種加載bean方式-注解和掃描
使用注解,注解的作用就是替代配置文件的配置,注解有@Component @Service @Repository等
替換配置文件中的<bean id= class=..>
@Component("cat") //起的名
public class Cat {
}@Component
public class Dog {
}使用完注解還得讓spring去掃描到這個(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
">
<!--告訴spring掃描哪個(gè)包c(diǎn)omponent導(dǎo)入context命名空間-->
<context:component-scan base-package="com"/>
</beans>運(yùn)行結(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)建一個(gè)類,返回你需要導(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;
}
}運(yùn)行結(jié)果

第三種加載bean方式-不使用配置文件
創(chuàng)建一個(gè)類代替配置文件
package com.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration//定義為配置類
@ComponentScan({"com.config","com.service"}) //注解掃描包
public class springConfig {
}運(yùn)行類也得修改
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);
}
}
}運(yùn)行結(jié)果

擴(kuò)展-bean的加載方式擴(kuò)展FactoryBean<>
初始化實(shí)現(xiàn)FactoryBean<>接口的類,實(shí)現(xiàn)對bean加載到容器之前的批處理操作。
實(shí)現(xiàn)了FactoryBean接口創(chuàng)建出來的對象不是本身而是里面的泛型。
創(chuàng)建一個(gè)類實(shí)現(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;
}
//是否是單例,單例則多次獲取都是一個(gè)對象
public boolean isSingleton() {
return false;
}
}@Component
public class Dog {
}啟動(dòng)的主類
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"));
}
}運(yùn)行結(jié)果

產(chǎn)生的是泛型的對象
擴(kuò)展-@ImportResource導(dǎo)入配置文件

看源碼可知道,可以寫入多個(gè)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();
}
}兩個(gè)配置文件中的bean,排在前面的首先加載,后面的之后加載,同的內(nèi)容以之后的為主,不同的內(nèi)容都加載。
擴(kuò)展-proxyBeanMethods屬性-產(chǎn)生代理對象
@Configuration注解中有一屬性proxyBeanMethod屬性,默認(rèn)值是true

值為false時(shí)
@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());
}
}運(yùn)行結(jié)果

產(chǎn)生的是普通對象,每一次調(diào)用方法都會new一個(gè)新的對象前提是這個(gè)方法是被bean管理的對象。
值為true時(shí)
不寫或?qū)憈rue時(shí)
@Configuration(proxyBeanMethods = true)
@ComponentScan("com")
@ImportResource({"applicationContext2.xml","applicationContext.xml"})
public class SpringConfig2 {
@Bean
public Cat cat(){
return new Cat();
}
}運(yùn)行結(jié)果

會產(chǎn)生一個(gè)代理對象,這個(gè)代理對象讓我們每次調(diào)用方法是都是同一個(gè),前提也是需要被bean容器管理
注:產(chǎn)生的bean對象沒指定名稱時(shí),默認(rèn)是方法名或類名首字母小寫,如類名是SpringTest則產(chǎn)生的bean是springTest
第四種加載bean方式-使用@Import
翻看@Import源碼可知,需要一個(gè)類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);
}
}
}運(yùn)行結(jié)果

全路徑名,加入的類即使沒有被spring管理也可以產(chǎn)生bean。
第五種加載bean方式-registerBean
使用上下文對象在容器初始化后注入bean
在創(chuàng)建完上下文對象的時(shí)候可以加載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 +
'}';
}
}運(yùn)行結(jié)果 ,當(dāng)有多個(gè)的時(shí)候,且bean的名字一致時(shí),以最后的為準(zhǔn)。

或者直接使用
app.register(Cat.class);
也可以快速的加載一個(gè)bean

第六種加載bean方式-實(shí)現(xiàn)ImportSelector接口
這個(gè)接口有許多方法用來判定

導(dǎo)入實(shí)現(xiàn)了ImportSelector接口的類,實(shí)現(xiàn)對導(dǎo)入源的編程式處理
public class MyImportSelector implements ImportSelector {
public String[] selectImports(AnnotationMetadata annotationMetadata) {//AnnotationMetadata 注解的源數(shù)據(jù)
// 做判定條件,是否有這個(gè)注解
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);
}
}
}運(yùn)行結(jié)果

第七種加載bean方式-實(shí)現(xiàn)ImportBeanDefinitionRegistrar
導(dǎo)入實(shí)現(xiàn)ImportBeanDefinitionRegistrar接口的類,通過BeanDefinition的注冊器注冊實(shí)名bean,實(shí)現(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 {
}運(yùn)行結(jié)果

第八種bean的加載方式-實(shí)現(xiàn)BeanDefinitionRegistryPostProcessor
導(dǎo)入實(shí)現(xiàn)了BeanDefinitionRegistryPostProcessor接口的類,通過BeanDefintion的注冊器注冊實(shí)名bean,實(shí)現(xiàn)對容器中bean的最終裁定.(以這個(gè)接口加載的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 {
}運(yùn)行結(jié)果

實(shí)現(xiàn)bean的方式總結(jié)
1.xml+<bean/>
2.xml:context+注解(@Component+4個(gè)@Bean
3.配置類+掃描+注解(@Component+4個(gè)@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上下文工具類?ApplicationContextUtil
這篇文章主要介紹了基于Spring上下文工具類?ApplicationContextUtil,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11
java時(shí)間戳與日期相互轉(zhuǎn)換工具詳解
這篇文章主要為大家詳細(xì)介紹了java各種時(shí)間戳與日期之間相互轉(zhuǎn)換的工具,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12
使用Jmeter進(jìn)行http接口測試的詳細(xì)流程
本文主要針對http接口進(jìn)行測試,使用Jmeter工具實(shí)現(xiàn), Jmter工具設(shè)計(jì)之初是用于做性能測試的,它在實(shí)現(xiàn)對各種接口的調(diào)用方面已經(jīng)做的比較成熟,因此,本次直接使用Jmeter工具來完成對Http接口的測試,需要的朋友可以參考下2024-12-12
在Java中將List轉(zhuǎn)換為String輸出過程解析
這篇文章主要介紹了在Java中將List轉(zhuǎn)換為String輸出過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09

