Spring 注解@Bean使用方式你都知道吗?
环境:Spring5.3.25
@Bean是方法级注释,是XML <bean/>元素的直接类比。注解支持<bean/>提供的一些属性,例如:
init-methoddestroy-methodautowiringname.
你可以在@Configuration或@Component类中使用@Bean注释。
要声明bean,可以使用@Bean注释对方法进行注释。可以使用此方法在ApplicationContext中注册bean定义,其类型指定为该方法的返回值。默认情况下,bean名与方法名相同。下面的例子展示了一个@Bean方法声明:
@Configuration
public class AppConfig {
@Bean
public TransferServiceImpl transferService() {
return new TransferServiceImpl();
}
}
前面的配置与下面的Spring XML完全等效:
<beans>
<bean id="transferService" class="com.acme.TransferServiceImpl"/>
</beans>
这两个声明都使一个名为transferService的bean在ApplicationContext中可用,绑定到类型为TransferServiceImpl的对象实例,如下图所示:
transferService -> com.acme.TransferServiceImpl
你也可以使用默认方法来定义bean。这允许通过在默认方法上实现带有bean定义的接口来组合bean配置。
public interface BaseConfig {
@Bean
default TransferServiceImpl transferService() {
return new TransferServiceImpl();
}
}
@Configuration
public class AppConfig implements BaseConfig {
}
你还可以用接口(或基类)返回类型声明@Bean方法,如下例所示:
@Configuration
public class AppConfig {
@Bean
public TransferService transferService() {
return new TransferServiceImpl();
}
}
然而,这将高级类型预测的可见性限制为指定的接口类型(TransferService)。然后,只有在实例化了受影响的单例bean之后,容器才知道完整类型(TransferServiceImpl)。非惰性单例bean根据其声明顺序进行实例化,因此你可能会看到不同的类型匹配结果,这取决于另一个组件何时尝试通过非声明类型进行匹配(例如@Autowired TransferServiceImpl,它只在transferServicebean实例化后才解析)。
一个@Bean注释的方法可以有任意数量的参数来描述构建该Bean所需的依赖关系。例如,如果我们的TransferService需要一个AccountRepository,我们可以用一个方法参数来实现该依赖关系,如下例所示:
@Configuration
public class AppConfig {
@Bean
public TransferService transferService(AccountRepository accountRepository) {
return new TransferServiceImpl(accountRepository);
}
}
解析机制与基于构造函数的依赖注入非常相似。
使用@Bean注释定义的任何类都支持常规的生命周期回调,并且可以使用JSR-250中的@PostConstruct和@PreDestroy注释。
也完全支持常规的Spring生命周期回调。如果bean实现InitializingBean、DisposableBean或Lifecycle,那么容器将调用它们各自的方法。
还完全支持一组标准的*Aware接口(如BeanFactoryAware、BeanNameAware、MessageSourceAware、ApplicationContextAware等)。
@Bean注释支持指定任意的初始化和销毁回调方法,就像Spring XML在Bean元素上的init方法和destroy方法属性一样,如下例所示:
public class BeanOne {
public void init() {
// initialization logic
}
}
public class BeanTwo {
public void cleanup() {
// destruction logic
}
}
@Configuration
public class AppConfig {
@Bean(initMethod = "init")
public BeanOne beanOne() {
return new BeanOne();
}
@Bean(destroyMethod = "cleanup")
public BeanTwo beanTwo() {
return new BeanTwo();
}
}
默认情况下,使用Java配置定义的具有公共close或shutdown方法的bean会自动使用销毁回调进行登记。如果你有一个公共的close或shutdown方法,并且不希望在容器关闭时调用它,那么可以将@Bean(destroyMethod="")添加到Bean定义中,以禁用默认(推断)模式。
public class Main {
static class Person {
public void close() {
System.out.println("close") ;
}
public void shutdown() {
System.out.println("shutdown") ;
}
}
@Configuration
static class AppConfig {
@Bean
// @Bean(destroyMethod = "") 这样就禁用了关闭的操作(close和shutdown)
public Person person() {
return new Person() ;
}
}
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class) ;
context.close() ;
}
}
注意:如果一个类中既有close方法又有shutdown方法,那么只有close方法生效。
以前面示例中的BeanOne为例,在构造过程中直接调用init()方法同样有效,如下面的例子所示:
@Configuration
public class AppConfig {
@Bean
public BeanOne beanOne() {
BeanOne beanOne = new BeanOne();
beanOne.init();
return beanOne;
}
}
当你直接在Java中工作时,你可以对对象执行任何你喜欢的操作,而不必总是依赖于容器生命周期。
Spring包含@Scope注释,以便您可以指定bean的范围。
你可以指定使用@Bean注释定义的Bean应该具有特定的作用域。可以使用Bean scopes部分中指定的任何标准作用域。
默认作用域是singleton,但您可以使用@Scope注释来覆盖它,如下例所示:
@Configuration
public class MyConfiguration {
@Bean
@Scope("prototype")
public Encryptor encryptor() {
// ...
}
}
@Scope and scoped-proxy
Spring通过作用域代理提供了一种方便的方式来处理作用域依赖。在使用XML配置时,创建这样一个代理的最简单方法是<aop:scope -proxy/>元素。在Java中配置bean时,使用@Scope注解可以为proxyMode属性提供类似的支持。默认值是ScopedProxyMode.DEFAULT,它通常表示不应该创建scoped proxy,除非在组件扫描指令级别配置了不同的DEFAULT。你可以指定ScopedProxyMode.TARGET_CLASS ScopedProxyMode。接口或ScopedProxyMode.NO。
如果你使用Java将XML参考文档(参见“限定范围的代理”)中的限定范围代理示例移植到我们的@Bean,它类似于以下内容:
// an HTTP Session-scoped bean exposed as a proxy
@Bean
@SessionScope
public UserPreferences userPreferences() {
return new UserPreferences();
}
@Bean
public Service userService() {
UserService service = new SimpleUserService();
// a reference to the proxied userPreferences bean
service.setUserPreferences(userPreferences());
return service;
}
默认情况下,配置类使用@Bean方法的名称作为生成的Bean的名称。但是,可以使用name属性覆盖此功能,如以下示例所示:
@Configuration
public class AppConfig {
@Bean("myThing")
public Thing thing() {
return new Thing();
}
}
正如Naming Beans中所讨论的,有时需要为单个bean提供多个名称,也称为bean别名。@Bean注释的name属性接受用于此目的的String数组。以下示例显示了如何为bean设置多个别名:
@Configuration
public class AppConfig {
@Bean({"dataSource", "subsystemA-dataSource", "subsystemB-dataSource"})
public DataSource dataSource() {
// instantiate, configure and return DataSource bean...
}
}
有时,提供一个bean的更详细的文本描述是有帮助的。当bean被公开(可能是通过JMX)用于监视目的时,这可能特别有用。
要向@Bean添加描述,可以使用@Description注释,如下例所示:
@Configuration
public class AppConfig {
@Bean
@Description("Provides a basic example of a bean")
public Thing thing() {
return new Thing();
}
}
完毕!!!
求关注
SpringBoot对Spring MVC都做了哪些事?(一)
SpringBoot对Spring MVC都做了哪些事?(二)
SpringBoot对Spring MVC都做了哪些事?(三)
SpringBoot对Spring MVC都做了哪些事?(四)
Spring Retry重试框架的应用
spring data jpa 高级应用


