spring 设计模式    2016-03-17 19:11:57    721    0    0

本文将会不断总结更新

工厂方法模式

Spring中提供了FactoryBean接口,用于创建各种不同的Bean。
title
开发人员也可以自己实现该接口,常用于框架集成。比如mybatis-spring-1.1.0.jar包中的SqlSessionFactoryBean就是如此。

模板方法模式

Spring针对JDBC,JMS,JPA等规范,都提供了相应的模板方法类,如JdbcTemplate,JmsTemplate, JpaTemplate
例如JdbcTemplate,它提供了很多常用的增加,删除,查询,修改方法模板。而JMSTemplate则提供了对于消息的发送,接收方法等。下面是JMSTemplate的部分方法图:
title

代理模式

Spring中AOP,事务等都大量运用了代理模式。

观察者模式

Spring中提供了一种事件监听机制,即ApplicationListener,可以实现Spring容器内的事件监听。可以参考这里
主要是以下两个接口:
发布消息
title
监听消息
title

单例模式

Spring默认的创建Bean的作用域就是单例,即每个Spring容器中只存在一个该类的实例。可以通过@Scope(“prototype”)来修改成prototype模式,prototype在设计模式中叫做原型模式,实际上,Spring中对于@Scope(“prototype”)标记的Bean的处理的确是原型模式。

原型模式

原型模式是创建型模式的一种,其特点在于通过“复制”一个已经存在的实例来返回新的实例,而不是新建实例。被复制的实例就是我们所称的“原型”,这个原型是可定制的。
原型模式多用于创建复杂的或者耗时的实例,因为这种情况下,复制一个已经存在的实例使程序运行更高效;或者创建值相等,只是命名不一样的同类数据。

Spring中,如果一个类被标记为”prototype”,每一次请求(将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法)都会产生一个新的bean实例。
但是,Spring不能对一个prototype Bean的整个生命周期负责,容器在初始化、配置、装饰或者

代码    2016-03-17 18:31:50    417    0    0

代码如下:

private static final Map<String, AtomicInteger> map = new HashMap<String, AtomicInteger>();
    private static final Object locker = new Object();

    public void increase(String key) {
        AtomicInteger count = map.get(key);
        if (count == null) {
            synchronized (locker) {
                if (map.get(key) == null) {
                    count = new AtomicInteger();
                    map.put(key, count);
                }
            }
        }
        count.incrementAndGet();
    }

上面的代码会报空指针异常
正确代码应该如下:

private static final Map<String, AtomicInteger> map = new HashMap<String, AtomicInteger>();
    private static final Object locker = new Object();

    public void increase(String key) {
        if (map.get(key) == null) {
            synchronized (locker) {
                if (map.get(key) == null) {
                    count = new AtomicInteger();
                    map.put(key, count);
 
设计模式 java    2016-03-16 19:01:09    635    0    0

相同点

  1. 简单工厂,工厂方法,抽象工厂都属于设计模式中的创建型模式。
  2. 主要功能都是帮助我们把对象的实例化部分抽取了出来,优化了系统的架构,并且增强了系统的扩展性。

不同点

类图

简单工厂:
title
工厂方法:
title
抽象工厂:
title

应用场景

简单工厂:适合创建同一级别的不同对象。
工厂方法:为每种产品提供一个工厂类,通过不同的工厂实例来创建不同的产品。工厂方法模式中我们把生成产品类的时间延迟,就是通过对应的工厂类来生成对应的产品类,在这里我们就可以实现“开发-封闭”原则,无论加多少产品类,我们都不用修改原来类中的代码,而是通过增加工厂类来实现。但是这还是有缺点的,如果产品类过多,我们就要生成很多的工厂类。
抽象工厂:针对产品族,比如每个汽车公司都要同时生产轿车,货车,客车,那么每一个工厂都要有对应的生产轿车,货车和客车的方法。所以,抽象工厂类中一般会有多个抽象方法。什么是产品族呢?简单的理解就是,不同牌子产的车里面会有跑车类型,家庭类型,商用类型等的车,不同牌子的车的跑车类型的车可以组成一个产品族。抽象工厂模式中我们可以定义实现不止一个接口,一个工厂也可以生成不止一个产品类,抽象工厂模式较好的实现了“开放-封闭”原则,是三个模式中较为抽象,并具一般性的模式。

业务变更的差别

下面当我们看一下,需要增加产品的时候,三种模式都需要如何操作。
简单工厂:如果是新增同一类型的产品(都是实现Product接口的),那么需要在工厂类的ifelse中新增一个判断。客户端不需要做变更
工厂方法:新增一个产品,我们就需要新增加一个工厂类。客户端也需要变更。
抽象工厂:新增一类产品,比如新增跑车,那么需要修改抽象工厂以及所有的实现类,改动很大。新增某一个产品,比如新增一款颜色的轿车,也需要单独的工厂实现类。

简单工厂 :用来生产同一等级结构中的任意产品。(对于增加新的产品,无能为力)
工厂方法 :用来生产同一等级结构中的固定产品。(支持增加任意产品)
抽象工厂 :用来生产不同产品族的全部产品。(对于增加新的产品,无能为力;支持增加产品族)

JDK中的应用

简单工厂在JDK中的应用有很多:

java.te
docker 容器    2016-03-12 18:18:43    377    0    0

安装Docker

在Linux系统上,可以通过两种方式。

方式一:安装docker-engine

方式二:直接通过curl安装

curl -fsSL https://get.docker.com/ | sh

curl如果没有安装,则需要先安装curl
这种方式安装成功之后,会自动启动docker

运行Docker

docker启动之后,可以通过docker run命令来运行镜像。

运行镜像

Hello world

docker run hello-world

运行举例:

root@mine:~# docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
03f4658f8b78: Already exists 
a3ed95caeb02: Already exists 
Digest: sha256:8be990ef2aeb16dbcb9271ddfe2610fa6658d13f6dfb8bc72074cc1ca36966a7
Status: Downloaded newer image for hello-world:latest

Hello from Docker.
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
 3. The Docker daemon created a new container from that image which runs
redis nosql    2016-03-12 11:27:53    529    0    0
## Redis 3.0之前的集群方案 3.0之前,Redis并没有提供一套集群方案,我们用redis cluster用的最多的应该是twitter发布的[Twemproxy](https://github.com/twitter/twemproxy),还有就是豌豆荚开发的[codis](https://github.com/wandoulabs/codis)。 上面的两种都是以中间件的形式提供
日志 框架 源码    2016-03-07 16:09:42    487    0    0

Commons-Logging的使用

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class App
{
    private static final Log log = LogFactory.getLog(App.class);

    public static void main( String[] args ) {
        log.info("rizhi ....");
    }
}

启动过程分析

可以看到,Log是通过LogFactory.getLog(Class clzz)方法获取的。
而getLog方法内部又是通过getFactory()方法,先获取到LogFactory,然后再创建Log的。

所以,commons-logging在选在使用哪个日志实现的时候,实际上是先选择使用哪个LogFactory。下面我们就来看一下这个过程(LogFactory类的public static LogFactory getFactory() throws LogConfigurationException方法)。

1. 首先查找缓存的LogFactory,找到就直接返回,否则继续下一步

 // Identify the class loader we will be using
        ClassLoader contextClassLoader = getContextClassLoaderInternal();

        if (contextClassLoader == null) {
            // This is an odd enough situation to report about. This
            // output will be a nuisance on JDK1.1, as the system
            // classloader is null in that env
linux java    2016-03-06 11:13:53    466    0    0

Linux中查找Java位置

whereis java  # 查找java文件
which java # 查看java命令执行路径
echo $JAVA_HOME #打印JAVA_HOME环境变量
echo $PATH 

Linux中修改环境变量

修改全局文件(所有用户都生效)

修改/etc/profile文件

vi 此文件/etc/profile
在profile文件末尾加入:
export JAVA_HOME=/usr/share/jdk1.6.0_20
export PATH=JAVAHOME/bin:PATH
export CLASSPATH=.:JAVAHOME/lib/dt.jar:JAVA_HOME/lib/tools.jar

注意:上面的/usr/share/jdk1.6.0_20是JDK安装路径,可以通过which java查看。
修改完profile文件之后还没有生效,想要生效需要执行source profile命令。

修改.bash_profile文件 (某个用户权限使用这些环境变量)

.bash_profile文件末尾加入:
export JAVA_HOME=/usr/share/jdk1.6.0_20
export PATH=JAVAHOME/bin:PATH
export CLASSPATH=.:

tricks linux    2016-03-06 10:55:08    448    0    0

在Windows中,如果我们在某个文件夹下,按住Shift同时点击鼠标右键,出现的菜单中有一项叫做“在此处打开命令行窗口”,如下图:
cmd here

从这里打开命令行窗口之后,窗口中的路径就是当前目录下,这样就省去了切换目录的麻烦。

在Ubuntu中,默认没有该功能,如果要实现类似功能,需要安装一个软件:nautilus-open-terminal

sudo apt-get install nautilus-open-terminal

完成之后需要重启一下电脑,重启完成之后在任意目录下右键就有了。

PS:快速开启命令行 Ctrl+Alt+T,多个窗口通过Tab页的形式打开:Ctrl+Shift+T

日志 框架 源码    2016-03-05 12:24:49    2178    0    0

简介

在系统开发中,日志是很重要的一个环节,日志写得好对于我们开发调试,线上问题追踪等都有很大的帮助。但记日志并不是简单的输出信息,需要考虑很多问题,比如日志输出的速度,日志输出对于系统内存,CPU的影响等,为此,出现了很多日志框架,以帮助开发者解决这些问题。

java中的常用日志框架

比较常用的有Log4j,SLF4j,Commons-logging,logback。当然,JDK本身也提供了java.util.logging包来提供对日志的支持。

Commons-loggin:是apache最早提供的日志的门面接口。它的主要作用是提供一个日志门面,使用者可以使用不同的日志实现。用户可以自由选择第三方的日志组件作为具体实现,像log4j,或者jdk自带的logging, common-logging会通过动态查找的机制,在程序运行时自动找出真正使用的日志库。common-logging内部有一个Simple logger的简单实现,但是功能很弱。

SLF4j:是Simple Logging Facade for Java的简称,即java的简单日志门面。类似于Apache Common-Logging,是对不同日志框架提供的一个门面封装,可以在部署的时候不修改任何配置即可接入一种日志实现方案。但是,他在编译时静态绑定真正的Log库。使用SLF4J时,如果你需要使用某一种日志实现,那么你必须选择正确的SLF4J的jar包的集合(各种桥接包)。

Log4j:经典的一种日志解决方案。内部把日志系统抽象封装成Logger 、appender 、pattern等实现。我们可以通过配置文件轻松的实现日志系统的管理和多样化配置。pache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件、甚至是套接口服务器、NT的事件记录器、UNIXSyslog守护进程等;用户也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,用户能够更加细致地控制日志的生成过程。这些可以通过一个 配置文件来灵活地进行配置,而不需要修改程序代码。

logback:也是一种日志实现。Logback是由log4j创始人设

算法 基础 加密    2016-03-02 20:35:30    845    0    0

Base64 是什么?

Base64是一种数据表示方法,它使用64个可打印字符来表示二进制数据,所以才叫做Base64。

Base64 能做什么?

Base64一般用于处理文本数据,表示、传输、存储。比如MIME中的email,以及在xml中存储复杂数据。
编码
将普通数据转换成符合Base64标准的数据的过程。
解码
将Base64标准的数据转换成普通数据的过程。

Base64 的原理?

64个可打印字符

52个字母:大写字母+小写字母
10个数字:0~9
两个特殊字符:+ 和 /
以上就够64个了,但是有时候还会用一个“=”,等号的作用是填充,后面会讲到。

Base64字符对照表:

数值 字符 数值 字符 数值 字符 数值 字符
0 A 16 Q 32 g 48 w
1 B 17 R 33 h 49 x
2 C 18 S 34 i 50 y
3 D 19 T 35 j 51 z
4 E 20 U 36 k 52 0
5 F 21 V 37 l 53 1
6 G 22 W 38 m 54 2
7 H 23 X 39 n 55 3
8 I 24 Y 40 o 56 4
9 J 25 Z 41 p 57 5
10 K 26 a 42 q 58 6
11 L 27 b 43 r 59 7
12 M 28 c 44 s 60 8
13 N 29 d 45 t 61 9
14 O 30 e 46 u 62 +
15 P 31