SpringBoot中注冊Bean的方式總結
@ComponentScan + @Componet相關注解
@Componet相關注解有@Configuration、@Controller、@Service、@Repository,配合@ComponentScan就能被掃描注冊到Spring容器中。
定義我們需要注冊的類
@Configuration
public class ForlanConfig {
@Bean
public ForlanBean forlanBean1(){
return new ForlanBean();
}
}
@Component
// @Controller
// @Service
// @Repository
public class ForlanComponent {
@Bean
public ForlanBean forlanBean2(){
return new ForlanBean();
}
}
public class ForlanBean {
}
驗證如下:
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(Application.class, args);
System.out.println(applicationContext.getBean("forlanConfig"));
System.out.println(applicationContext.getBean("forlanComponent"));
}
// 輸出如下:
cn.forlan.ForlanConfig$$EnhancerBySpringCGLIB$$e43dabb2@1305c126
cn.forlan.ForlanComponent@43af351a
@Bean
前面已經定義好需要注冊的類,直接驗證即可
驗證如下:
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(Application.class, args);
System.out.println(applicationContext.getBean("forlanBean1"));
System.out.println(applicationContext.getBean("forlanBean2"));
}
// 輸出如下:
cn.forlan.ForlanBean@64279ab
cn.forlan.ForlanBean@6650a6c
@Import
它可以導入的類有:Component, Configuration, ImportSelector, ImportBeanDefinitionRegistrar, ImportResource
定義我們需要注冊的類
public class CaffeineForlanCache {
}
public class RedisForlanCache {
}
public class ForlanCustomize {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
實現ImportSelector
public class ForlanImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
Map<String, Object> annotationAttributes = importingClassMetadata.getAnnotationAttributes(EnableForlanCache.class.getName());
//通過 不同type注入不同的緩存到容器中
CacheType cacheType = (CacheType) annotationAttributes.get("cacheType");
if(cacheType.equals(CacheType.CAFFEINE)){
return new String[]{CaffeineForlanCache.class.getName()};
}else{
return new String[]{RedisForlanCache.class.getName()};
}
}
}
實現ImportBeanDefinitionRegistrar
public class ForlanBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(ForlanCustomize.class)
.addPropertyValue("name", "forlan").getBeanDefinition();
registry.registerBeanDefinition("forlanCustomize", beanDefinition);
}
}
定義注解導入
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({ForlanImportSelector.class, ForlanBeanDefinitionRegistrar.class})
public @interface EnableForlanCache {
CacheType cacheType() default CacheType.REDIS;
}
驗證如下:
@EnableForlanCache(cacheType = CacheType.CAFFEINE)
public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(Application.class, args);
System.out.println(applicationContext.getBean("forlanBean1"));
System.out.println(applicationContext.getBean("forlanBean2"));
}
}
// 輸出如下:
cn.forlan.ForlanCustomize@245cb8df
cn.forlan.CaffeineForlanCache@578c3fd9
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'cn.forlan.RedisForlanCache' available
spring.factories
定義我們需要注冊的類
public class ForlanAutoConfiguration {
}
在resources\META-INF下新建spring.factories,填寫內容,SpringBoot在啟動時,就會自動注入
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ cn.forlan.ForlanAutoConfiguration
驗證如下:
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(Application.class, args);
System.out.println(applicationContext.getBean(ForlanAutoConfiguration.class));
System.out.println(applicationContext.getBean("cn.forlan.ForlanAutoConfiguration"));
}
// 輸出如下:
cn.forlan.ForlanAutoConfiguration@19d53ab4
cn.forlan.ForlanAutoConfiguration@19d53ab4
注:這種方式的注入的BeanName為路徑+類名
總結
總的來說,一共有如下幾種方式可以注冊bean:
- @ComponentScan + @Componet相關注解
- 使用@Bean注解
- 使用@Import注解
- spring.factories
@Configuration和@Component的主要區(qū)別?
使用場景:@Configuration主要用于定義配置類,其中包含了Bean的定義和配置;而@Component適用于任何需要被Spring管理的類。
功能:@Configuration主要用于配置類的定義和初始化Bean;而@Component主要用于組件的自動掃描和注冊。
@Bean是不是必須和@Configuration一起使用?
不是的,盡管@Bean注解常常出現在帶有@Configuration注解的配置類中,用于定義和初始化Spring容器中的Bean,但它也可以單獨使用。@Bean注解的主要作用是告訴Spring框架,被該注解標注的方法將返回一個對象,這個對象需要被注冊到Spring容器中。在非配置類中使用@Bean注解,只需要確保該方法能夠被Spring掃描到即可。
@Import導入配置類有意義?
總結來說,@Import導入的類本身不是Bean,而是用于擴展Spring容器配置的工具。它可以定義或注冊其他的Bean,但你不能直接通過applicationContext.getBean()獲取這些導入類的實例。相反,你應該獲取它們定義或注冊的Bean的實例。它的主要價值在于動態(tài)注入Bean。
出現異常:java.lang.NoClassDefFoundError: Could not initialize class org.springframework.beans.factory.BeanDefinitionStoreException
原因是這個類寫的有問題,ForlanImportSelector根本就沒有初始化,不是是當前類

以上就是SpringBoot中注冊Bean的方式總結的詳細內容,更多關于SpringBoot注冊Bean的資料請關注腳本之家其它相關文章!
相關文章
restTemplate發(fā)送get與post請求并且?guī)祮栴}
這篇文章主要介紹了restTemplate發(fā)送get與post請求并且?guī)祮栴},具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07

