@Bean注解详解
Posted zensezz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了@Bean注解详解相关的知识,希望对你有一定的参考价值。
@Bean注解详解
Bean 用法
@Bean表示方法产生一个由Spring管理的bean,属性的名称语义与Spring XML中的<bean> 标签配置的一样
public MyBean myBean() {
// instantiate and configure MyBean obj
return obj;
}
当使用name属性可用时,用于确定bean名称的默认策略是使用方法的名称。
这是方便和直观的,但是如果需要显式命名,则可以在注解上使用 name 属性(或其别名{value})。
另请注意 name接受一个字符串数组,允许为单个bean使用多个名称(即主bean名称加上一个或多个别名)。
@Bean({"b1", "b2"}) // bean available as \'b1\' and \'b2\', but not \'myBean\'
public MyBean myBean() {
// instantiate and configure MyBean obj
return obj;
}
Bean 增强
@Bean注释不提供Profile, Scope, Lazy, DependsOn, Primary, Order功能
意思是,如果要在bean上配置Profile, Scope, Lazy, DependsOn, Primary, Order这些的时候,不再是用属性了,而是在该bean上使用它们对应的注解
@Bean
@Profile("production")
@Scope("prototype")
@Order(-100)
public MyBean myBean() {
// instantiate and configure MyBean obj
return obj;
}
上述注释的语义与它们在组件类级别的用法相匹配:
- @Profile 允许选择性地包含某些bean。
- @Scope 将bean的范围从单例更改为指定的范围。
- @Lazy 仅在默认单例作用域的情况下才具有实际效果。
- @DependsOn 会在创建此bean之前强制创建特定的其他bean,以及该bean通过直接引用表示的任何依赖关系,这通常对单例启动很有帮助。
- @Primary 是一种在注入点级别解决歧义的机制如果需要注入单个目标组件,但多个bean按类型匹配,
如果需要注入单个目标组件,但多个Bean按类型匹配 - @Order;@Bean 方法还可以声明限定符批注和 @Order,在注入点解析期间要像相应的那样考虑相应组件类上的注释,但每个bean定义可能非常个别(在具有相同 bean类的多个定义的情况下)。在初始类型匹配之后,order的值会缩小候选集的范围;order值确定在收集情况下解析元素的顺序注入点(通过类型和限定符匹配多个目标bean。
- @Order 值可能会影响注入点的优先级,但请注意,它们不会影响单例启动顺序,这是依赖关系和 @DependsOn 声明,另外,javax.annotation.Priority 在此级别上不可用,因为它不能在方法上声明。它的语义可以通过 @Order 值与 @Primary 结合使用,以对每种类型的单个bean进行调整。
@Bean使用场景
通常, @Bean方法在@Configuration 类中声明。因此,在此模式下,不能将 @Configuration类及其工厂方法标记为final或private。在这种情况下,bean方法可以直接调用来引用同一类中的其他 @Bean方法。
这样可以确保bean 之间的引用是强类型的且可传导的。保证了这样的bean间引用 像getBean()查找一样,加强作用域和AOP语义。这些是从原始 “ Spring JavaConfig”项目中所知道的语义,这些语义要求在运行时将每个此类配置类的CGLIB子类化。
@Configuration
public class AppConfig {
@Bean
public FooService fooService() {
return new FooService(fooRepository());
}
@Bean
public FooRepository fooRepository() {
return new JdbcFooRepository(dataSource());
}
// ...
}
注意:
- @Bean 方法也可以在用 @Configuration注释的类中声明。
例如,可以在 @Component 类中甚至在其他类中将bean方法声明为。
在这种情况下, @Bean方法将以所谓的lite模式进行处理。 - bean 容器中将 lite模式下的 Bean方法视为普通的工厂方法(类似于XML中的 factory-method声明),适当地应用范围和生命周期回调。在这种情况下,包含的类保持不变,并且对于包含类或工厂方法没有异常约束。
- 与 @Configuration类中bean方法的语义相反,在lite模式下不支持 bean间引用 。相反,当一个 @Bean方法以lite模式调用另一个@Bean方法时,该调用是标准的Java方法调用;Spring不会通过CGLIB代理拦截调用。这类似于内部 @Transactional方法调用,然而在代理模式下,Spring不会拦截调用;但是仅在AspectJ模式下,Spring会拦截调用。如下
@Component
public class Calculator {
public int sum(int a, int b) {
return a+b;
}
@Bean
public MyBean myBean() {
return new MyBean();
}
}
@Bean 与 BeanFactoryPostProcessor(BFPP)
对于返回Spring org.springframework.beans.factory.config.BeanFactoryPostProcessor.BeanFactoryPostProcessor()类型的 @Bean方法,必须特别注意。由于BFPP对象必须在容器生命周期的早期进行实例化,因此它们可能会干扰内部的 @Autowired,@Value和 @PostConstruct 等批注的处理。@Configuration 类。为了避免这些生命周期问题,请将BFPP-返回的 @Bean方法标记为static。例如:
@Bean
public static PropertySourcesPlaceholderConfigurer pspc() {
// instantiate, configure and return pspc ...
}
BeanFactoryPostProcessor.通过将此方法标记为static,可以在不引发其声明 @Configuration类的实例的情况下调用该方法,从而避免了上述生命周期冲突。但是请注意,如上所述,对于范围界定和AOP语义,static 下的@Bean方法不会得到增强。 BFPP情况下可行,因为其他@Bean方法通常不引用它们,将为具有返回类型可分配给 BeanFactoryPostProcessor的任何非静态 @Bean方法发出WARN级别的日志消息
@Bean的方法
- value()
/**
* Alias for {@link #name}.
* <p>Intended to be used when no other attributes are needed, for example:
* {@code @Bean("customBeanName")}.
* @since 4.3.3
* @see #name
*/
@AliasFor("name")
String[] value() default {};
- name()
Bean的名称,如果有多个名称,则为主Bean名称加别名。如果未指定,则Bean的名称为带注释的方法的名称。如果指定方法名称将被忽略。 如果未声明其他属性,也可以通过value属性配置bean名称和别名
/**
* The name of this bean, or if several names, a primary bean name plus aliases.
* <p>If left unspecified, the name of the bean is the name of the annotated method.
* If specified, the method name is ignored.
* <p>The bean name and aliases may also be configured via the {@link #value}
* attribute if no other attributes are declared.
* @see #value
*/
@AliasFor("value")
String[] name() default {};
- autowire()
是否通过名称或类型通过基于约定的自动装配来注入依赖项? 注意,这种自动装配模式只是基于约定的基于bean属性设置器方法的外部驱动自动装配,类似于XML bean定义。默认模式确实允许注释驱动的自动装配。 “ no”仅指外部驱动的自动装配,不影响bean类本身通过注释表示的任何自动装配要求。Spring5.1弃用,因为 @Bean工厂方法参数解析和 @Autowired处理取代了基于名称/类型的bean属性注入
/**
* Are dependencies to be injected via convention-based autowiring by name or type?
* <p>Note that this autowire mode is just about externally driven autowiring based
* on bean property setter methods by convention, analogous to XML bean definitions.
* <p>The default mode does allow for annotation-driven autowiring. "no" refers to
* externally driven autowiring only, not affecting any autowiring demands that the
* bean class itself expresses through annotations.
* @see Autowire#BY_NAME
* @see Autowire#BY_TYPE
* @deprecated as of 5.1, since {@code @Bean} factory method argument resolution and
* {@code @Autowired} processing supersede name/type-based bean property injection
*/
@Deprecated
Autowire autowire() default Autowire.NO;
- autowireCandidate()
此bean是否适合自动连接到其他bean? 默认为true;对于内部代理,请将其设置为false,而不是要在其他地方出现相同类型的Bean。
/**
* Is this bean a candidate for getting autowired into some other bean?
* <p>Default is {@code true}; set this to {@code false} for internal delegates
* that are not meant to get in the way of beans of the same type in other places.
* @since 5.1
*/
boolean autowireCandidate() default true;
initMethod()
初始化期间要在Bean实例上调用的方法的可选名称。鉴于可以在Bean注释方法的主体内直接以编程方式调用该方法,因此不常用。默认值为“”(空字符串),表示没有要调用的初始化方法。
/**
* The optional name of a method to call on the bean instance during initialization.
* Not commonly used, given that the method may be called programmatically directly
* within the body of a Bean-annotated method.
* <p>The default value is {@code ""}, indicating no init method to be called.
* @see org.springframework.beans.factory.InitializingBean
* @see org.springframework.context.ConfigurableApplicationContext#refresh()
* 初始化期间要在Bean实例上调用的方法的可选名称。
* 鉴于可以在Bean注释方法的主体内直接以编程方式调用该方法,因此不常用。
* 默认值为“”(空字符串),表示没有要调用的初始化方法。
*/
String initMethod() default "";
destroyMethod
关闭应用程序上下文时要在Bean实例上调用的方法的可选名称,例如JDBC DataSource实现上的 close()方法或Hibernate SessionFactory对象。该方法必须没有参数,但可以引发任何异常。为方便用户,容器将尝试针对 @Bean方法返回的对象推断一个destroy方法。例如,给定一个 @Bean方法返回一个Apache Commons DBCP 的 BasicDataSource,则容器将注意到该对象上的 close()方法可用,并自动将其注册为 destroyMethod 。目前,这种“销毁方法推断”仅限于检测名为“ close”或“ shutdown”的公共无参数方法。可以在继承层次结构的任何级别上声明该方法,并且无论 @Bean方法的返回类型如何,都将检测该方法(即,检测是在创建时针对bean实例自身进行反射性发生的)。要为特定的 @Bean禁用destroy方法推断,请指定一个空字符串作为值,例如 @Bean(destroyMethod =“”)。注意, org.springframework.beans.factory.DisposableBean回调接口仍然会被检测到,并调用相应的destroy方法:换句话说,code destroyMethod =“”仅影响自定义关闭/关闭方法,而 java.io.Closeable/ java.lang.AutoCloseable声明了close方法。
注意:仅在生命周期在工厂的完全控制下的bean上调用,对于单例来说总是这样,但对于任何其他范围都不能保证。
/**
* The optional name of a method to call on the bean instance upon closing the
* application context, for example a {@code close()} method on a JDBC
* {@code DataSource} implementation, or a Hibernate {@code SessionFactory} object.
* The method must have no arguments but may throw any exception.
* <p>As a convenience to the user, the container will attempt to infer a destroy
* method against an object returned from the {@code @Bean} method. For example, given
* an {@code @Bean} method returning an Apache Commons DBCP {@code BasicDataSource},
* the container will notice the {@code close()} method available on that object and
* automatically register it as the {@code destroyMethod}. This \'destroy method
* inference\' is currently limited to detecting only public, no-arg methods named
* \'close\' or \'shutdown\'. The method may be declared at any level of the inheritance
* hierarchy and will be detected regardless of the return type of the {@code @Bean}
* method (i.e., detection occurs reflectively against the bean instance itself at
* creation time).
* <p>To disable destroy method inference for a particular {@code @Bean}, specify an
* empty string as the value, e.g. {@code @Bean(destroyMethod="")}. Note that the
* {@link org.springframework.beans.factory.DisposableBean} callback interface will
* nevertheless get detected and the corresponding destroy method invoked: In other
* words, {@code destroyMethod=""} only affects custom close/shutdown methods and
* {@link java.io.Closeable}/{@link java.lang.AutoCloseable} declared close methods.
* <p>Note: Only invoked on beans whose lifecycle is under the full control of the
* factory, which is always the case for singletons but not guaranteed for any
* other scope.
* @see org.springframework.beans.factory.DisposableBean
* @see org.springframework.context.ConfigurableApplicationContext#close()
*/
String destroyMethod() default AbstractBeanDefinition.INFER_METHOD;
以上是关于@Bean注解详解的主要内容,如果未能解决你的问题,请参考以下文章