spring boot bean注册 多实例

发布时间 2023-04-15 21:26:09作者: youxin

@Configuration
3.1.@Configuration作用
@Configuration底层是含有@Component,所以@Configuration 具有和 @Component的作用。
@Configuration 用于定义配置类,可理解为Spring的xml配置文件里面的<beans>标签。
@Configration 标注的类不能是final 类型
@Configration 标注类中可以声明一个或多个 @Bean方法
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
String value() default "";
}

@Configuration标注在类上,相当于把该类作为spring的xml配置文件中的<beans>

作用为:配置spring容器(应用上下文)

@Configuration
public class TestConfiguration {
public TestConfiguration() {
System.out.println("TestConfiguration容器启动初始化。。。");
}
}
 
相当于

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd" default-lazy-init="false">

</beans>
 
3.2.@Configuration使用
@Configration标注的类中可以声明多个@Bean方法,并且 Bean 与 Bean 之间是可以有依赖关系的。
如果一个 bean 的依赖其他 bean,可以注入方式有:

直接调用对配置类中依赖Bean的方法
在形参上使用@Qualifier("beanName")通过Bean的名字注入实例
在形参上使用@Autowired通过Bean的类型注入实例
————————————————
版权声明:本文为CSDN博主「墩墩分墩」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq877728715/article/details/109543674

 

@Bean
4.1.@Bean作用
@Bean标注在方法上(返回某个实例的方法),等价于spring的xml配置文件中的<bean>,

作用为:注册bean对象

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Bean {
@AliasFor("name")
String[] value() default {};

@AliasFor("value")
String[] name() default {};

/** @deprecated */
@Deprecated
Autowire autowire() default Autowire.NO;

boolean autowireCandidate() default true;

String initMethod() default "";

String destroyMethod() default "(inferred)";
}
 
name: 指定bean的名字,并且可以接受一个数组,配置多个name,默认采用的是 "方法名" + "首字母小写"的命名方式
initMethod: 初始化Bean时执行的方法名
destoryMethod: 销毁Bean时执行的方法名
或者使用通过@PostConstruct 和 @PreDestroy 方法 实现初始化和销毁bean之前进行的操作 。

配置类

@Configuration
public class TestConfiguration {
public TestConfiguration() {
System.out.println("TestConfiguration容器启动初始化。。。");
}

// @Bean注解注册bean,同时可以指定初始化和销毁方法
@Bean(initMethod = "init",destroyMethod = "destroy")
@Scope("prototype")//每次从Spring容器获取都会新建一个TestBean 对象
public TestBean testBean() {
TestBean testBean = new TestBean();
testBean.setUsername("admin");
testBean.setPassword("123456");
testBean.setUrl("www.baidu.com");
return testBean;
}
}

 
要被注册到Spring容器的Bean

@Data
public class TestBean {
private String username;
private String url;
private String password;
//Bean初始化方法
public void init() {
System.out.println("TestBean 初始化。。。");
}
//Bean销毁方法
public void destroy() {
System.out.println("TestBean 销毁。。。");
}
}
 
上述操作相当于实例化TestBean ,并交给Spring容器管理

注:

@Bean标注的方法,如果没有指定bean的名称,默认采用的是 “方法名” + "首字母小写"的命名方式
@Bean注解默认作用域为单例singleton作用域,可通过@Scope("prototype")设置为原型作用域;
@Bean的作用是注册bean对象,我们也可以使用@Component、@Controller、@Service、@Repository等注解注册bean(在需要注册的类上加注解),然后配置@ComponentScan注解进行自动扫描。
4.2.指定@Bean别名
Bean 名称
默认情况下 Bean 名称就是方法名,比如下面 Bean 名称便是 myBean

@Bean
public MyBean myBean() {
return new MyBean();
}

@Bean 注解支持设置别名。

@Bean("myBean")
public MyBean myBean() {
return new MyBean();
}

@Bean 注解支持设置多个别名。

@Bean({"myBean1","myBean2"})
public MyBean myBean() {
return new MyBean();
}
 
4.3.@Bean 与其他注解一起使用
@Bean 注解常与 @Scope、@Lazy,@DependsOn 和 @Primary注解一起使用:

@Profile :可以在不同环境加载不同的Bean。如: 开发环境和生产环境加载不同的数据源Bean
@Scope :将 Bean 的作用域从单例改变为指定的作用域
@Scope("prototype ") :每次获取 Bean 的时候会有一个新的实

