大概看了一下第三章的内容,我从项目中仔细寻找,始终没有发现哪里有这种配置,但是看完觉得spring还有这么牛B的功能啊,spring的厉害之处,这种设计程序的思想,很让我感慨。。。

一、环境与profile

(1)配置profile bean

面对这样的需求:想出一种方法来配置DataSource,使其在每种环境下都会选择最为合适的配置,你会如何做呢?看看spring所提供的解决方案。spring中引入了bean profile的功能。在Java配置中,可以使用@Profile 注解指定某个bean属于哪一个profile。

1)在Java类中配置profile bean

package com.myapp;
import javax.sql.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; //@Profile注解应用在累计别上。它会告诉spring这个配置类中的bean只有在dev profile 激活时才会创建,没有激活,则不会创建
@Configuration
@Profile("dev")
public class DevelopmentProfileConfig{
  return new
  EmbeddDatabaseBuilder().setType(EmbeddedDatebaseType.H2).
  addScript("classpath:schema.sql").addScript("classpath:test-
  data.sql").build();
} package com.myapp;
import javax.sql.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.jndi.JndiObjectFactoryBean; //@Profile注解应用在累计别上。它会告诉spring这个配置类中的bean只有在prod profile 激活时才会创建,没有激活,则不会创建
@Configuration
@Profile("prod")
public class ProductiontProfileConfig{
  JndiObjectFactoryBean jndiObjectFactoryBean = new JndiObjectFactoryBean();
  jndiObjectFactoryBean.setJndiName("jdbc/myDS");
  jndiObjectFactoryBean.setResourceRef(true);
  jndiObjectFactoryBean.setProxyInterface(javax.sql.DataSource.class);
  return (DataSource) jndiObjectFactoryBean.getObject();
} //可以将这两个bean的声明放置在同一个配置类中
package com.myapp;
import javax.sql.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.jndi.JndiObjectFactoryBean; @Configuration
public class DateSourceConfig{ //为dev profile装配bean
public DataSource embeddedDataSource(){
return new
  EmbeddDatabaseBuilder().setType(EmbeddedDatebaseType.H2).
  addScript("classpath:schema.sql").addScript("classpath:test-
  data.sql").build();
} //为prod profile 装配bean
public DataSource jbdiDataSource(){
JndiObjectFactoryBean jndiObjectFactoryBean = new JndiObjectFactoryBean();
  jndiObjectFactoryBean.setJndiName("jdbc/myDS");
  jndiObjectFactoryBean.setResourceRef(true);
  jndiObjectFactoryBean.setProxyInterface(javax.sql.DataSource.class);
  return (DataSource) jndiObjectFactoryBean.getObject();
}
}

2)在XML中配置profile bean

//xml中配置的实际效果和在Java类中配置是一样的

//dev profile 的bean
<beans profile="dev">
<jdbc:embedded-database id="dataSource">
<jdbc:script location="classpath:schema.sql" />
<jdbc:script location="classpath:test-data.sql" />
</jdbc:embedded-database>
</beans> //qa profile 的bean
<beans profile="qa">
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destory-method="close" p:url="jdbc:h2:tcp://deserver/~/test" p:driverClassName="org.h2.Driver" p:username="sa" p:password="password" p:initialSize="20" p:maxActive="30">
</bean>
</beans> //prod profile 的bean
<beans>
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/myDataSource" resource-ref="true" proxy-interfase="javax.sql.DataSource" />
</beans>

2)激活 profile

profile bean 配置OK了,如何来激活配置的bean呢?依赖两个独立的属性:spring.profiles.active 和 spring.profiles.default。设置了spring.profiles.active属性的话,那么它的值就会来确定哪个profile是激活的,如果设置了spring.profiles.default属性,那么spring 会查找spring.profiles.default的值,如果两个属性都设置的话,肯定会优先spring.profiles.active属性对应的profile bean 装配

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

1))作为DispatcherServlet的初始化参数