商朝恐怖文化 活人祭祀、吃人肉杀婴儿以镇宅
导语:据说商朝人几乎什么都能吃,甚至于某些地方记载商朝人还曾经尝试过吃人肉,考古人员曾经发现了装着婴儿骨骼的陶罐,很可能是商朝人在建房子前杀死婴儿埋葬在地下祭祀,以达到镇宅安居的目的,下面和探秘志一起了解一下商朝的恐怖文化。商朝恐怖文化我要新鲜事2023-05-09 01:45:350003红河的源头在哪里 源自西北山箐(云南大理地带)
红河的源头在西北山箐,这里属于云南大理地带。充满大自然的气息,并且还有一些历史文化的奇异景象。红河是中国比较著名的一条河流,经过若干年这条河一直存在,并且奔腾不息,虽然并不是很清澈,但是周边的景色很美丽,来往的船只也很多。一、红河的特点我要新鲜事2023-05-11 19:46:190000金融危机对普通人生活的影响 老百姓生活会变得怎样
金融危机对于普通人生活有很大的影响,很多影响都是显而易见的,比如说货币购买力缩水了,人们工资减少了,有很多人可能失去工作,资产泡沫也开始破碎,人们也不会花更多精力去享受生活了,生活的各个方面变化都是挺大的。金融危机对普通人生活的影响1.货币购买力缩水我要新鲜事2023-05-12 15:54:210000如何登陆火星 看完整个过程 惊叹科技的神奇(火星基地)
今后人类要想更好的登陆火星,必须要将多项技术整合起来才能实现。尽管我们对火星非常感兴趣,可是人类还没有办法真正的登陆火星,至少以当前的科学技术还做不到。火星登陆我要新鲜事2023-03-22 18:27:330001宇宙间的生命可有多种形式,科学家们为什么只注意到碳基生命呢
关于是否有外星人的疑问,我想差不多都能给我们一个确定的回答。宇宙的大小究竟是多少呢?这一问题,我们都无法确切地解答,只有无可奈何地用“无限”二字来描述。从逻辑上推断,无限大宇宙里,外星人生命形态肯定也会千变万化,它们不一定像我们地球人。我要新鲜事2023-05-14 17:46:230000