Spring容器注入bean的五種方法逐個解析
前言
我們在項(xiàng)目開發(fā)中都用到Spring,知道對象是交由Spring去管理。那么將一個對象加入到Spring容器中,有幾種方法呢,我們來總結(jié)一下。
@ComponentScan+@Component
@ComponentScan可以放在啟動類上,指定要掃描的包路徑;該包路徑下被@Component修飾的類,都會被注入到Spring容器中。
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan(basePackages = "com.gs.beanRegister")
public class BootStrap {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(BootStrap.class);
A bean = context.getBean(A.class);
bean.say();
}
}
com.gs.beanRegister包下:
import org.springframework.stereotype.Component;
@Component
public class A {
public void say() {
System.out.println("這是a");
}
}
注:在SpringBoot中,由于其自動裝配的特性,所以@ComponentScan可以不加,只要@Component修飾的類和啟動類在同一包下或者在啟動類所在包的子包下。
@Configuration+@Bean
@Configuration用來聲明一個配置類,如果它的方法被@Bean修飾,那么該方法返回的對象也會被注入到Spring容器中。
代碼方面,BootStrap 類不動,A類的@Component去掉,com.gs.beanRegister包下建個配置類:
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Bean;
@Configuration
public class MyConfiguration {
@Bean
public A a() {
return new A();
}
}
通過@Import注解
這個注解可能平時大家接觸得不多,它有好幾種使用方式。
1.直接導(dǎo)入類的class
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
@Import(A.class)
public class BootStrap {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(BootStrap.class);
A bean = context.getBean(A.class);
//B bean = context.getBean(B.class);
bean.say();
}
}
A類不用添加任何注解:
public class A {
public void say() {
System.out.println("這是a");
}
}
2.導(dǎo)入配置類
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Import;
@Import(MyConfiguration.class)
public class BootStrap {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(BootStrap.class);
A bean = context.getBean(A.class);
bean.say();
}
}
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
// 使用@Import導(dǎo)入配置類時,@Configuration可以不加
//@Configuration
public class MyConfiguration {
@Bean
public A a() {
return new A();
}
}
3.導(dǎo)入ImportSelector的實(shí)現(xiàn)類
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Import;
@Import(MyImportSelector.class)
public class BootStrap {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(BootStrap.class);
A bean = context.getBean(A.class);
bean.say();
}
}
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata metadata) {
// 返回要注入的bean的全路徑,A類不用任何注解修飾
// SpringBoot的自動裝配,就用到了這種方式:
// 返回配置類的全路徑,配置類的@Bean方法返回的對象也能注入到容器中
return new String[] { A.class.getName() };
}
}
4.導(dǎo)入ImportBeanDefinitionRegistrar的實(shí)現(xiàn)類
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Import;
@Import(MyImportBeanDefinitionRegistrar.class)
public class BootStrap {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(BootStrap.class);
A bean = context.getBean(A.class);
bean.say();
}
}
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
public class MyImportBeanDefinitionRegistrar implements
ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata,
BeanDefinitionRegistry registry) {
// 構(gòu)建bean的元數(shù)據(jù),A類不用任何注解修飾
// spring-mybatis掃描mapper接口,生成代理類,就是用的這種方式
BeanDefinition definition = new RootBeanDefinition(A.class);
registry.registerBeanDefinition("a", definition);
}
}
借助FactoryBean接口
實(shí)現(xiàn)FactoryBean接口的類,除了本身會被注入外,getObject方法返回的對象也會被注入到Spring容器中。
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Import;
@Import(MyFactoryBean.class)
public class BootStrap {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(BootStrap.class);
A bean = context.getBean(A.class);
bean.say();
}
}
import org.springframework.beans.factory.FactoryBean;
public class MyFactoryBean implements FactoryBean {
@Override
public Object getObject() throws Exception {
return new A();
}
@Override
public Class<?> getObjectType() {
return A.class;
}
}
借助BeanDefinitionRegistryPostProcessor接口
在Spring容器啟動時,會調(diào)用該接口的postProcessBeanDefinitionRegistry方法,大概意思是等BeanDefinition(上面提到的bean的元數(shù)據(jù))加載完成后,再對它進(jìn)行后置處理。所以可以在此調(diào)整BeanDefinition,從而把對應(yīng)的bean注入。
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class BootStrap {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext();
BeanDefinitionRegistryPostProcessor postProcessor =
new MyBeanDefinitionRegistryPostProcessor();
context.addBeanFactoryPostProcessor(postProcessor);
context.refresh();
A a = context.getBean(A.class);
a.say();
}
}
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
public class MyBeanDefinitionRegistryPostProcessor implements
BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry
registry) throws BeansException {
BeanDefinition definition = new RootBeanDefinition(A.class);
registry.registerBeanDefinition("a", definition);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory
beanFactory) throws BeansException {
}
}
到此這篇關(guān)于Spring容器注入bean的五種方法逐個解析的文章就介紹到這了,更多相關(guān)Spring注入bean內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MyBatis如何調(diào)用存儲過程與存儲函數(shù)
這篇文章主要介紹了MyBatis如何調(diào)用存儲過程與存儲函數(shù),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11
SpringCloud-Gateway轉(zhuǎn)發(fā)WebSocket失敗問題及解決
這篇文章主要介紹了SpringCloud-Gateway轉(zhuǎn)發(fā)WebSocket失敗問題及解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-09-09
SpringBoot中MapStruct實(shí)現(xiàn)優(yōu)雅的數(shù)據(jù)復(fù)制
本文主要介紹了SpringBoot中MapStruct實(shí)現(xiàn)優(yōu)雅的數(shù)據(jù)復(fù)制,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-08-08
SpringBoot詳解如何進(jìn)行整合Druid數(shù)據(jù)源
Druid是阿里開發(fā)的一款開源的數(shù)據(jù)源,被很多人認(rèn)為是Java語言中最好的數(shù)據(jù)庫連接池,本文主要介紹了SpringBoot整合Druid數(shù)據(jù)源的方法實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06
SpringBoot實(shí)現(xiàn)文件上傳與下載功能的示例代碼
文件上傳與下載是Web應(yīng)用開發(fā)中常用的功能之一。接下來我們將討論如何在Spring?Boot的Web應(yīng)用開發(fā)中,如何實(shí)現(xiàn)文件的上傳與下載,感興趣的可以了解一下2022-06-06

