首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Spring框架@Bean注解源码分析和应用举例

在Spring框架中,有一个注解与众不同。

同样是声明bean实例,@Component、@Controller等注解是用在类上的,在Spring容器里完成实例化的。

而这个注解是用在方法上,在方法里由用户完成对象的实例化,最后交给Spring容器管理。而且这个注解还不能单独使用,和@Configuration搭配使用频率最高,它就是@Bean注解。

一、@Bean简介

@Bean是Spring框架 3.0 版本的一个注解,用于标识一个方法,该方法将返回一个由 Spring 管理的 Bean 对象。同时,被@Bean注解的方法只会被Spring容器识别一次。

在配置类中,通过在方法上标注 @Bean 注解,Spring 容器会在运行时调用该方法,并将方法返回的对象注册为一个 Bean。

通过 @Bean 注解,可以将自定义的对象纳入到 Spring 容器的管理范围内,从而可以享受 Spring 提供的依赖注入、AOP 等功能。

一般情况下,@Bean 注解可以与 @Configuration 注解一起使用,将一个类标识为配置类,并在该类中声明需要被 Spring 管理的 Bean 对象的创建方法。这些方法可以包含业务逻辑来创建 Bean 实例,并可以设置其属性、依赖关系等。

例如:

@Configurationpublic class AppConfig { @Bean public MyService myService() { return new MyServiceImpl(); } // 其他@Bean方法...}

在上面的示例中,myService() 方法使用 @Bean 注解标注,Spring 容器会调用该方法并将其返回的 MyService 对象注册为一个 Bean。

二、@Bean的源码解读

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface Bean {

/** * bean的名称,可以指定多个别名,默认为被注解的方法名(方法名首字母小写) */ @AliasFor("name") String[] value() default {};

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

/** * 是否自动装配,默认false,从5.1版本这个字段就作废 * @deprecated as of 5.1 */ @Deprecated Autowire autowire() default Autowire.NO;

/** * * @since 5.1 */ boolean autowireCandidate() default true;

/** * 初始化方法 * @see org.springframework.beans.factory.InitializingBean * @see org.springframework.context.ConfigurableApplicationContext#refresh() */ String initMethod() default "";

/** * 销毁方法 * @see org.springframework.beans.factory.DisposableBean * @see org.springframework.context.ConfigurableApplicationContext#close() */ String destroyMethod() default AbstractBeanDefinition.INFER_METHOD;

}

value:bean名称,可以指定多个,默认为注解的方法名称;

name:bean名称,同value;

autowire:自定装配默认不开启,在5.1版本作废;

initMethod:bean的初始化方法;作用同InitializingBean接口的afterPropertiesSet 方法。

destroyMethod:默认使用 javaConfig 配置的bean,如果存在 close 或者 shutdown 方法,则在 bean 销毁时会自动执行该方法,如果不想执行该方法,则不要在对象中定义close 或者 shutdown 方法,或者将该值设置为空。

@Bean注解可以注解在方法上,也可以注解在其他注解上,其他注解也必须在方法上。

三、@Bean注解的应用

1、创建一个对象MyBean备用

2、在配置文件中配置bean,3种方式

/** * 在配置文件中配置bean,3种方式 * @author * @date 2024年4月19日 * @Description * */@Configurationclass MyConfig{ // 1、创建一个以方法命令的bean @Bean public MyBean myBean() { return new MyBean(); } // 2、创建一个有别名的bean @Bean(name={"b1","b2"},autowireCandidate=false) public MyBean myBean1() { return new MyBean(); } // 3、bean注解的完整使用 @Bean(value={"b3","b4"},autowireCandidate=false,initMethod="init",destroyMethod="close") public MyBean myBean2() { return new MyBean(); }}

3、测试代码

import org.springframework.context.annotation.AnnotationConfigApplicationContext;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;/** * @Bean使用测试代码*/public class SpringApp2 { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class); // 1、通过class获取bean实例 MyBean myBean = context.getBean(MyBean.class); System.out.println("myBean:" + myBean); // 2、通过别名获取bean实例 myBean = (MyBean) context.getBean("b1"); System.out.println("b1:" + myBean); myBean = (MyBean) context.getBean("b2"); System.out.println("b2:" + myBean); // 3、完整@Bean注解的应用 myBean = (MyBean) context.getBean("b3"); System.out.println("b3:" + myBean); myBean = (MyBean) context.getBean("b4"); System.out.println("b4:" + myBean); myBean.fun(); // 关闭上下文,调用销毁方法 context.close(); }}

在上面的示例中,我们使用三种方式创建同一个对象的bean。

第一种bean的名称默认,也就是使用方法名作为bean的名称。

第二种,给bean起两个别名b1,b2。

第三种,给bean起两个别名b3,b4,并且把bean中的属性都设置了一遍。

4、运行结果

执行结果,和网上有些文章里写的不一样。

也就是第二种方式中,很多文章里都说这个bean有三个名称:b1、b2和方法名,但实际上只有两个指定的bean名称,两个名称指向同一个实例。因此只要设置了name或value,就会覆盖默认的方法名作为bean的名称。

最后容器关闭时,销毁方法被调用了三次,因为前面配置了三个bean。

当然除此之外,@Bean还可以和Scope、DependsOn、Lazy、Primary等搭配使用,这里就不演示了。

  • 发表于:
  • 原文链接https://page.om.qq.com/page/O8AzNb-5hHJ8tvk96qAAfgow0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券