目录
2.使用AnnotationConfigApplicationContext初始化Spring容器
基于Java的容器配置
1.基本概念:@Bean与@Configuration
Spring的基于java的配置所支持的核心工件为@Configuration类与@Bean方法。
@Bean注解用于指定一个方法,此方法用于实例化、配置和初始化一个由Spring容器管理的对象。即@Bean注解与xml配置中的<bean>元素作用等价。
@Bean可以与任意@Component使用,不过,常常与@Configuration同时使用。
@Configuration类的主要目的是作为一个bean定义的源。
@Configuration允许内部bean依赖通过简单调用定义在当前类下的@Bean方法进行定义。
@Configuration
public class AppConfig {
@Bean
public Foo foo() {
return new FooImpl();
}
}
<beans>
<bean id="foo" class="examples.FooImpl" />
</beans>
note:以上两种配置等价。
当@Bean方法没有声明在@Configuration类中时,这些方法被认为是在lite模式下运行。即,@Bean方法可以被看作是提供了一种通用的工厂方法机制,没有其他特别的运行时语义。
"lite"@Bean方法不能声明内部bean依赖。由于没有CGLIB子类在运行时生成,所以,当进行类设计时,没有任何限制。(eg:class可以设置为final。)
"full"模式被使用时,交叉方法引用会被重定向到容器生命周期管理。这将会阻止相同@Bean方法被通过常规java调用方式意外调用,从而帮助降低难以发现的bug。
2.使用AnnotationConfigApplicationContext初始化Spring容器
AnnotationConfigApplicationContext除了能够接收@Configuration类作为输入,还可以接受简单@Component类以及被JSR-330注解的类。
当@Configuration类被作为输入提供时,@Configuration类本身也会作为bean定义被注册,并且所有声明其中的@Bean方法都会被作为bean定义注册。
当@Component与JSR-330类被提供时,它们会作为bean定义被注册,DI元数据(@Autowired或@Inject)会在必要的时候被使用。
简单构造
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
}
note:将@Configuration类作为源输入构建的ApplicationContext中。
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(Example.class, Foo.class);
}
note:将多个@Component或JSR-300的注解类作为输入,构建ApplicationContext。
note:这些输入的类使用依赖注入标签。(eg:@Autowired等)
通过编程方式register(Class<?>...)构建容器
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(AppConfig.class, OtherConfig.class);
ctx.register(AdditionalConfig.class);
ctx.refresh();
}
启用组件扫描
@Configuration
@ComponentScan(basePackages = "com.acme")
public class AppConfig {
...
}
note:使用@ComponentScan注解开启组建扫描。
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.scan("com.acme");
ctx.refresh();
}
note:使用AnnotationConfigApplicationContext提供的scan(String...)方法启用组件扫描功能。
ps:@Configuration注解由元注解@Component构成,所以,自动扫描会将@Configuration类作为组建扫描的候选,将其作为容器中的beam定义进行注册。
在web应用中支持AnnotationConfigWebApplicationContext
<web-app>
<!-- Configure ContextLoaderListener to use AnnotationConfigWebApplicationContext
instead of the default XmlWebApplicationContext -->
<context-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</context-param>
<!-- Configuration locations must consist of one or more comma- or space-delimited
fully-qualified @Configuration classes. Fully-qualified packages may also be
specified for component-scanning -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.acme.AppConfig</param-value>
</context-param>
<!-- Bootstrap the root application context as usual using ContextLoaderListener -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Declare a Spring MVC DispatcherServlet as usual -->
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- Configure DispatcherServlet to use AnnotationConfigWebApplicationContext
instead of the default XmlWebApplicationContext -->
<init-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</init-param>
<!-- Again, config locations must consist of one or more comma- or space-delimited
and fully-qualified @Configuration classes -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.acme.web.MvcConfig</param-value>
</init-param>
</servlet>
<!-- map all requests for /app/* to the dispatcher servlet -->
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
</web-app>
note:web.xml配置。
3.使用@Bean注解
@Bean时方法层次注解,与xml的<bean>元素作用类似。
声明一个bean
@Configuration
public class AppConfig {
@Bean
public FooImpl foo() {
return new FooImpl();
}
}
note:声明一个名称为foo,类型为FooImpl的bean。
ps:bean的类型由方法返回值指定。
ps:默认情况下,bean的名称为方法名。
ps:可以将返回值设置为一个接口或base类。
ps:将返回值设置为接口,这会限制对特定接口的类型预测的可见性,即只有当被影响的单例bean实例化时,实际类型才会被容器得知。
ps:非怠惰bean根据声明顺序进行实例化。所以,其他组件试图通过未声明类型进行匹配的时机,将会决定类型匹配的结果。
ps:如果坚持通过已声明的服务接口来引用类型,@Bean返回类型可以安全地参与设计决策。
ps:对于实现多个接口的组件,通过声明最特殊的返回类型可能是安全的。
bean依赖
@Bean方法可以通过任意数量的参数来描述构建bean所必需的依赖。
@Configuration
public class AppConfig {
@Bean
public Example example(Foo foo) {
return new Example(foo);
}
}
note:这种方式注入与基于构造器的注入方式等价。通过参数类型进行bean注入。
接收生命周期回调
@Bean支持指定任意initialization回调方法与destruction回调方法,类似于xml的bean元素的init-method属性与destroy-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();
}
}
默认情况下,由java配置定义的beans会有默认的公共close方法与shutdown方法,这些方法默认作为destruction回调。
可以使用@Bean(destroyMethod="")阻止默认destruction回调执行。
指定bean范围
@Configuration
public class MyConfiguration {
@Bean
@Scope("prototype")
public Encryptor encryptor() {
// ...
}
}
Spring提供了一种方便的方法与范围限定的代理一起执行。
配置通过java中的beans的@Scope注解,提供一个proxyMode属性。
默认情况下,值为ScopeProxyMode.NO(无代理),可以手动指定ScopedProxyMode.TARGET_CLASS或ScopedProxyMode.INTERFACES。
定制bean名称
@Configuration
public class AppConfig{
@Bean(name="myFoo")
public Foo foo() {
return new Foo();
}
}
note:将@Bean默认定义的bean名称(方法名),重载为myFoo。
bean别名
@Configuration
public class AppConfig {
@Bean(name = { "dataSource", "subsystemA-dataSource", "subsystemB-dataSource" })
public DataSource dataSource() {
// instantiate, configure and return DataSource bean...
}
}
bean描述
@Configuration
public class AppConfig {
@Bean
@Description("Provides a basic example of a bean")
public Foo foo() {
return new Foo();
}
}