从Spring3.0,@Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器。
注意:@Configuration注解的配置类有如下要求:
目录
一、用@Configuration加载Spring
1.1、@Configuration配置spring并启动spring容器
1.2、@Configuration启动容器+@Bean注册Bean,@Bean下管理bean的生命周期
1.3、@Configuration启动容器+@Component注册Bean
1.4、使用 AnnotationConfigApplicationContext 注册 AppContext 类的两种方法
1.5、配置Web应用程序(web.xml中配置AnnotationConfigApplicationContext)
1.6、@Configuation总结
二、组合多个配置类
2.1、在@configuration中引入spring的xml配置文件
2.2、在@configuration中引入其它注解配置
2.3、@configuration嵌套(嵌套的Configuration必须是静态类)
@Configuration标注在类上,相当于把该类作为spring的xml配置文件中的
,作用为:配置spring容器(应用上下文)
package com.example.test.configuration;
import org.springframework.context.annotation.Configuration;
@Configuration
public class TestConfiguration {
public TestConfiguration(){
System.out.println("TestConfiguration 容器启动初始化了。。。");
}
}
测试:
package com.example.test.configuration;
import org.springframework.context.annotation.Configuration;
@Configuration
public class TestConfiguration {
public TestConfiguration(){
System.out.println("TestConfiguration 容器启动初始化了。。。");
}
}
从运行主方法结果可以看出,spring容器已经启动了:
@Bean标注在方法上(返回某个实例的方法),等价于spring的xml配置文件中的
,作用为:注册bean对象
bean类:
package com.example.test.configuration;
public class TestBean {
private String userName;
private String url;
private String password;
public void sayHello(){
System.out.println("TestBean sayHello...");
}
public void start(){
System.out.println("TestBean 初始化。。。");
}
public void cleanUp(){
System.out.println("TestBean 销毁。。。");
}
}
配置类:
package com.example.test.configuration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
@Configuration
public class TestConfiguration {
public TestConfiguration(){
System.out.println("TestConfiguration 容器启动初始化了。。。");
}
//@Bean注解注册bean,同时可以指定初始化和销毁方法
@Bean(name = "testBean",initMethod = "start",destroyMethod = "cleanUp")
@Scope("prototype")
public TestBean testBean(){
return new TestBean();
}
}
测试:
package com.example.test.configuration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestRun {
public static void main(String[] args) throws InterruptedException {
//如果加载 spring-context.xml文件:
//ApplicationContext context=new ClassPathXmlApplicationContext("spring-context.xml");
//@Configuration 注解的spring容器加载方式,用AnnotationConfigApplicationContext替换ClassPathApplicationContext
ApplicationContext context=new AnnotationConfigApplicationContext(TestConfiguration.class);
//获取Bean
TestBean tb= (TestBean) context.getBean("testBean");
tb.sayHello();
System.out.println(tb);
TestBean tb2= (TestBean) context.getBean("testBean");
tb2.sayHello();
System.out.println(tb2);
}
}
结果:
注:
(1)、@Bean注解在返回实例的方法上,如果未通过@Bean指定bean的名称,则默认与标注的方法名相同;
(2)、@Bean注解默认作用域为单例singleton作用域,可通过@Scope(“prototype”)设置为原型作用域;
(3)、既然@Bean的作用是注册bean对象,那么完全可以使用@Component、@Controller、@Service、@Ripository等注解注册bean,当然需要配置@ComponentScan注解进行自动扫描。
@Bean下管理bean的生命周期
可以使用基于 Java 的配置来管理 bean 的生命周期。@Bean
支持两种属性,即 initMethod
和destroyMethod
,这些属性可用于定义生命周期方法。在实例化 bean 或即将销毁它时,容器便可调用生命周期方法。生命周期方法也称为回调方法,因为它将由容器调用。使用 @Bean
注释注册的 bean 也支持 JSR-250 规定的标准 @PostConstruct
和 @PreDestroy
注释。
Bean类:
package com.example.test.configuration;
import org.springframework.stereotype.Component;
//增加注册bean的注解
@Component
public class TestBean {
private String userName;
private String url;
private String password;
public void sayHello(){
System.out.println("TestBean sayHello...");
}
public void start(){
System.out.println("TestBean 初始化。。。");
}
public void cleanUp(){
System.out.println("TestBean 销毁。。。");
}
}
配置类:
package com.example.test.configuration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = "com.example.test.configuration")
public class TestConfiguration {
public TestConfiguration(){
System.out.println("TestConfiguration 容器启动初始化了。。。");
}
}
测试:
package com.example.test.configuration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = "com.example.test.configuration")
public class TestConfiguration {
public TestConfiguration(){
System.out.println("TestConfiguration 容器启动初始化了。。。");
}
}
sayHello()方法都被正常调用:
1.4.1、 配置类的注册方式是将其传递给 AnnotationConfigApplicationContext
构造函数
package com.example.test.configuration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class TestRun {
public static void main(String[] args) throws InterruptedException {
//@Configuration 注解的spring容器加载方式,用AnnotationConfigApplicationContext替换ClassPathApplicationContext
ApplicationContext context=new AnnotationConfigApplicationContext(TestConfiguration.class);
TestBean tb = (TestBean) context.getBean("testBean");
tb.sayHello();
}
}
1.4.2、 AnnotationConfigApplicationContext 的register 方法传入配置类来注册配置类
package com.example.test.configuration;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class TestRun {
public static void main(String[] args){
AnnotationConfigApplicationContext ctx=new AnnotationConfigApplicationContext();
ctx.register(TestConfiguration.class);
ctx.refresh();
TestBean tb = (TestBean) ctx.getBean("testBean");
tb.sayHello();
}
}
过去,您通常要利用 XmlWebApplicationContext 上下文来配置 Spring Web 应用程序,即在 Web 部署描述符文件 web.xml 中指定外部 XML 上下文文件的路径。XMLWebApplicationContext 是 Web 应用程序使用的默认上下文类。以下代码描述了 web.xml 中指向将由 ContextLoaderListener 监听器类载入的外部 XML 上下文文件的元素。
contextConfigLocation
/WEB-INF/applicationContext.xml
org.springframework.web.context.ContextLoaderListener
sampleServlet
org.springframework.web.servlet.DispatcherServlet
...
现在,您要将 web.xml 中的上述代码更改为使用 AnnotationConfigApplicationContext 类。切记,XmlWebApplicationContext 是 Spring 为 Web 应用程序使用的默认上下文实现,因此您永远不必在您的web.xml 文件中显式指定这个上下文类。现在,您将使用基于 Java 的配置,因此在配置 Web 应用程序时,需要在web.xml 文件中指定 AnnotationConfigApplicationContext 类。上述代码将修改如下:
contextClass
org.springframework.web.context.
support.AnnotationConfigWebApplicationContext
contextConfigLocation
demo.AppContext
org.springframework.web.context.ContextLoaderListener
sampleServlet
org.springframework.web.servlet.DispatcherServlet
contextClass
org.springframework.web.context.
support.AnnotationConfigWebApplicationContext
...
@Configuation等价于
@Bean等价于
@ComponentScan等价于
配置类:
package com.example.test.configuration;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportResource;
/**
* 引入spring的xml配置文件
*/
@Configuration
@ImportResource("classpath:applicationContext-configuration.xml")
public class WebConfig {
}
Bean:
package com.example.test.configuration;
public class TestBean2 {
private String userName;
private String url;
private String password;
public void sayHello(){
System.out.println("TestBean2 sayHello...");
}
public void start(){
System.out.println("TestBean2 初始化。。。");
}
public void cleanUp(){
System.out.println("TestBean2 销毁。。。");
}
}
classpath:applicationContext-configuration.xml :
测试:
package com.example.test.configuration;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class TestRun {
public static void main(String[] args){
AnnotationConfigApplicationContext ctx=new AnnotationConfigApplicationContext();
ctx.register(WebConfig.class);
ctx.refresh();
TestBean2 tb = (TestBean2) ctx.getBean("testBean2");
tb.sayHello();
}
}
配置类:
package com.example.test.configuration;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportResource;
/**
* 引入spring的xml配置文件
*/
@Configuration
@ImportResource("classpath:applicationContext-configuration.xml")//配置文件
@Import(TestConfiguration.class)//配置类
public class WebConfig {
}
测试:
package com.example.test.configuration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class TestRun {
public static void main(String[] args){
ApplicationContext ctx=new AnnotationConfigApplicationContext(WebConfig.class);
TestBean tb = (TestBean) ctx.getBean("testBean");
tb.sayHello();
TestBean2 tb2 = (TestBean2) ctx.getBean("testBean2");
tb2.sayHello();
}
}
结果:
通过配置类嵌套的配置类,达到组合多个配置类的目的。但注意内部类必须是静态类。
配置类:
package com.example.test.configuration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = "com.example.test.configuration") //TestBean 增加了@Component注解
public class TestConfiguration {
public TestConfiguration(){
System.out.println("TestConfiguration 容器启动初始化了。。。");
}
static class TestConfiguration2{
@Bean
TestBean2 testBean2(){
return new TestBean2();
}
}
}
测试类:
package com.example.test.configuration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class TestRun {
public static void main(String[] args){
ApplicationContext ctx=new AnnotationConfigApplicationContext(TestConfiguration.class);
TestBean tb = (TestBean) ctx.getBean("testBean");
tb.sayHello();
TestBean2 tb2 = (TestBean2) ctx.getBean("testBean2");
tb2.sayHello();
}
}
结果:
参考文章:https://www.breakyizhan.com/java/14623.html#11