@Lazy :只有在默认单例作用域的情况下才有实际效果
@DependsOn :在当前 Bean 创建之前需要先创建其他 Bean,可以控制Bean的加载顺序,
@Primary: 当一种类型的Bean,可能会有几种不同的实现类,可以使用@Primary,让Sping容器默认注入某一个实例
4.3.@Bean初始化和销毁的回调
通过 @Bean 注解的initMethod和 destrodMethod数学可以Bean 在初始化和销毁时会调用哪个方法

public class MyBean {
public void init() {
System.out.println("MyBean开始初始化...");
}
public void destroy() {
System.out.println("MyBean销毁...");
}
}
 
@Bean(initMethod="init", destroyMethod="destroy")
public MyBean myBean() {
return new MyBean();
}
1
2
3
4
4.4.Bean的条件装配注解
@Conditional : 指定的Condition实现类,matches方法返回true,则实例化一个Bean

@Configuration
public class BeanConfig {
//如果WindowsCondition的实现方法返回true,则注入这个bean
@Conditional({WindowsCondition.class})
@Bean(name = "bill")
public Person person1(){
return new Person("Bill Gates",62);
}

//如果LinuxCondition的实现方法返回true,则注入这个bean
@Conditional({LinuxCondition.class})
@Bean("linus")
public Person person2(){
return new Person("Linus",48);
}
}
 
创建 LinuxCondition和 WindowsCondition类,并实现Condition接口

public class LinuxCondition implements Condition {

@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
Environment environment = conditionContext.getEnvironment();
String property = environment.getProperty("os.name");
if (property.contains("Linux")){
return true;
}
return false;
}
}
 
@ConditionalOnBean(仅仅在当前上下文中存在某个对象时,才会实例化一个Bean)

//RedisOperBean依赖redisTemplate
@Component
@ConditionalOnBean(name="redisTemplate")
public class RedisOperBean {
private final RedisTemplate redisTemplate;
public RedisOperBean(RedisTemplate redisTemplate) {}
}
 
@ConditionalOnMissingBean(仅仅在当前上下文中不存在某个对象时,才会实例化一个Bean)

@Bean
@ConditionalOnMissingBean(name = "imageValidateCodeGenerator")
public ValidateCodeGenerator imageValidateCodeGenerator() {
ImageCodeGenerator codeGenerator = new ImageCodeGenerator();
codeGenerator.setSecurityProperty(securityProperties);
return codeGenerator;
}
 
@ConditionalOnClass(某个class位于classpath 上,才会实例化一个Bean)

@Configuration
@ConditionalOnClass(name = "this.clazz.does.not.Exist")
class OnClassModule {}
1
2
3
@ConditionalOnMissingClass(某个class类路径上不存在的时候,才会实例化一个Bean)

@ConditionalOnWebApplication: 是web应用

@ConditionalOnNotWebApplication(不是web应用)

@ConditionalOnResource:classpath下存在指定的资源文件,才会实例化一个Bean

@Bean
@ConditionalOnResource(resources="classpath:shiro.ini")
protected Realm iniClasspathRealm(){}
1
2
3
@ConditionalOnExpression(当表达式为true的时候,才会实例化一个Bean)

@Configuration
@ConditionalOnExpression("${enabled:false}")
public class BigpipeConfiguration {
@Bean
public OrderMessageMonitor orderMessageMonitor(ConfigContext configContext) {
return new OrderMessageMonitor(configContext);
}
}
 
表达式其他用法

@ConditionalOnExpression("${mq.cumsumer.enabled}==1&&${rabbitmq.comsumer.enabled:true}")
@ConditionalOnExpression("'${mq.comsumer}'.equals('rabbitmq')")
1
2
SpringBoot为我们提供的配置类有180多个,但是我们不可能会全部引入。所以在自动装配的时候,会去ClassPath下面寻找,是否有对应的配置类。如果有配置类,则按条件注解 @Conditional或者@ConditionalOnProperty等相关注解进行判断,决定是否需要装配。如果classPath下面没有对应的字节码,则不进行任何处理。
————————————————
版权声明:本文为CSDN博主「墩墩分墩」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq877728715/article/details/109543674

 

首先介绍概念,什么是spring中bean的多实例和单实例。
在Spring中,bean可以被定义为两种模式:prototype(多例)和singleton(单例)
singleton(单例):只有一个共享的实例存在,所有对这个bean的请求都会返回这个唯一的实例。
prototype(多例):对这个bean的每次请求都会创建一个新的bean实例,类似于new。
Spring bean默认是单例模式。
————————————————