zoukankan      html  css  js  c++  java
  • spring-context中@Bean的源码解析说明和它与其他注解的结合使用

    spring版本为5.0.11

    Spring的@Bean注解用于告诉方法,产生一个Bean对象,然后这个Bean对象交给Spring管理。产生这个Bean对象的方法Spring只会调用一次,随后这个Spring将会将这个Bean对象放在自己的IOC容器中。

    @Bean可以和其他注解结合使用,比如@profile,@scope,@lazy,@depends-on @primary等注解

    @Bean的源码解析

    /**
     * Indicates that a method produces a bean to be managed by the Spring container.
     *
     * <h3>Overview</h3>
     *
     * <p>The names and semantics of the attributes to this annotation are intentionally
     * similar to those of the {@code <bean/>} element in the Spring XML schema. For
     * example:
     *
     * <pre class="code">
     *     &#064;Bean
     *     public MyBean myBean() {
     *         // instantiate and configure MyBean obj
     *         return obj;
     *     }
     * </pre>
     *
     * <h3>Bean Names</h3>
     *
     * <p>While a {@link #name} attribute is available, the default strategy for
     * determining the name of a bean is to use the name of the {@code @Bean} method.
     * This is convenient and intuitive, but if explicit naming is desired, the
     * {@code name} attribute (or its alias {@code value}) may be used. Also note
     * that {@code name} accepts an array of Strings, allowing for multiple names
     * (i.e. a primary bean name plus one or more aliases) for a single bean.
     *
     * <pre class="code">
     *     &#064;Bean({"b1", "b2"}) // bean available as 'b1' and 'b2', but not 'myBean'
     *     public MyBean myBean() {
     *         // instantiate and configure MyBean obj
     *         return obj;
     *     }
     * </pre>
     *
     * <h3>Profile, Scope, Lazy, DependsOn, Primary, Order</h3>
     *
     * <p>Note that the {@code @Bean} annotation does not provide attributes for profile,
     * scope, lazy, depends-on or primary. Rather, it should be used in conjunction with
     * {@link Scope @Scope}, {@link Lazy @Lazy}, {@link DependsOn @DependsOn} and
     * {@link Primary @Primary} annotations to declare those semantics. For example:
     *
     * <pre class="code">
     *     &#064;Bean
     *     &#064;Profile("production")
     *     &#064;Scope("prototype")
     *     public MyBean myBean() {
     *         // instantiate and configure MyBean obj
     *         return obj;
     *     }
     * </pre>
     *
     * The semantics of the above-mentioned annotations match their use at the component
     * class level: {@code @Profile} allows for selective inclusion of certain beans.
     * {@code @Scope} changes the bean's scope from singleton to the specified scope.
     * {@code @Lazy} only has an actual effect in case of the default singleton scope.
     * {@code @DependsOn} enforces the creation of specific other beans before this
     * bean will be created, in addition to any dependencies that the bean expressed
     * through direct references, which is typically helpful for singleton startup.
     * {@code @Primary} is a mechanism to resolve ambiguity at the injection point level
     * if a single target component needs to be injected but several beans match by type.
     *
     * <p>Additionally, {@code @Bean} methods may also declare qualifier annotations
     * and {@link org.springframework.core.annotation.Order @Order} values, to be
     * taken into account during injection point resolution just like corresponding
     * annotations on the corresponding component classes but potentially being very
     * individual per bean definition (in case of multiple definitions with the same
     * bean class). Qualifiers narrow the set of candidates after the initial type match;
     * order values determine the order of resolved elements in case of collection
     * injection points (with several target beans matching by type and qualifier).
     *
     * <p><b>NOTE:</b> {@code @Order} values may influence priorities at injection points,
     * but please be aware that they do not influence singleton startup order which is an
     * orthogonal concern determined by dependency relationships and {@code @DependsOn}
     * declarations as mentioned above. Also, {@link javax.annotation.Priority} is not
     * available at this level since it cannot be declared on methods; its semantics can
     * be modeled through {@code @Order} values in combination with {@code @Primary} on
     * a single bean per type.
     *
     * <h3>{@code @Bean} Methods in {@code @Configuration} Classes</h3>
     *
     * <p>Typically, {@code @Bean} methods are declared within {@code @Configuration}
     * classes. In this case, bean methods may reference other {@code @Bean} methods in the
     * same class by calling them <i>directly</i>. This ensures that references between beans
     * are strongly typed and navigable. Such so-called <em>'inter-bean references'</em> are
     * guaranteed to respect scoping and AOP semantics, just like {@code getBean()} lookups
     * would. These are the semantics known from the original 'Spring JavaConfig' project
     * which require CGLIB subclassing of each such configuration class at runtime. As a
     * consequence, {@code @Configuration} classes and their factory methods must not be
     * marked as final or private in this mode. For example:
     *
     * <pre class="code">
     * &#064;Configuration
     * public class AppConfig {
     *
     *     &#064;Bean
     *     public FooService fooService() {
     *         return new FooService(fooRepository());
     *     }
     *
     *     &#064;Bean
     *     public FooRepository fooRepository() {
     *         return new JdbcFooRepository(dataSource());
     *     }
     *
     *     // ...
     * }</pre>
     *
     * <h3>{@code @Bean} <em>Lite</em> Mode</h3>
     *
     * <p>{@code @Bean} methods may also be declared within classes that are <em>not</em>
     * annotated with {@code @Configuration}. For example, bean methods may be declared
     * in a {@code @Component} class or even in a <em>plain old class</em>. In such cases,
     * a {@code @Bean} method will get processed in a so-called <em>'lite'</em> mode.
     *
     * <p>Bean methods in <em>lite</em> mode will be treated as plain <em>factory
     * methods</em> by the container (similar to {@code factory-method} declarations
     * in XML), with scoping and lifecycle callbacks properly applied. The containing
     * class remains unmodified in this case, and there are no unusual constraints for
     * the containing class or the factory methods.
     *
     * <p>In contrast to the semantics for bean methods in {@code @Configuration} classes,
     * <em>'inter-bean references'</em> are not supported in <em>lite</em> mode. Instead,
     * when one {@code @Bean}-method invokes another {@code @Bean}-method in <em>lite</em>
     * mode, the invocation is a standard Java method invocation; Spring does not intercept
     * the invocation via a CGLIB proxy. This is analogous to inter-{@code @Transactional}
     * method calls where in proxy mode, Spring does not intercept the invocation &mdash;
     * Spring does so only in AspectJ mode.
     *
     * <p>For example:
     *
     * <pre class="code">
     * &#064;Component
     * public class Calculator {
     *     public int sum(int a, int b) {
     *         return a+b;
     *     }
     *
     *     &#064;Bean
     *     public MyBean myBean() {
     *         return new MyBean();
     *     }
     * }</pre>
     *
     * <h3>Bootstrapping</h3>
     *
     * <p>See the @{@link Configuration} javadoc for further details including how to bootstrap
     * the container using {@link AnnotationConfigApplicationContext} and friends.
     *
     * <h3>{@code BeanFactoryPostProcessor}-returning {@code @Bean} methods</h3>
     *
     * <p>Special consideration must be taken for {@code @Bean} methods that return Spring
     * {@link org.springframework.beans.factory.config.BeanFactoryPostProcessor BeanFactoryPostProcessor}
     * ({@code BFPP}) types. Because {@code BFPP} objects must be instantiated very early in the
     * container lifecycle, they can interfere with processing of annotations such as {@code @Autowired},
     * {@code @Value}, and {@code @PostConstruct} within {@code @Configuration} classes. To avoid these
     * lifecycle issues, mark {@code BFPP}-returning {@code @Bean} methods as {@code static}. For example:
     *
     * <pre class="code">
     *     &#064;Bean
     *     public static PropertySourcesPlaceholderConfigurer pspc() {
     *         // instantiate, configure and return pspc ...
     *     }
     * </pre>
     *
     * By marking this method as {@code static}, it can be invoked without causing instantiation of its
     * declaring {@code @Configuration} class, thus avoiding the above-mentioned lifecycle conflicts.
     * Note however that {@code static} {@code @Bean} methods will not be enhanced for scoping and AOP
     * semantics as mentioned above. This works out in {@code BFPP} cases, as they are not typically
     * referenced by other {@code @Bean} methods. As a reminder, a WARN-level log message will be
     * issued for any non-static {@code @Bean} methods having a return type assignable to
     * {@code BeanFactoryPostProcessor}.
     *
     * @author Rod Johnson
     * @author Costin Leau
     * @author Chris Beams
     * @author Juergen Hoeller
     * @author Sam Brannen
     * @since 3.0
     * @see Configuration
     * @see Scope
     * @see DependsOn
     * @see Lazy
     * @see Primary
     * @see org.springframework.stereotype.Component
     * @see org.springframework.beans.factory.annotation.Autowired
     * @see org.springframework.beans.factory.annotation.Value
     */
    @Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})//可以标注在方法上、注解类上
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Bean {
    
        /**
         * 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 {};
    
        /**
         * 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 {};
    
        /**
         * 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;
    
        /**
         * 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;
    
        /**
         * 可选择的方法在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()
         */
        String initMethod() default "";
    
        /**
         * 方法的可选择名称在调用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;
    
    }

    1.@Bean和@Profile

    https://www.cnblogs.com/mufeng07/p/12202037.html

    @Profile指定特定环境和@Bean结合,bean只有这个环境被激活的时候才能注册到容器中。默认是default环境

    2.@Bean和@Scope 注解

    在Spring中对于bean的默认处理都是单例的

    Spring还为我们定义了其他情况:

    ScopeDescriptionn
    singleton 默认单例的bean定义信息,对于每个IOC容器来说都是单例对象
    prototype bean对象的定义为任意数量的对象实例
    request bean对象的定义为一次HTTP请求的生命周期,也就是说,每个HTTP请求都有自己的bean实例,它是在单个bean定义的后面创建的。仅仅在web-aware的上下文中有效
    session bean对象的定义为一次HTTP会话的生命周期。仅仅在web-aware的上下文中有效
    application bean对象的定义范围在ServletContext生命周期内。仅仅在web-aware的上下文中有效
    websocket bean对象的定义为WebSocket的生命周期内。仅仅在web-aware的上下文中有效

    singleton和prototype 一般都用在普通的Java项目中,而request、session、application、websocket都用于web应用中。

    3.@Bean和@Lazy

    表明一个bean 是否延迟加载,可以作用在方法上,表示这个方法被延迟加载;可以作用在@Component (或者由@Component 作为原注解) 注释的类上,表明这个类中所有的bean 都被延迟加载。如果没有@Lazy注释,或者@Lazy 被设置为false,那么该bean 就会急切渴望被加载;除了上面两种作用域,@Lazy 还可以作用在@Autowired和@Inject注释的属性上,在这种情况下,它将为该字段创建一个惰性代理,作为使用ObjectFactory或Provider的默认方法。

    4.@Bean和@DependsOn

    指当前bean所依赖的bean。任何指定的bean都能保证在此bean创建之前由IOC容器创建。在bean没有通过属性或构造函数参数显式依赖于另一个bean的情况下很少使用,可能直接使用在任何直接或者间接使用 Component 或者Bean 注解表明的类上。

    5.@Bean和@Primary

    指示当多个候选者有资格自动装配依赖项时,应优先考虑bean。此注解在语义上就等同于在Spring XML中定义的bean 元素的primary属性。注意: 除非使用component-scanning进行组件扫描,否则在类级别上使用@Primary不会有作用。如果@Primary 注解定义在XML中,那么@Primary 的注解元注解就会忽略,相反使用

    @Primary 的两种使用方式

    • 与@Bean 一起使用,定义在方法上,方法级别的注解
    • 与@Component 一起使用,定义在类上,类级别的注解
  • 相关阅读:
    【XSY2720】区间第k小 整体二分 可持久化线段树
    【XSY2719】prime 莫比乌斯反演
    【XSY2718】gift 分数规划 网络流
    【CTSC2017】【BZOJ4903】吉夫特 卢卡斯定理 DP
    【XSY2729】欧拉子图 无向图连通性 数学
    【XSY2730】Ball 多项式exp 多项式ln 多项式开根 常系数线性递推 DP
    【BZOJ1999】【NOIP2007】树网的核 单调队列优化DP
    NOIP2017游记
    【BZOJ2127】happiness 网络流
    【BZOJ3625】【CF438E】小朋友和二叉树 NTT 生成函数 多项式开根 多项式求逆
  • 原文地址:https://www.cnblogs.com/mufeng07/p/12201961.html
Copyright © 2011-2022 走看看