java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > SpringBoot注册Bean

SpringBoot中注册Bean的方式总结

作者:程序员Forlan

这篇文章主要介绍了SpringBoot中注册Bean的方式总结,@ComponentScan + @Componet相关注解,@Bean,@Import和spring.factories这四种方式,文中代码示例给大家介绍的非常详细,需要的朋友可以参考下

@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:

@Configuration和@Component的主要区别?

使用场景:@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的实例。它的主要价值在于动态注入Bean。

出现异常:java.lang.NoClassDefFoundError: Could not initialize class org.springframework.beans.factory.BeanDefinitionStoreException

原因是这个类写的有问题,ForlanImportSelector根本就没有初始化,不是是当前类

在这里插入图片描述

以上就是SpringBoot中注册Bean的方式总结的详细内容,更多关于SpringBoot注册Bean的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文