2))作为web应用的上下文参数

3))作为JNDI条目

4))作为环境变量

5))作为JVM的系统属性

6))在集成测试上,使用@ActiveProfiles注解设置

web.xml 中设置默认的profile

//为上下文设置默认的profile
<context-param>
<param-name>spring.profile.default</param-name>
<param-value>dev</param-value>
</context-param> //为Servlet设置默认的profile 可以列出多个profile名称,并以逗号分隔来实现
<servlet>
<servlet-name>app-servlet</servlet-name>
<servlet-class>
org.springframework.web.servlet.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>spring.profiles.default</param-name>
<param-value>dev</param-value>
</init-param>
</servlet>

二、条件化的bean

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

//条件化的创建bean
@Bean
@Conditional(MagicExistsCondition.class)
public MagicBean magicBean(){
return new MagicBean();
} //@Conditional 将会通过Condition 接口进行条件对比
public interface Condition{
public boolean matches(ConditionContext ctcx,AnnotatedTypeMetadata metadata);
} //在Contidion 中检查是否存在magic属性,满足这个条件,matches()方法返回true,则所有的@Conditional 注解上引用MagicExistsCondition的bean都会被创建
public class MagicExistsCondition implements Condition{
public boolean matches(ConditionContext context,AnnotatedTypeMetadata metadata){
Environment env = context.getEnvironment();
return env.containsProperty("magic");
}
}

注:这里讲解了两个比较特殊的接口,一个是ConditionContext,一个是AnnotatedTypeMetadata,做一个说明:

public interface ConditionContext{
//检查bean的定义
BeanDefinitonRegistry getRegistry();
//检查bean是否存在,甚至探查bean的属性
ConfigurableListableBeanFactory getBeanFactory();
//检查环境变量是否存在以及它的值是什么
Environment getEnvironment();
//返回ResourceLoader所加载的资源
ResourceLoader getResourceLoader();
//返回ClassLoader加载并检查类是否存在
ClassLoader getClassLoader();
} //检查带有@Bean注解的方法上还有什么其他的注解
public interface AnnotatedTypeMetadata{
boolean isAnnotated(String annotationType);
Map<String,Object> getAnnotationAttributes(String annotationType);
Map<String,Object> getAnnotationAttributes(String annotationType,boolean classValueAsString);
MultiValueMap<String,Object> getAnnotationAttributes(String annotationType);
MultiValueMap<String,Object> getAnnotationAttributes(String annotationType,boolean classValueAsString);
}

注:spring4 中对@Profile注解进行了重构,使其基于@Conditional 和 Condition实现,@Profile在spring4 中的实现:

