Spring:@Configuration 使用

 

编写不易,转载请注明(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

  

猜你喜欢

转载自shihlei.iteye.com/blog/2405771
今日推荐