原文出处:https://www.cnblogs.com/duanxz/p/7493276.html
从Spring3.0,@Configuration
用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext
或AnnotationConfigWebApplicationContext
类进行扫描,并用于构建bean定义,初始化Spring容器。
注意:@Configuration
注解的配置类有如下要求:
@Configuration
不可以是final类型;
@Configuration
不可以是匿名类;
嵌套的configuration必须是静态类。
一、用@Configuration
加载spring
1.1、@Configuration
配置spring并启动spring容器
1.2、@Configuration
启动容器+@Bean注册Bean
1.3、@Configuration
启动容器+@Component注册Bean
1.4、使用 AnnotationConfigApplicationContext
注册 AppContext 类的两种方法
1.5、配置Web应用程序(web.xml中配置AnnotationConfigApplicationContext
)
二、组合多个配置类
2.1、在@configuration
中引入spring的xml配置文件
2.2、在@configuration
中引入其它注解配置
2.3、@configuration
嵌套(嵌套的Configuration必须是静态类)
三、@EnableXXX
注解
四、@Profile
逻辑组配置
五、使用外部变量
@Configuation加载Spring方法
@Configuation注解一个类配置应用上下文
用@Configuation
注解一个类,这个类相当于Spring容器的应用上下文(xml)
配置类
package test;
import org.springframework.context.annotation.Configuration;
@Configuration
public class BeansContainer {
public BeansContainer(){
System.out.println("启动spring容器");
}
}
相当于,这个xml应用上下文
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd" default-lazy-init="false">
</beans>
测试
package test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
public class test {
public static void main(String[] args){
AbstractApplicationContext context
= new AnnotationConfigApplicationContext(BeansContainer.class);
}
}
结果
@Configuration启动容器+@Bean注册Bean,@Bean下管理bean的生命周期
@Bean标注在方法上(返回某个实例的方法),等价于spring的xml配置文件中的,作用为:注册bean对象
bean类:
package test;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
@Configuration
public class BeansContainer {
public BeansContainer(){
System.out.println("启动spring容器");
}
@Bean("person")
@Scope("prototype")
public Person createPerson(){
return new Person();
}
}
配置类
package test;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
@Configuration
public class BeansContainer {
public BeansContainer(){
System.out.println("启动spring容器");
}
@Bean("person")
@Scope("prototype")
public Person createPerson(){
return new Person();
}
}
测试
package test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
public class test {
public static void main(String[] args){
AbstractApplicationContext context
= new AnnotationConfigApplicationContext(BeansContainer.class);
Person person = context.getBean("person",Person.class);
}
}
结果
注:
(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
注释。如果您正在使用 XML 方法来定义 bean,那么就应该使用 bean 元素来定义生命周期回调方法。以下代码显示了在 XML 配置中通常使用 bean 元素定义回调的方法。
bean类
package test;
public class Person {
private String name;
public Person(){
System.out.println("创建Person对象");
System.out.println(this);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void init(){
System.out.println("this is init()");
}
public void destroy(){
System.out.println("this is destroy");
}
}
配置类
package test;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
@Configuration
public class BeansContainer {
public BeansContainer(){
System.out.println("启动spring容器");
}
@Bean(name = "person",initMethod = "init",destroyMethod = "destroy")
@Scope("prototype")
public Person createPerson(){
return new Person();
}
}
测试
package test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
public class test {
public static void main(String[] args){
AbstractApplicationContext context
= new AnnotationConfigApplicationContext(BeansContainer.class);
Person person = context.getBean("person",Person.class);
Person person2 = context.getBean("person",Person.class);
}
}
结果
分析:
结果中的1:表明initMethod
生效
结果中的2:表明@Scope("prototype")
生效
@Configuration启动容器+@Component注册Bean
bean类:
package test;
import org.springframework.stereotype.Component;
@Component("p")
public class Person {
private String name;
public Person(){
System.out.println("创建Person对象");
System.out.println(this);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void init(){
System.out.println("this is init()");
}
public void destroy(){
System.out.println("this is destroy");
}
}
配置类
package test;
import org.springframework.context.annotation.*;
@Configuration
@ComponentScan(basePackages = "test")
public class BeansContainer {
public BeansContainer(){
System.out.println("启动spring容器");
}
/**
@Bean(name = "person",initMethod = "init",destroyMethod = "destroy")
@Scope("prototype")
public Person createPerson(){
return new Person();
}*/
}
测试
package test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
public class test {
public static void main(String[] args){
AbstractApplicationContext context
= new AnnotationConfigApplicationContext(BeansContainer.class);
Person person = context.getBean("p",Person.class);
}
}
@Component("beanName")
指定bean的名字,便于取用bean
使用 AnnotationConfigApplicationContext 注册 AppContext 类的两种方法
配置类的注册方式是将其传递给 AnnotationConfigApplicationContext 构造函数
// @Configuration注解的spring容器加载方式,用AnnotationConfigApplicationContext替换ClassPathXmlApplicationContext
ApplicationContext context = new AnnotationConfigApplicationContext(TestConfiguration.class);
//获取bean
TestBean tb = (TestBean) context.getBean("testBean");
tb.sayHello();
AnnotationConfigApplicationContext 的register 方法传入配置类来注册配置类
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(AppContext.class)
}
配置Web应用程序(web.xml中配置AnnotationConfigApplicationContext)
过去,您通常要利用 XmlWebApplicationContext
上下文来配置 Spring Web 应用程序,即在 Web 部署描述符文件 web.xml 中指定外部 XML 上下文文件的路径。XMLWebApplicationContext
是 Web 应用程序使用的默认上下文类。以下代码描述了 web.xml 中指向将由 ContextLoaderListener
监听器类载入的外部 XML 上下文文件的元素。
<web-app>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<servlet>
<servlet-name>sampleServlet</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
</servlet>
...
</web-app>
现在,您要将 web.xml 中的上述代码更改为使用 AnnotationConfigApplicationContext
类。切记,XmlWebApplicationContext
是 Spring 为 Web 应用程序使用的默认上下文实现,因此您永远不必在您的web.xml 文件中显式指定这个上下文类。现在,您将使用基于 Java 的配置,因此在配置 Web 应用程序时,需要在web.xml 文件中指定 AnnotationConfigApplicationContext
类。上述代码将修改如下:
<web-app>
<context-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.
support.AnnotationConfigWebApplicationContext
</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
demo.AppContext
</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<servlet>
<servlet-name>sampleServlet</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.
support.AnnotationConfigWebApplicationContext
</param-value>
</init-param>
</servlet>
...
</web-app>
以上修改后的 web.xml 现在定义了 AnnotationConfigWebApplicationContext
上下文类,并将其作为上下文参数和 servlet 元素的一部分。上下文配置位置现在指向 AppContext
配置类。这非常简单。下一节将演示 bean 的生命周期回调和范围的实现。
@Configuation总结
@Configuation
等价于 <Beans></Beans>
@Bean
等价于<Bean></Bean>
@ComponentScan
等价于<context:component-scan base-package="com.dxz.demo"/>
组合多个配置类
在@configuration中引入spring的xml配置文件
配置类
package test;
import org.springframework.context.annotation.*;
import test2.Config;
@Configuration
@ImportResource("classpath:xspringmvc-servlet.xml")
@ComponentScan(basePackages = "test")
public class BeansContainer {
public BeansContainer(){
System.out.println("启动spring容器");
}
}
xml文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 支持的其中一个属性,支持的最大文件大小,以字节为单位 -->
<property name="maxUploadSize" value="100000"/>
</bean>
<bean
</beans>
这里很遗憾,我想添加以上bean时,会报错,可能跟依赖有关系,导入自己的bean是可以的。
在@configuration中引入其它注解配置
配置类
package test;
import org.springframework.context.annotation.*;
import test2.Config;
@Configuration
@Import(Config.class)
@ComponentScan(basePackages = "test")
public class BeansContainer {
public BeansContainer(){
System.out.println("启动spring容器");
}
}
package test2;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class Config {
public Config(){
System.out.println("启动Config容器");
}
@Bean
public Student student(){
return new Student();
}
}
@configuration嵌套(嵌套的Configuration必须是静态类)
通过配置类嵌套的配置类,达到组合多个配置类的目的。但注意内部类必须是静态类
package test;
import org.springframework.context.annotation.*;
import test2.Config;
@Configuration
@ComponentScan(basePackages = "test")
public class BeansContainer {
public BeansContainer(){
System.out.println("启动spring容器");
}
@Configuration
static class innerBeansContainer{
public innerBeansContainer(){
System.out.println("启动BeansContainer容器");
}
@Bean
public boss boss(){
return new boss();
}
}
}