/*
@Profile本身也使用了@Conditional注解,并且引用了ProfileCondition作为Condition实现,ProfileCondition在做出决策的过程中,考虑到了ConditionContext和AnnotatedTypeMetadata中多个因素
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
@Document
@Conditional(ProfileCondition.class)
public @interface Profile{
String[] value();
}

三、spring中高级装配(1)的更多相关文章

  1. 四、spring中高级装配(2)

    这个是接着上一篇写的,这章内容较多,分开来记录一下... 三.处理自动装配的歧义性 自动装配让spring完全负责bean引用注入到构造参数和属性中,不过,仅有一个bean匹配所需的结果时,自动装配才 ...

  2. Spring学习(三)-----Spring自动装配Beans

    在Spring框架,可以用 auto-wiring 功能会自动装配Bean.要启用它,只需要在 <bean>定义“autowire”属性. <bean id="custom ...

  3. (三)Spring 高级装配 bean的作用域@Scope

    1.默认情况下,spring通过@Autowared注入的bean是单例的bean,但有些情况是不满足的,例如:购物车,每个会话,或每个用户登录使用的购物车都是独立的 spring的定义的作用域: a ...

  4. Spring高级装配

    Spring高级装配 目录 一.Profile(根据开发环境创建对应的bean) 二.条件化的创建bean(根据条件创建bean) 三.处理自动装配歧义性(指定首选bean.限定符限制bean) 四. ...

  5. Spring(3)——装配 Spring Bean 详解

    装配 Bean 的概述 前面已经介绍了 Spring IoC 的理念和设计,这一篇文章将介绍的是如何将自己开发的 Bean 装配到 Spring IoC 容器中. 大部分场景下,我们都会使用 Appl ...

  6. Spring 自动装配及其注解

    一.属性自动装配 首先,准备三个类,分别是User,Cat,Dog.其中User属性拥有Cat和Dog对象. package com.hdu.autowire; public class User { ...

  7. spring 自动装配 default-autowire=&quot;byName/byType&quot;

    <PRE class=html name="code">spring 自动装配 default-autowire="byName/byType"   ...

  8. Spring高级装配(一) profile

    Spring高级装配要学习的内容包括: Spring profile 条件化的bean声明 自动装配与歧义性 bean的作用域 Spring表达式语言 以上属于高级一点的bean装配技术,如果你没有啥 ...

  9. Spring Bean装配学习

    解释:所谓装配就是把一个类需要的组件给它设置进去,英文就是wire,wiring:注解Autowire也叫自动装配. 目前Spring提供了三种配置方案: 在XML中进行显式的配置 在Java中进行显 ...

随机推荐

  1. 一个tomcat部署多个应用实例总结

    项目组有好几个项目需要运行,之前项目少,一个tomcat对应一个项目还能应付,但现在项目多了,要是再一个tomcat对应一个项目的话,一方面看起来很业余,一方面也加大服务器的维护难度.所以现在需要对t ...

  2. Java-Maven:Maven百科

    ylbtech-Java-Maven:Maven百科 1.返回顶部 1. Maven项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的软件项目管理工具.Maven 除了以程序 ...

  3. bzoj1756

    1756: Vijos1083 小白逛公园 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1150  Solved: 371[Submit][Statu ...

  4. Python安装、配置图文详解

    原文地址:http://weixiaolu.iteye.com/blog/1617440 目录: 一. Python简介 二. 安装python 1. 在windows下安装 2. 在Linux下安装 ...

  5. PCB AdminMongo安装使用

    AdminMongo是针对Mongodb设计的一款Web端可视化工具,它是使用Node.js编写,这里将安装过程记录一下. 一.下载AdminMongo 前题:安装使用adminMongo需提前安装好 ...

  6. ARC102 C~D

    C: 枚举中间点,计算两边点差值,把个数乘起来即可 #include<iostream> #include<cstdio> #include<algorithm> ...

  7. Luogu P1396 营救【最小生成树/二分答案/最短路】 By celur925

    题目描述 “咚咚咚……”“查水表!”原来是查水表来了,现在哪里找这么热心上门的查表员啊!小明感动的热泪盈眶,开起了门…… 妈妈下班回家,街坊邻居说小明被一群陌生人强行押上了警车!妈妈丰富的经验告诉她小 ...

  8. Ubuntu 18 安装 wps

    本来有三种方法 1. 软件中心 安装最简单 2. 命令行snap 安装 如果没有安装snap 先安装 sudo apt install snapd 然后安装wps sudo snap install ...

  9. ROS学习笔记一:ROS安装与测试

    1 Ubuntu和ROS版本的对应关系 Ubuntu 和 ROS 都存在不同的版本,其对应关系如下: 注:如果Ubuntu版本和ROS版本不对应的话,安装就不会成功了- 笔者安装的是Ubuntu14. ...

  10. matlab实现算术编解码 分类: 图像处理 2014-06-01 23:01 357人阅读 评论(0) 收藏

    利用Matlab实现算术编解码过程,程序如下: clc,clear all; symbol=['abc']; pr=[0.4 0.4 0.2]; %各字符出现的概率 temp=[0.0 0.4 0.8 ...