三、spring中高级装配(1)
大概看了一下第三章的内容,我从项目中仔细寻找,始终没有发现哪里有这种配置,但是看完觉得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)的更多相关文章
- 四、spring中高级装配(2)
这个是接着上一篇写的,这章内容较多,分开来记录一下... 三.处理自动装配的歧义性 自动装配让spring完全负责bean引用注入到构造参数和属性中,不过,仅有一个bean匹配所需的结果时,自动装配才 ...
- Spring学习(三)-----Spring自动装配Beans
在Spring框架,可以用 auto-wiring 功能会自动装配Bean.要启用它,只需要在 <bean>定义“autowire”属性. <bean id="custom ...
- (三)Spring 高级装配 bean的作用域@Scope
1.默认情况下,spring通过@Autowared注入的bean是单例的bean,但有些情况是不满足的,例如:购物车,每个会话,或每个用户登录使用的购物车都是独立的 spring的定义的作用域: a ...
- Spring高级装配
Spring高级装配 目录 一.Profile(根据开发环境创建对应的bean) 二.条件化的创建bean(根据条件创建bean) 三.处理自动装配歧义性(指定首选bean.限定符限制bean) 四. ...
- Spring(3)——装配 Spring Bean 详解
装配 Bean 的概述 前面已经介绍了 Spring IoC 的理念和设计,这一篇文章将介绍的是如何将自己开发的 Bean 装配到 Spring IoC 容器中. 大部分场景下,我们都会使用 Appl ...
- Spring 自动装配及其注解
一.属性自动装配 首先,准备三个类,分别是User,Cat,Dog.其中User属性拥有Cat和Dog对象. package com.hdu.autowire; public class User { ...
- spring 自动装配 default-autowire="byName/byType"
<PRE class=html name="code">spring 自动装配 default-autowire="byName/byType" ...
- Spring高级装配(一) profile
Spring高级装配要学习的内容包括: Spring profile 条件化的bean声明 自动装配与歧义性 bean的作用域 Spring表达式语言 以上属于高级一点的bean装配技术,如果你没有啥 ...
- Spring Bean装配学习
解释:所谓装配就是把一个类需要的组件给它设置进去,英文就是wire,wiring:注解Autowire也叫自动装配. 目前Spring提供了三种配置方案: 在XML中进行显式的配置 在Java中进行显 ...
随机推荐
- net share
IT知识梳理 2017-11-30 06:57:10 Dos 命令进阶(一)讲解思路 1.Net常用命令 (1)net share - 查看共享命令 net share ipc$ - 设置ipc$共享 ...
- asp.net mvc5 使用百度ueditor 本编辑器完整示例(三)在IIS中多个应用程序使用多个ueditor对象
最近做了一个项目,要求同一类型的多个专业应用程序(网站),但是每个应用程序都需要调用各自当中的ueditor. 步骤: 一.在vs2013中设置每个专业的asp.net mvc 应用程序. 1.配置根 ...
- Mysql数据库的数据类型、索引、锁、事务和视图
Mysql数据库的数据类型.索引.锁.事务和视图 数据的类型 1)数据类型: 数据长什么样? 数据需要多少空间来存放? 系统内置数据类型和用户定义数据类型 2)MySql 支持多种列类型: 数值类型 ...
- 使用FFMPEG从MP4封装中提取视频流到.264文件 (转载)
命令行: ffmpeg -i 20130312_133313.mp4 -codec copy -bsf: h264_mp4toannexb -f h264 20130312_133313.264 说明 ...
- idea 快捷键以及包含字符串文件搜索
1.idea也有一个类似于eclipse的包含字符串文件搜索(特别实用) idea 里按快捷键:ctrl+H 2.下图是idea的快捷键汇总 3.debug调试 F5:跳入方法 F6:向下逐行调试 ...
- bzoj 1602: [Usaco2008 Oct]牧场行走【瞎搞】
本来想爆手速写个树剖,然而快下课了就手残写了了个n方的短小-- 暴力把查询的两个点中深的一个跳上来,加上边权,然后一起跳加边权就行了 #include<iostream> #include ...
- VS2013程序打包报 ISEXP : error -****: An error occurred streaming
原因缺少打包文件 解决方案: 找到打包文件 右击选择 downLoad selected item
- Luogu P2458 [SDOI2006]保安站岗【树形Dp】
题目描述 五一来临,某地下超市为了便于疏通和指挥密集的人员和车辆,以免造成超市内的混乱和拥挤,准备临时从外单位调用部分保安来维持交通秩序. 已知整个地下超市的所有通道呈一棵树的形状:某些通道之间可以互 ...
- centos 7添加快捷键
转自:http://www.cnblogs.com/flying607/p/5730867.html centos7中不自带启动终端的快捷键,可以自定义添加. 点击右上角的用户名,点击设置,在设置面板 ...
- python之计数统计
前言: 计数统计,简单的说就是统计某一项出现的次数.实际应用中很多需求都需要用到这个模型,如检测样本中某一值出现的次数.日志分析某一消息出现的频率.分析文件中相同字符串出现的概率等等.以下是实现的不同 ...