编写不易,转载请注明(http://shihlei.iteye.com/blog/2405771)!
一 @Configuration 概述
@Bean: 描述@Bean注解的方法生成的Bean 被Spring容器管理, 其中value属性可以指定Bean在Spring容器中的名字。
@Configuration:描述@Configuration注解的类,Spring容器扫描@Bean注解的方法,将生成的Bean纳入容器管理(可以简化xml配置) 。
存在于:
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version${spring.version}</version> </dependency>
二 使用Demo
(一)配置类
package x.demo.spring.context.conf.define;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SimpleConfiguraiton {
@Bean
public BeanInSimple beanInSimple() {
return new BeanInSimple();
}
}
class BeanInSimple {
}
(二)Spring容器引导@Configuration 的几种方法
方法1 :
通过AnnotationConfigApplicationContext 或 web 版 AnnotationConfigWebApplicationContext 引导Bean导入容器
package x.demo.spring.context.conf;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import x.demo.spring.context.conf.define.EnvConfiguration;
import x.demo.spring.context.conf.define.ProfileConfiguration;
import x.demo.spring.context.conf.define.RealConfiguration;
import x.demo.spring.context.conf.define.SimpleConfiguraiton;
public class ConfigurationAnnocationDemo {
//打印相关信息
private static void show(ApplicationContext context) {
String[] beans = {"beanInSimple"};
for (String b : beans) {
boolean isContains = context.containsBean(b);
System.out.println(b + " is exist : " + isContains);
if (isContains) {
System.out.println(b + " : " + context.getBean(b));
}
}
}
/**
* 通过AnnotationConfigApplicationContext 或 web 版 AnnotationConfigWebApplicationContext 直接注册配置类,驱动Bean导入容器
*/
public static void triggerViaAnnotationConfigApplicationContext() {
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();) {
context.register(SimpleConfiguraiton.class);
context.refresh();
show(context);
}
}
public static void main(String[] args) {
ConfigurationAnnocationDemo.triggerViaAnnotationConfigApplicationContext();
}
}
方法2:
通过Spring Xml文件引导Bean导入容器
xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd"> <context:annotation-config/> <bean class="x.demo.spring.context.conf.define.SimpleConfiguraiton"/> </beans>
程序:
package x.demo.spring.context.conf;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import x.demo.spring.context.conf.define.EnvConfiguration;
import x.demo.spring.context.conf.define.ProfileConfiguration;
import x.demo.spring.context.conf.define.RealConfiguration;
import x.demo.spring.context.conf.define.SimpleConfiguraiton;
public class ConfigurationAnnocationDemo {
//打印相关信息
private static void show(ApplicationContext context) {
String[] beans = {"beanInSimple"};
for (String b : beans) {
boolean isContains = context.containsBean(b);
System.out.println(b + " is exist : " + isContains);
if (isContains) {
System.out.println(b + " : " + context.getBean(b));
}
}
}
/**
* xml 方式触发@ComponentScan使用
*/
public static void triggerViaXml() {
try (ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext
("classpath:x.demo.spring.context.conf/spring-conf.xml");) {
show(context);
}
}
public static void main(String[] args) {
ConfigurationAnnocationDemo.triggerViaXml();
}
}
方法3:
通过ComponentScan 引导Bean导入容器:可参考之前的文章《Spring:@ComponentScan 使用》
package x.demo.spring.context.conf;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import x.demo.spring.context.conf.define.EnvConfiguration;
import x.demo.spring.context.conf.define.ProfileConfiguration;
import x.demo.spring.context.conf.define.RealConfiguration;
import x.demo.spring.context.conf.define.SimpleConfiguraiton;
@ComponentScan("x.demo.spring.context.conf.define")
public class ConfigurationAnnocationDemo {
//打印相关信息
private static void show(ApplicationContext context) {
String[] beans = {"beanInSimple"};
for (String b : beans) {
boolean isContains = context.containsBean(b);
System.out.println(b + " is exist : " + isContains);
if (isContains) {
System.out.println(b + " : " + context.getBean(b));
}
}
}
/**
* 通过ComponentScan 引导Bean导入容器
*/
public static void triggerViaComponentScan() {
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();) {
context.register(ConfigurationAnnocationDemo.class);
context.refresh();
show(context);
}
}
public static void main(String[] args) {
ConfigurationAnnocationDemo.triggerViaComponentScan();
}
}
(二)结果
beanInSimple is exist : true beanInSimple : x.demo.spring.context.conf.define.BeanInSimple@4c15e7fd
三 读取配置初始化@Configuration中的Bean
可以通过 @PropertySource() 或 @Value 加载配置文件中的数据,初始化Bean
配置文件:classpath:x.demo.spring.context.conf/env.properties
x.demo.spring.context.conf.define.env=dev
程序:
package x.demo.spring.context.conf.define;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
@Configuration
//导入属性文件
@PropertySource("classpath:x.demo.spring.context.conf/env.properties")
public class EnvConfiguration {
//获取整个配置文件值
@Resource
Environment env;
//获取属性文件中指定key的信息
@Value("${x.demo.spring.context.conf.define.env}")
String envValue;
@Bean
public BeanInEnv beanInEnv() {
System.out.println("env reads : " + env.getProperty("x.demo.spring.context.conf.define.env"));
System.out.println("env @Value : " + envValue);
return new BeanInEnv(envValue);
}
}
class BeanInEnv {
public BeanInEnv(String env) {
}
}
四 组合其他@Configutration定义
@Configuration 可以组合其他的注解,来生成合并的配置
(1)使用@Import:
导入其他@Configuration注解的类 或 有@Bean注解方法的类。多用于@Configuration 类导入依赖。
(2)使用@ImportResource:
从Xml中读取Bean定义,组合Bean 配置。
(3)使用静态内部类:
Demo:
BaseConfiguration:
package x.demo.spring.context.conf.define;
import org.springframework.context.annotation.Bean;
public class BaseConfiguration {
@Bean
public BeanInBase beanInBase() {
return new BeanInBase();
}
}
class BeanInBase {
}
Xml bean定义:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean class="x.demo.spring.context.conf.define.BeanInRealXmlDependency"/> </beans>
RealConfiguration:
package x.demo.spring.context.conf.define;
import javax.annotation.Resource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportResource;
@Configuration
//导入其他的配置
@Import(BaseConfiguration.class)
//从Xml文件导入Bean定义
@ImportResource("classpath:x.demo.spring.context.conf/spring-xml-dependency.xml")
public class RealConfiguration {
@Resource
BeanInRealXmlDependency beanInRealXmlDependency;
@Resource
BeanInRealNestedDependency beanInRealNestedDependency;
@Bean
public BeanInReal beanInReal() {
return new BeanInReal(beanInRealXmlDependency, beanInRealNestedDependency);
}
//静态内部类方式导入定义
@Configuration
static class NestedConfiguration {
@Bean
public BeanInRealNestedDependency beanInRealNestedDependency() {
return new BeanInRealNestedDependency();
}
}
}
class BeanInReal {
public BeanInReal(BeanInRealXmlDependency beanInRealXmlDependency, BeanInRealNestedDependency beanInRealNestedDependency) {
System.out.println("beanInRealXmlDependency : " + beanInRealXmlDependency);
System.out.println("beanInRealNestedDependency : " + beanInRealNestedDependency);
}
}
class BeanInRealNestedDependency {
}
class BeanInRealXmlDependency {
}
五 根据条件生成Bean导入Spring容器
(1)根据@Profile:
在某个Profile激活的时候使用某个配置:
package x.demo.spring.context.conf.define;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
@Configuration
public class ProfileConfiguration {
@Bean()
@Profile("dev")
public BeanInProfile beanInRealOnDev() {
return new BeanDev();
}
@Bean()
@Profile("online")
public BeanInProfile beanInRealOnOnline() {
return new BeanOnline();
}
}
class BeanInProfile {
}
class BeanDev extends BeanInProfile {
}
class BeanOnline extends BeanInProfile {
}
注:测试是要添加虚拟机参数指定激活那个profile
(2)根据@Conditional
@Conditional 可以指定条件,根据条件确定是否生成Bean
这里简单实现了根据数据库是否有驱动,实例化某个Bean
package x.demo.spring.context.conf.define;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Map;
import java.util.Objects;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.type.AnnotatedTypeMetadata;
@Configuration
public class ConditionalConfiguration {
@Bean
@ConditionalOnDBDriver(driver = "com.mysql.jdbc.Driver")
public BeanDB beanMySql() {
return new BeanMySql();
}
@Bean
@ConditionalOnDBDriver(driver = "oracle.jdbc.driver.OracleDriver")
public BeanDB beanOracle() {
return new BeanOracle();
}
}
class BeanDB {
}
class BeanMySql extends BeanDB {
}
class BeanOracle extends BeanDB {
}
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnDBDriverCondition.class)
@interface ConditionalOnDBDriver {
/**
* 驱动名称
*
* @return 驱动名称
*/
String driver();
}
/**
* 加载条件
*/
class OnDBDriverCondition implements Condition {
/**
* 匹配条件:某个类在class path下某个指定名字的类是否存在,
* <p>
* 注:其他需求可以配合maven <optional>true</optional>,使用
*
* @param context 条件上线文,包括beanFactory , env,classloader 等
* @param metadata 元数据,提供被注解的类,方法信息
* @return true 注册到容器,false 不注册到容器
*/
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
try {
Map<String, Object> attributes = metadata.getAnnotationAttributes("x.demo.spring.context.conf.define.ConditionalOnDBDriver");
if (Objects.isNull(attributes)) {
return false;
}
String driver = String.valueOf(attributes.get("driver"));
System.out.println("[debug] driver : " + driver);
Class.forName(driver);
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
}
注:如果要 向容器注入BeanMySql需要添加MySql依赖
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.44</version> <optional>true</optional> </dependency>
六 完成测试程序
结构:
代码:
package x.demo.spring.context.conf;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import x.demo.spring.context.conf.define.EnvConfiguration;
import x.demo.spring.context.conf.define.ProfileConfiguration;
import x.demo.spring.context.conf.define.RealConfiguration;
import x.demo.spring.context.conf.define.SimpleConfiguraiton;
@ComponentScan("x.demo.spring.context.conf.define")
public class ConfigurationAnnocationDemo {
//打印相关信息
private static void show(ApplicationContext context) {
String[] beans = {"beanInSimple", "beanInBase", "beanInEnv", "beanInReal", "beanInProfile","beanInRealOnDev",
"beanInRealOnOnline","beanMySql","beanOracle"};
for (String b : beans) {
boolean isContains = context.containsBean(b);
System.out.println(b + " is exist : " + isContains);
if (isContains) {
System.out.println(b + " : " + context.getBean(b));
}
}
}
/**
* 通过AnnotationConfigApplicationContext 或 web 版 AnnotationConfigWebApplicationContext 直接注册配置类,驱动Bean导入容器
*/
public static void triggerViaAnnotationConfigApplicationContext() {
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();) {
context.register(SimpleConfiguraiton.class, EnvConfiguration.class, RealConfiguration.class, ProfileConfiguration.class);
context.refresh();
show(context);
}
}
/**
* xml 方式触发@ComponentScan使用
*/
public static void triggerViaXml() {
try (ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext
("classpath:x.demo.spring.context.conf/spring-conf.xml");) {
show(context);
}
}
/**
* 通过ComponentScan 引导Bean导入容器
*/
public static void triggerViaComponentScan() {
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();) {
context.register(ConfigurationAnnocationDemo.class);
context.refresh();
show(context);
}
}
public static void main(String[] args) {
ConfigurationAnnocationDemo.triggerViaComponentScan();
}
}
结果:
[debug] driver : com.mysql.jdbc.Driver [debug] driver : oracle.jdbc.driver.OracleDriver env reads : dev env @Value : dev beanInRealXmlDependency : x.demo.spring.context.conf.define.BeanInRealXmlDependency@7a52f2a2 beanInRealNestedDependency : x.demo.spring.context.conf.define.BeanInRealNestedDependency@78047b92 beanInSimple is exist : true beanInSimple : x.demo.spring.context.conf.define.BeanInSimple@60dcc9fe beanInBase is exist : true beanInBase : x.demo.spring.context.conf.define.BeanInBase@222114ba beanInEnv is exist : true beanInEnv : x.demo.spring.context.conf.define.BeanInEnv@16e7dcfd beanInReal is exist : true beanInReal : x.demo.spring.context.conf.define.BeanInReal@3d121db3 beanInProfile is exist : false beanInRealOnDev is exist : true beanInRealOnDev : x.demo.spring.context.conf.define.BeanDev@3b07a0d6 beanInRealOnOnline is exist : false beanMySql is exist : true beanMySql : x.demo.spring.context.conf.define.BeanMySql@11a9e7c8 beanOracle is exist : false