zoukankan      html  css  js  c++  java
  • Spring学习笔记-高级装配-03

    主要内容:

      ●Spring profile

      ●条件化的bean声明

      ●自动装配与歧义性

      ● Spring表达式语言

    本章介绍一些高级的装配技术,可实现更为高级的装配功能。

    环境与profile

    软件开发时,有一个很大的挑战就是讲应用程序从一个环境迁移到另外一个环境,开发环境可能并不适合迁移到生产环境,比如:数据库配置、加密算法以及外部系统的集成可能会发生变化。

    比如数据库配置:

      ● 在开发环境中可能使用的是嵌入式数据库,并预先加载测试数据,bean配置类可能会在一个带有@Bean注解的方法上使用EmbeddedDatabasebuilder(嵌入式数据源)。

      ● 在生产环境中可能使用JNDI从容器中获取一个DataSource。

      ● 在测试环境中可能选择另外一个不同的DataSource。

    在不同的还击某个bean因此不同,我们需要一种方法来配置DataSource,使其在不同环境中都会选择最合适的配置。

    配置profile

    Spring3.1版本中,引入了bean profile功能,要使用它,首先要将所有不同的bean定义整理到一个或多个profile中,在将应用部署到每个环境时,要确保对应的profile处于激活的状态。

    使用配置类配置profile

    在Java配置中,可使用@Profile注解指定某个bean属于哪一个profile,例如,在配置类中,

    嵌入式数据库的DataSource配置

    @Configuration
    @Profile("dev") //告诉Spring这个配置类的bean只有在dev profile激活时才会创建,如果dev profile没有激活那么带有@Bean注解的方法都会被忽略掉
    public class DevelopmentProfileConfig {
      @Bean
    public DataSource dataSource(){ return new EmbeddedDatabaseBuilder() .setType(EmbeddedDatabaseType.H2) .addScript("classppath:schema.sql") .addScript("classpath:test-data.sql") .build(); } }

    一个适用于生产环境的配置

    @Configuration
    @Profile("prod") //告诉Spring这个配置类的bean只有在prod profile激活时才会创建,如果dev profile没有激活那么带有@Bean注解的方法都会被忽略掉
    public class ProductionProfileConfig {
        @Bean
        public DataSource dataSource(){
            JndiObjectFactoryBean jndiObjectFactoryBean=
                    new JndiObjectFactoryBean();
            jndiObjectFactoryBean.setJndiName("jdbc/DS");
            jndiObjectFactoryBean.setResourceRef(true);
            jndiObjectFactoryBean.setProxyInterface(javax.sql.DataSource.class);
            return (DataSource) jndiObjectFactoryBean;
        }
    }

    在Spring中,只能在类级别上使用@Profile注解,不过从3.2版本开始,也可以再方法级别使用@Profile,这样的话就能和@Bean同时使用,同时将两个bean的声明放在同一个配置类中。

    @Profile注解基于激活的profile实现bean的装配

    @Configuration
    public class DataSourceProfile {
        @Bean
        @Profile("dev")  //为dev profile装配的bean
        public DataSource embededDataSource(){
            return new EmbeddedDatabaseBuilder()
                .setType(EmbeddedDatabaseType.H2)
                .addScript("classppath:schema.sql")
                .addScript("classpath:test-data.sql")
                .build();
        }
        @Bean
        @Profile("prod") //为prod profile装配的bean
        public DataSource jndiDataSource(){
            JndiObjectFactoryBean jndiObjectFactoryBean=
                    new JndiObjectFactoryBean();
            jndiObjectFactoryBean.setJndiName("jdbc/DS");
            jndiObjectFactoryBean.setResourceRef(true);
            jndiObjectFactoryBean.setProxyInterface(javax.sql.DataSource.class);
            return (DataSource) jndiObjectFactoryBean;
        }
    }

    使用XML配置profile

    了解即可

    激活profile

    String在确定哪个profile处于激活状态时,需要依赖两个独立的属性:spring.profile.active和spring.profiles.default,如果设置了spring.profile.active属性,那么它的值就会用来确定哪个profile是激活的,如果没有设置,那就会查找spring.profiles.default的值,如果均没有设置那就没有激活的profile,则只会创建那些没用定义在profile中的bean。

    有多种方式来设置这两个属性:

    ● 作为DispatcherServlet的初始化参数;

    ● 作为Web应用的上下文参数;

    ●  作为JNDI条目;

    ● 作为环境变量;

    ● 作为JVM的系统属性;

    ● 在集成测试类上,使用@ActiveProfiles注解设置。

    在Web.xml文件中设置默认的profile

    <Web-app version="2.5">
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring/root-context.xml</param-value>
        </context-param>
        
        <context-param>
            <param-name>spring.profiles.default</param-name>    <!-- 为上下文设置默认的profile -->
            <param-value>dev</param-value>
        </context-param>
        
        <listener>
            <listent-class>
                org.springframework.web.context.ContextLoaderListener
            </listent-class>
        </listener>
        
        <servlet>
            <servlet-name>appServlet</servlet-name>
            <servlet-class>
                org.springframework.web.servlet.DispatcherServlet
            </servlet-class>
            <init-param>
                <param-name>spring.profiles.default</param-name> <!-- 为Servlet设置默认的profile -->
                <param-value>dev</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
        
        <servlet-mapping>
            <servlet-name>appServlet</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    </Web-app>

     按照这种方式设置spring.profiles.default,所有开发文员都能才能够版本控制软件获得应用程序代码,并且使用开发环境的设置运行代码,而不需要任何额外设置。

    当程序部署到测试、生产或其他环境中,负责部署人员根据情况使用系统属性、环境变量或JNDI设置spring.profiles.active即可,此时spring.profiles.default值会被忽略,因为spring会优先使用spring.profiles.active的值。

    使用profile进行测试

    当集成运行测试时,通常会希望采用与生产环境相同的配置进行测试,但如果配置中的bean定义在profile中,那么在运行测试中,就需要有一种方式来启用合适的profile。

    Spring提供了@ActiveProfiles注解,我们可使用它指定运行测试时要激活那个Profile。在集成测试时,通常想要激活的是开发环境的profile,例如,下面的测试类片段展现如何使用@ActiveProfile激活dev profile:

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextCOnfiguration(classes={PersistenceTestConfig.class})
    @ActiveProfiles("dev")
    public class ActiveProfileTest {
    ....

    条件化的Bean

      假设希望一个或多个bean只有在应用的类路径下包含特定的库时才会创建。或希望某个bean只有当另外某个特定的bean也声明后才会创建,以及等等需要满足各种条件才会创建。

    在Spring4引入了一个新的@Conditional注解,它可以用到带有@Bean注解的方法上,如果给定的条件计算结果为true,就会创建这个bean,否则就会被忽略。

    未完待续...

  • 相关阅读:
    5、流程控制
    4、字典和元祖
    3、列表操作
    2、字符串和数据类型
    1.标识符练习
    使用xpath提取页面所有a标签的href属性值
    网页提取所有邮箱
    正则表达式
    提取包含QQ的文本为QQ邮箱
    python继承小demo
  • 原文地址:https://www.cnblogs.com/vice/p/8761232.html
Copyright © 2011-2022 走看看