分类目录归档:原创文章

博客迁移公告

鉴于访问workpress速度较慢,整站迁移到独立域名:http://heartaway.cn    heartaway.cn

Advertisements

Spring中property-placeholder的使用与解析

在我们程序开发中,进程会需要把一些变量通过property方式进行提取,方便不同环境配置不同的属性,替换变量的方法通常有两种,一种是静态替换,一种是动态替换;所谓静态替换,是在打包编译的时候,把变量替换掉,动态替换,是在程序运行起来时,通过把属性注入到程序的环境变量中,类初始化的时候,再使用环境变量进行替换的一种方法。

静态替换常用工具:autoconfig
动态替换常用工具:spring.property-placeholder

spring动态替换变量实践

简洁配置法:

<context:property-placeholder location="classpath:xxx.properties" 
ignore-unresolvable="true"/>

等价于:

<bean id="propertyConfigurer" class=
"org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
 <property name="location">
 <value>myConfig.properties</value>
 </property>
 </bean>

完整配置属性:

<context:property-placeholder 
 location="" 
 file-encoding="" 
 ignore-resource-not-found="" 
 ignore-unresolvable="" 
 properties-ref="" 
 local-override="" 
 system-properties-mode="" 
 order="" 
/>

ignore-resource-not-found:如果属性文件找不到,是否忽略,默认false,即不忽略,找不到将抛出异常

ignore-unresolvable:是否忽略解析不到的属性,如果不忽略,找不到将抛出异常

order:当配置多个<context:property-placeholder/>时的查找顺序

不推荐将ignore-resource-not-found和ignore-unresolvable的值设置为ture,默认为false,可以有效避免程序运行异常。

使用PropertySource注解配置

Spring3.1添加了@PropertySource注解,方便添加property文件到环境.

properties的注入与使用

java中使用@Value注解获取:

@Value( "${jdbc.url}" )
private String jdbcUrl;

在Spring的xml配置文件中获取:

<bean id="dataSource">
 <property name="url" value="${jdbc.url}" />
</bean>

配置多个property-placeholder属性

Spring容器是采用反射扫描的发现机制,通过标签的命名空间实例化实例,当Spring探测到容器中有一个org.springframework.beans.factory.config.PropertyPlaceholderCVonfigurer的Bean就会停止对剩余PropertyPlaceholderConfigurer的扫描,即只能存在一个实例!

所以一遍不建议配置多个property-placeholder对象,但是在必须使用多个的场景下,如何配置呢?

<context:property-placeholder location="xxx.properties" ignore-unresolvable="true"/>
<context:property-placeholder location="xxx.properties" ignore-unresolvable="true"/>

需要设置ignore-unresolvable=”true”,否则后面的property-placeholder不会被加载;ignore-unresolvable单独使用来看是“是否忽视不存在的配置项”,不仅如此,其还有一个隐含意思:是否还要扫描其他配置项:如果为false,则会忽视后续的property-placeholder,如果需要配置多个property-placeholder则应该设置为true;

context:property-placeholder 工作原理

在 ContextNamespaceHandler 中对于 context中的property-placeholder 标签,会采用PropertyPlaceholderBeanDefinitionParser解析器进行解析;

public class ContextNamespaceHandler extends NamespaceHandlerSupport {
 @Override public void init() { 
    registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser()); 
    registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser()); 
    registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser()); 
    registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser()); 
    registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser()); 
    registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser()); 
    registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser()); 
    registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser()); 
  }
}

PropertyPlaceholderBeanDefinitionParser解析器会将property-placeholder 标签解析为一个PropertySourcesPlaceholderConfigurer的单例 bean 。

可以看出 PropertySourcesPlaceholderConfigurer 或者 PropertyPlaceholderConfigurer 仅仅是做了一个配置文件的解析工作,真正的注入并不由它们完成,而是托付给了Spring 的Bean初始化流程。
之所以这么做可以生效,是因为这两个类实现了 BeanFactoryPostProcessor 接口,这个接口的优先级高于后续的Spring Bean。

属性元素的注入依赖于 AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues。 通过解析PropertySourcesPlaceholderConfigurer 查询得到元素值。

public PropertyValues postProcessPropertyValues(PropertyValues pvs, 
PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
 InjectionMetadata metadata = this.findAutowiringMetadata(beanName, bean.getClass());
    try {
        metadata.inject(bean, beanName, pvs);
        return pvs;
    } catch (Throwable var7) {
        throw new BeanCreationException(beanName,
        "Injection of autowired dependencies failed", var7);
    }
 }

PropertySourcesPlaceholderConfigurer本质上是一个BeanFactoryPostProcessor。解析XML的流程在BeanFactoryPostProcessor之前, 优先将配置文件的路径以及名字通过Setter传入PropertySourcesPlaceholderConfigurer。

如上BeanFactoryPostProcessor的优先级又优于其余的Bean。因此可以实现在bean初始化之前的注入。

