Spring @Bean注解的使用场景与案例实现
作者:Super_Leng
一、简单介绍
翻看Spring的源码时,发现@Bean注解的源码上标注了Since: 3.0,也就是说,@Bean注解是Spring从3.0版本开始提供的源码。@Bean注解可以标注在方法上,将当前方法的返回值注入到IOC容器中,也可以标注到注解上,作为元注解使用。
二、注解说明
@Bean注解可以说是使用Spring开发应用程序时,使用的比较多的一个注解,尤其是基于SpringBoot开发应用程序时,@Bean注解使用的就很多了。@Bean注解可以标注到方法上,将当前方法的返回值注入到IOC容器中。@Bean注解也可以标注到注解上,作为元注解使用。
1. 注解源码
/** * @author Rod Johnson * @author Costin Leau * @author Chris Beams * @author Juergen Hoeller * @author Sam Brannen * @since 3.0 */ @Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Bean { //Since: 4.3.3 @AliasFor("name") String[] value() default {}; @AliasFor("value") String[] name() default {}; //Since: 5.1 boolean autowireCandidate() default true; String initMethod() default ""; String destroyMethod() default AbstractBeanDefinition.INFER_METHOD; }
从@Bean源码的注释可以看出,@Bean注解是Spring从3.0版本开始提供的注解,注解中各个属性的含义如下所示:
- name:String[]数组类型,指定注入到IOC容器中的Bean的名称,可以指定多个名称。如果不指定name属性和value属性的值,则注入到IOC容器中的Bean的名称默认是方法的名称。
- value:String[]数组类型,从Spring 4.3.3版本开始提供的@Bean的属性,作用与name属性相同。
- autowireCandidate:boolean类型,表示是否支持自动按照类型注入到其他的Bean中。此属性会影响@Autowired注解,不会响应@Resource注解,默认为true,表示支持自动按照类型注入到其他的Bean中。
- initMethod:指定初始化的方法。
- destroyMethod:指定销毁的方法。
2. 注解使用场景
在使用Spring的注解开发应用程序时,如果是我们自己开发的类,可以在类上标注@Component注解(也可以是@Repository、@Service、@Controller等注解),将类注入到IOC容器中。但是,有时很多类不是我们自己写的,而是依赖的第三方的类库,此时就无法在类上标注@Component等注解了,此时就需要使用@Bean注解将其注入到IOC容器中。
也就是说,@Bean注解适用于将第三方提供的类注入到IOC容器中的场景。使用@Bean注解创建的Bean对象默认是单实例Bean对象。
三、使用案例
1. 案例描述
使用@Bean注解将User类的对象注入到IOC容器中,打印初始化和销毁方法,并验证使用@Bean注解创建的Bean对象默认是单实例Bean。
2. 案例实现
使用@Bean注解可以将类对象注入到IOC容器中,并且@Bean注解的initMethod属性可以指定初始化的方法,destroyMethod属性可以指定销毁的方法。当IOC容器对Bean对象进行初始化时,会执行@Bean注解的initMethod属性指定的方法,当IOC容器在关闭时,会执行@Bean注解的destroyMethod属性指定的方法,触发销毁方法的逻辑。
注意:上述逻辑仅限于注入到IOC容器中的单例Bean对象。如果是单实例Bean,则IOC容器启动时,就会创建Bean对象,IOC容器关闭时,销毁Bean对象。如果是多实例Bean,IOC容器在启动时,不会创建Bean对象,在每次从IOC容器中获取Bean对象时,都会创建新的Bean对象返回,IOC容器关闭时,也不会销毁对象。也就是说,如果是多实例Bean,IOC容器不会管理Bean对象。
本节,就以单实例Bean为例来实现案例程序,具体的实现步骤如下所示:
新建注入到IOC容器中的User类
public class User { private final Logger logger = LoggerFactory.getLogger(User.class); public User(){ logger.info("执行构造方法..."); } public void init(){ logger.info("执行初始化方法..."); } public void destroy(){ logger.info("执行销毁方法..."); } }
IOC容器启动时,会创建User类的对象并调用init()方法进行初始化。IOC容器关闭时,会销毁User类的对象,并调用destroy()方法执行销毁逻辑。
可以看到,User类的实现比较简单,提供了一个无参构造方法,一个表示初始化的init()方法和一个表示销毁的destroy()方法,每个方法中都打印了相应的日志来说明调用了对应的方法。
创建Spring的配置类BeanConfig
@Configuration @ComponentScan(basePackages = "com.lwk.demo.spring.annocation.bean") public class BeanConfig { @Bean(initMethod = "init", destroyMethod = "destroy") public User user(){ return new User(); } }
可以看到,在BeanConfig类上标注了@Configuration注解,说明BeanConfig类是一个Spring的配置类,并且在BeanConfig类上标注了@ComponentScan注解,指定要扫描的包为com.lwk.demo.spring.annocation.bean。
在BeanConfig类中定义了一个user()方法,返回一个User对象。在user()方法上标注了@Bean注解,并通过initMethod属性指定的初始化方法为User类的init()方法,通过destroyMethod属性指定的销毁方法为User类的destroy()方法。
创建案例测试类BeanTest
public class BeanTest { private static final Logger LOGGER = LoggerFactory.getLogger(BeanTest.class); public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanConfig.class); LOGGER.info("IOC容器启动完成...."); User user1 = context.getBean(User.class); User user2 = context.getBean(User.class); LOGGER.info("user1是否等于user2===>>>{}", (user1 == user2)); context.close(); } }
可以看到,在BeanTest类中,通过BeanConfig配置类创建了IOC容器,从IOC容器中两次获取User对象,分别赋值给user1和user2,打印user1是否等于user2的日志,并关闭IOC容器。
3. 案例测试
运行BeanTest类的main()方法,输出的日志信息如下所示:
15:56:57.404 [main] INFO com.lwk.demo.spring.annocation.bean.entity.User - 执行构造方法...
15:56:57.405 [main] INFO com.lwk.demo.spring.annocation.bean.entity.User - 执行初始化方法...
15:56:57.431 [main] INFO com.lwk.demo.spring.annocation.bean.BeanTest - IOC容器启动完成....
15:56:57.432 [main] INFO com.lwk.demo.spring.annocation.bean.BeanTest - user1是否等于user2===>>>true
15:56:57.437 [main] DEBUG org.springframework.context.annotation.AnnotationConfigApplicationContext - Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@41975e01, started on Thu Mar 09 15:56:57 CST 2023
15:56:57.438 [main] INFO com.lwk.demo.spring.annocation.bean.entity.User - 执行销毁方法...
可以看到,IOC容器在启动时,就创建了User对象,并调用了@Bean注解的initMethod方法指定的初始化方法,IOC容器在关闭时,调用@Bean注解的destroyMethod属性指定的销毁方法。并且通过打印的user1是否等于user2的日志为true,可以说明使用@Bean注解默认创建的Bean对象是单实例Bean,每个类在IOC容器中只会存在一个单实例Bean对象。
到此这篇关于Spring @Bean注解的使用场景与案例实现的文章就介绍到这了,更多相关Spring @Bean注解内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!