Skip to content

Latest commit

 

History

History
239 lines (158 loc) · 8.18 KB

File metadata and controls

239 lines (158 loc) · 8.18 KB

3.12.3  使用@Bean注解

@Bean是一个方法级的注解,它与XML中的类似。 注解支持<bean/>提供的一些属性,例如:init-methoddestroy-methodautowiringname

可以在@Configuration或@Component注解的类中使用@Bean注解。

声明bean

要声明一个bean,只需使用@Bean注解一个方法。使用此方法,将会在ApplicationContext内注册一个bean,bean的类型是方法的返回值类型。 默认情况下,bean名称将与方法名称相同。 下面是一个简单的例子:@Bean方法声明:

@Configuration
public class AppConfig {

	@Bean
	public TransferService transferService() {
		return new TransferServiceImpl();
	}

}

上面的配置完全等同于以下Spring XML:

<beans>
	<bean id="transferService" class="com.acme.TransferServiceImpl"/>
</beans>

两种方式都定义了一个名字为transferService的bean,且绑定了TransferServiceImpl的实例:

transferService -> com.acme.TransferServiceImpl

Bean之间的依赖

一个@Bean注解的方法可以有任意数量的参数描述构建该bean所需的依赖。 例如,如果我们的TransferService需要一个AccountRepository,我们可以通过一个方法参数来实现该依赖:

@Configuration
public class AppConfig {

	@Bean
	public TransferService transferService(AccountRepository accountRepository) {
		return new TransferServiceImpl(accountRepository);
	}

}

解析机制与基于构造函数的依赖注入非常相似,参见相关部分 。

接收生命周期回调

使用@Bean注解定义的任何类都支持常规的生命周期回调,并且可以使用JSR-250的@PostConstruct@PreDestroy注解,参见JSR-250注解 。

完全支持常规Spring lifecycle回调。如果bean实现了InitializingBean, DisposableBean, or Lifecycle,它们各自的方法由容器调用。

同样地,标准的*Aware接口,如 BeanFactoryAwareBeanNameAwareMessageSourceAwareApplicationContextAware等等都完全支持。

@Bean注解支持指定任意初始化和销毁回调方法,就像Spring XML的bean元素的init-methoddestroy-method属性:

public class Foo {
	public void init() {
		// initialization logic
	}
}

public class Bar {
	public void cleanup() {
		// destruction logic
	}
}

@Configuration
public class AppConfig {

	@Bean(initMethod = "init")
	public Foo foo() {
		return new Foo();
	}

	@Bean(destroyMethod = "cleanup")
	public Bar bar() {
		return new Bar();
	}

}

[Note]

默认情况下,使用java config定义的bean中close方法或者shutdown方法,会作为销毁回调自动调用。
若bean中有close,shutdown方法,又不是销毁回调,通过设置@Bean(destroyMethod=""),即可关闭该默认的自动匹配销毁回调模式。
你可能希望对通过JNDI获取的资源执行此操作,因为它的生命周期是在应用程序外部管理的。尤其是,使用DataSource时一定要关闭它,不关会有问题。

@Bean(destroyMethod="")
public DataSource dataSource() throws NamingException {
	return (DataSource) jndiTemplate.lookup("MyDS");
}

同样地,,使用@Bean方法,通常会选择使用程序化的JNDI查找:使用Spring的JndiTemplate /JndiLocatorDelegate帮助类或直接使用JNDI的InitialContext但是不要使用JndiObjectFactoryBean变体,因为它会强制你去声明一个返回类型作为FactoryBean的类型代替实际的目标类型,这会使得交叉引用变得很困难。

当然,上面Foo的例子中,也可以在构造函数中调用init()方法,和上面例子中的效果相同;

@Configuration
public class AppConfig {
	@Bean
	public Foo foo() {
		Foo foo = new Foo();
		foo.init();
	    return foo;
	}

	// ...

}
[Tip]
如果是直接使用java,对于对象,你想怎么搞就怎么搞,并不总需要依赖容器生命周期!

指定bean的作用域

使用@Scope注解

可以使用任何标准的方式为@Bean注解的bean指定一个作用域。 你可以使用Bean Scopes章节中的任意标准作用域。

默认范围是singleton,但是你可以使用@Scope注解来覆盖它:

@Configuration
public class MyConfiguration {

	@Bean
	@Scope("prototype")
	public Encryptor encryptor() {
		// ...
	}

}
@Scope 和作用域代理

Spring通过scoped代理提供了一种方便的方式完成作用域bean依赖关系。 在使用XML配置时创建这种代理的最简单的方法是<aop:scoped-proxy/>元素。 若是在Java代码中配置bean,有一种等价的做法,使用@Scope注解并配置其proxyMOde属性. 默认是没有代理(ScopedProxyMode.NO),但你可以指定ScopedProxyMode.TARGET_CLASSScopedProxyMode.INTERFACES

如果将XML格式的作用域代理示例转换成Java中使用@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的方法名作为返回bean的名字。 但是,使用name属性可以覆盖此功能。

@Configuration
public class AppConfig {

	@Bean(name = "myFoo")
	public Foo foo() {
		return new Foo();
	}

}

bean别名

第3.3.1节“命名bean”中所讨论的有时候需要给一个bean指定多个name。@Bean注解的name属性就是干这个用的,该属性接收一个字串数组。

@Configuration
public class AppConfig {

	@Bean(name = { "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 Foo foo() {
		return new Foo();
	}

}