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