zoukankan      html  css  js  c++  java
  • Spring笔记——Spring高级配置

    1、环境与profile

      在开发软件的时候,有一个很大的挑战就是将应用软件从一个环境迁移到另一个环境,开发阶段中,某些环境相关做法可能并不适合迁移到生产环境,甚至即便迁移过去也无法正常运行。为此Spring可根据环境(在运行时)去决定该创建那个bean和不创建那个bean。这样同一个部署单元(可能是war文件)能够运用于所有的环境,没有必要进行重新构建。

      例如:开发环境下的DataSource 用EmbeddedDatabaseBuilder 创建,生产环境下的DataSource用JndiObjectFactoryBean创建更加合理。

    1.1、配置profile bean

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

    • 通过Java配置类配置——@Profile
    @Configuration
    public class DataSourceConfig {
       @Bean(destroyMethod="shutdown")
       @Profile("dev") // 为dev profile装配的bean
       public DataSource embeddedDataSource() {
            return new ...
       }
       @Bean
       @Profile("prod") // 为prod profile装配的bean
       public DataSource jndiDataSource() {
            return new ...
        }   
    } 
    • 通过XML配置profile
    <beans ...>
        <beans profile="dev">
            <bean>...</bean>
        </beans>
        <beans profile="qa">
            <bean>...</bean>
        </beans>
        <beans profile="prod">
            <bean>...</bean>
        </beans>
    </beans>

    1.2、激活profile

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

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

    • 作为DispatcherServlet的初始化参数;
    • 作为Web应用的上下文参数;
    • 作为JNDI条目;
    • 作为环境变量;
    • 作为JVM的系统属性;
    • 在集成测试类上,使用@ActiveProfiles注解设置。

      例如:Web应用的web.xml文件中设置默认的profile

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://java.sun.com/xml/ns/javaee"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
        version="2.5">
        <display-name>ssm-spring</display-name>
    
        <context-param><!-- 为上下文设置默认profile -->
            <param-name>spring.profiles.default</param-name>
            <param-value>dev</param-value>
        </context-param>
        
        <!-- springmvc前端控制器 -->
        <servlet>
            <servlet-name>springmvc</servlet-name>
            <servlet-class>org.springframwork.web.servlet.DispatcherServlet</servlet-class>
            <init-param><!-- 为Servlet设置默认profile -->
                <param-name>spring.profiles.default</param-name>
                <param-value>dev</param-value>
            </init-param>
        </servlet>
        <servlet-mapping>
            <servlet-name>springmvc</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    </web-app>

    2、条件化的Bean

      【条件】

    • 希望一个或多个bean只有在应用的类路径下包含特定的库时才创建;
    • 希望某个bean只有当另外某个特定的bean也声明了之后才会创建 ;
    • 要求只有某个特定的环境变量设置之后,才会创建某个bean

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

    @Configuration
    @ComponentScan
    public class BeanConfig {
    
        @Bean
        @Conditional(MagicExistsCondition.class) // 设置创建bean的条件
        public MagicBean magicBean() {
            return new MagicBean();
        }
    }
    
    public class MagicExistsCondition implements Condition {
    
        public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
            Environment ev = context.getEnvironment(); 
            return ev.containsProperty("magic"); // 检查magic属性是否存在
        }
    
    }

    3、处理自动装配的歧义性

      当在Spring上下文中存在多个bean能够匹配所需的结果时,@autowired自动装配将产生歧义,Spring将抛出NoUniqueBeanDefinitionException异常。

      解决办法:

    • 标示首选的bean
    @Component
    @Primary
    public class IceCrean implements Dessert {...}
    <bean id="iceCream" class="..." primary="true" />
    • 限定自动装配的bean——使用@Qualifier

      (1)、使用@Qualifier("iceCream")限定bean的范围。@Qualifier注解所设置的参数就是想要注入的beanID;

      (2)、使用自定义的限定符注解

    @Component
    @Qualifier("cold")
    public class Poosicle implements Dessert {...}
    
    @Bean
    @Qualifier("cold")
    public Dessert iceCream() {
      return new IceCream();  
    }

    4、bean的作用域

      在默认情况下, Spring应用上下文中所有bean都是作为以单例(singleton)的形式创建的。 也就是说,不管给定的一个bean被注入到其他bean多少次,每次所注入的都是同一个实例。
      Spring定义了多种作用域:

    • 单例(Singleton):在整个应用中,只创建bean的一个实例(默认作用域)。
    • 原型(Prototype):每次注入或者通过Spring应用上下文获取的时候,都会创建一个新的bean实例。
    • 会话(Session):在Web应用中,为每个会话创建一个bean实例。
    • 请求(Rquest):在Web应用中,为每个请求创建一个bean实例。 

      4.1、使用@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE )设置bean的作用域;

      4.2、使用<bean id="xxx" class="xxxx" scope="" />设置bean的作用域。

    5、运行时值注入

       运行时注入的两种方式:

    • 属性占位符(Property placeholder);
    • Spring表达式语言(SpEL)。

    5.1、注入外部的值

      (1)、通过Java配置类注入

    @Configuration
    @PropertySource("classpath:com/zhux/ssm/app.properties") // 声明属性源
    public class ExpressiveConfig {
    
        @Autowired
        Environment env;
        
        @Bean
        public MagicBean magicBean() {
            return new MagicBean(env.getProperty("magic.title"), env.getProperty("magic.arttist")); // 检索属性值
        }
    }

      (2)、通过XML注入

    <context:property-placeholder location="classpath:db.properties"/>
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
      <property name="driverClassName" value="${jdbc.driver}" />
      <property name="url" value="${jdbc.url}" />
      <property name="username" value="${jdbc.username}" />
      <property name="password" value="${jdbc.password}" />
    </bean>

      (3)、使用@Value注解——如果我们依赖于组件扫描和自动装配来创建和初始化应用组件的话,那么就没有指定占位符的配置文件或类了 。此时我们可以使用@Value注解。为了使用占位符,我们必须要配置一个PropertyPlaceholderConfigurer beanPropertySourcesPlaceholderConfigurer bean

    public class MagicBean {
      public MagicBean(@Value("${magic.title}") title, @Value("${magic.artist}") artist) {     ...   }


    // Java配置类中
    @Bean
    public static PropertySourcesPlaceholderConfigurer p
    laceholderConfigurer {
      return new PropertySourcesPlaceholderConfigurer();
    }

     5.2、使用Spring表达式语言进行装配——SpEL

  • 相关阅读:
    动态页面技术----EL技术、JSTL技术,javaEE的开发模式
    动态页面技术----JSP技术
    会话技术Cookie&Session
    HttpServletRequest
    设计模式和抽象类、方法
    类的继承
    类与对象
    面向对象和面向过程的区别
    PHP-错误处理
    PHP-文件加载
  • 原文地址:https://www.cnblogs.com/zhuxiong/p/7653506.html
Copyright © 2011-2022 走看看