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)文章
Java實(shí)現(xiàn)圖片與二進(jìn)制的互相轉(zhuǎn)換
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)圖片與二進(jìn)制的互相轉(zhuǎn)換,將圖片轉(zhuǎn)二進(jìn)制再將二進(jìn)制轉(zhuǎn)成圖片,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-03-03
java去除中文括號小括號,或者英文括號的實(shí)例代碼
這篇文章主要介紹了java去除中文括號小括號,或者英文括號的實(shí)例代碼,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09
SpringBoot讀取properties或者application.yml配置文件中的數(shù)據(jù)
這篇文章主要介紹了SpringBoot讀取properties或者application.yml配置文件中的數(shù)據(jù),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06
解析SpringBoot中@Autowire注解的實(shí)現(xiàn)原理
在開發(fā)Java項(xiàng)目時,依賴注入是一種常見的實(shí)現(xiàn)方式,SpringBoot框架通過@Autowired注解來實(shí)現(xiàn)依賴注入的功能,本文將介紹SpringBoot中 Autowired注解實(shí)現(xiàn)的原理2023-06-06

