@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子类化。
@Configurationpublic 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会拦挡调用。如下
@Componentpublic 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 */@DeprecatedAutowire 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;