Spring @Value注入流程

  1. Spring Context 的初始化开始
  2. 读取到context:property-placeholder标签或者PropertySourcesPlaceholderConfigurer
  3. 解析并实例化一个PropertySourcesPlaceholderConfigurer。同时向其中注入配置文件路径、名称
  4. PropertySourcesPlaceholderConfigurer自身生成多个StringValueResolver备用,Bean准备完毕
  5. Spring在初始化非BeanFactoryPostProcessor的Bean的时候,AutowiredAnnotationBeanPostProcessor 负责找到Bean内有@Value注解的Field或者Method
  6. 通过PropertySourcesPlaceholderConfigurer寻找合适的StringValueResolver并解析得到val值。注入给@Value的Field或Method。(Method优先)2
  7. Spring的其他流程。

 

参考:

http://blog.csdn.net/qyp199312/article/details/54313784

Molly 安装与测试

Molly下载地址:https://github.com/palvaro/molly

首先阅读tutorial.md文件,安装方法按照Installation.md来执行;

需要注意点:

  1. 在mac OS下不能使用brew install来安装apr、apr-util,需要下载这两个组件的源码,通过make、install的方式进行安装;
  2. bin 目录下只有c4,缺少z3的安装文件,需要自己下载安装;
  3. 依赖安装完毕后,需要将依赖的库添加到PATH中;

安装Scala构建工具:sbt

brew install sbt@1

参考:http://www.scala-sbt.org/download.html

继续阅读

《那时花开》

作品:《那时花开》   字数:约 35000 字      体裁:中篇小说    关键字:校园青春

背景:小说记录了自己以在高中时期一群小伙伴的学习生活,作者:陈晓雷

袁河是高二上学期转到陆可凡他们班的。至于转班的原因却不得而知。不过众所周知的是,陆可凡他们班的语文老师是袁河的爸爸,所以就有人猜测这可能是他爸爸的注意,目的很简单,无非就是为了方便监督和管教儿子学习。那为什么到了高二才转班呢?答案也很简单,因为高二是承上启下的关键学期,既能延续高一时的学习状态,又能为高三做准备,所以这时转班最合适不过了。

转到陆可凡他们班上后,袁河发现了一个奇怪的现象。

比如一般课间休息的时候,同学们都会以固有的方式来放松自己。其中少数同学会走出教室,站在外面的走廊上,抬头仰望天空,认真盘算自己忧伤的心事。或者靠在旁边的栏杆上,低头看着地面,仔细回忆某天的快乐心情。而大多数同学则会三五成群地聚在一起,找一个大家都感兴趣的话题,然后各抒己见,开始谈论。 继续阅读

Taobao SSO 跨域登录过程解析

今年的双十一和双十二已经告一段落,你是否买到了你想要的宝贝呢?我们知道双十一是天猫的主场,双十二是淘宝的主场,你有没有注意到你在登录了淘宝后,访问天猫或者飞猪,你还是处于登录态的,但是我们知道cookie是不能跨域的,那么阿里是如何做到了多域名下的登录态同步呢?接下来我们通过抓包进行请求解析来了解这个过程。

基础知识:

  1. 如果忘了Cookie和Session的区别,那么建议你先回顾一下,可以参考:https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/06.1.md
  2. 如果不知道为什么需要鉴权,为什么需要SSO,为什么需要跨域登录,建议你先阅读上一篇文章“系统权限控制”。

继续阅读

系统权限控制体系

在 Web 应用开发中,安全一直是非常重要的一个方面。安全虽然属于应用的非功能性需求,但是应该在应用开发的初期就考虑进来。比如我们开放的功能页面需要登录授权之后才能访问,一些功能需要具备特定权限的人才能操作;再比如我们开放了数据API接口,如果不做访问控制,那么任何人都可以调用,当被不法分子操作时将给我们带来巨大的麻烦。那么在Java 整个体系中访问控制是否有一套理论技术支撑呢,我们是否可以做一个通用性的访问控制系统来完成分布式系统架构下的复杂的权限控制?接下来会一一介绍。

访问控制的本质:

系统权限控制 本质上是访问控制(Access Control),那访问控制的本质又是什么呢?其实就是合法的访问受保护的资源,通俗的解释就是“【谁】是否有可以对某个【资源】进行某种【操作】”;可以看出访问控制的三个基本要素:主体(请求实体)、客体(资源实体)、控制策略(属性集合);

访问控制需要完成的两个任务:

  1. 识别和确认访问系统的用户;
  2. 决定该用户可以对某一系统资源进行何种类型的访问;

继续阅读

应用架构设计原则

软件系统架构设计原则就是把我们在各种场景下的架构设计进行抽选化提取公共特征形成过一定的方法论,这些方法论是经过严格推敲并具备移植性的,我们在设计系统时遵从这些设计规则可以为我们的体统提供更高的扩展性、稳定性。

抽象原则

各平台(含基础设施、中间件技术服务、各层业务服务等)需要通过合理地抽象,将内部信息、处理与扩展能力聚合成标准的服务于扩展接口,并通过统一的形式提供给使用者,屏蔽内部的实现与运行细节。

继续阅读