原有项目无法启动junit测试,经过几番调整后,剔除了重复引用的多版本spring后,aop冲突解决了,测试junit没问题。

第二天再用junit测试,报这个错误。

java.lang.NoClassDefFoundError: org/junit/runner/Describable

Google之,junit4.4升级至4.5即可。可能跟easymock有关系。

easymock好用吗?不觉得使用,写代码量太大,用法学习成本也很高。

当junit报错找不到placeholder时,可以maven package一下。

定义:向下传递事件的模式即责任链模式。

1、事件类拥有共同的父类Event。
2、事件处理的类都要共同实现一个事件接口方法,方法参数为共同的事件父类。
3、事件处理类中含有下一级的事件处理类实例字段,定义为接口类型;
4、事件处理类的接口方法中通过instanceof判断是否本类处理,如果不是调用下一级的事件类来处理。

核心:某个接口的实现类中有这个接口的另一个实现类属性(字段),if not, field do same thing (invoke the same method)。

public class Event {
}
public class OneDayRestEvent extends Event {
}
public class TwoDayRestEvent extends Event {
}
public class FiveDayRestEvent extends Event {
}
public interface EventHandler {
    void handle(Event event);
}
public class LeaderEventHandler implements EventHandler{
    private EventHandler eventHandler;
    public LeaderEventHandler(EventHandler eventHandler){
        this.eventHandler=eventHandler;
    }
    @Override
    public void handle(Event event) {
        if(event instanceof OneDayRestEvent){
            System.out.println("do leaderEvent");
        }else{
            eventHandler.handle(event);
        }
    }
}
public class ManagerEventHandler implements EventHandler {
    private EventHandler eventHandler;
    public ManagerEventHandler(EventHandler eventHandler){
        this.eventHandler=eventHandler;
    }
    @Override
    public void handle(Event event) {
        if(event instanceof TwoDayRestEvent){
            System.out.println("do managerEvent");
        }else{
            eventHandler.handle(event);
        }
    }
}
public class DirectorEventHandler implements EventHandler {

    @Override
    public void handle(Event event) {
        System.out.println("do directorEvent");
    }
}
public class Test {
    public static void main(String[] args) {
        FiveDayRestEvent fiveDayRestEvent=new FiveDayRestEvent();
        OneDayRestEvent oneDayRestEvent=new OneDayRestEvent();
        TwoDayRestEvent twoDayRestEvent=new TwoDayRestEvent();

        EventHandler directorEventHandler=new DirectorEventHandler();
        //在链条中经理向下传递给总监
        EventHandler managerEventHandler=new ManagerEventHandler(directorEventHandler);
        //在链条中主管向下传递给经理
        EventHandler leaderEventHandler=new LeaderEventHandler(managerEventHandler);

        leaderEventHandler.handle(oneDayRestEvent);
        leaderEventHandler.handle(twoDayRestEvent);
        leaderEventHandler.handle(fiveDayRestEvent);
        System.out.println("=====================");
        managerEventHandler.handle(twoDayRestEvent);
        managerEventHandler.handle(fiveDayRestEvent);
        System.out.println("=====================");
        directorEventHandler.handle(fiveDayRestEvent);
    }
}

例:一天假只需组长审批,两天到五天假经理审批,五天以上总监审批。
这只是一种理论上的模式,真正应用时还需要增加很多逻辑来控制业务上责任链规则,比如如何判断是否本类执行,可能是instanceof判断,也可能设计个审批层级,大于某个level,manager处理等。

最近使用的会移至尾部,LinkedHashMap输出时其元素是有顺序的,HashMap是无序的,因为hashMap没有双向链表,只是根据hashcode的值决定存储在数组中哪个位置;

LinkedHashMap可以作为LRU的一个实现,自带核心方法 removeEldestEntry(),默认返回false。

自己可以继承这个类,重写 removeEldestEntry方法,当put时,会调用。

一般场景,当map.size()>maxCapacity 时,返回true,意味着在put时会移除掉最老的那个。

 

Spring 2.0以后有了AbstractRoutingDataSource 抽象类

里面有两个核心方法

determineTargetDataSource()
determineCurrentLookupKey()

所有的待切换的数据源都存在map中,所以切哪个目标数据源targetDataSource,要看能够lookup到哪个key。

自定义一个DynamicDataSource AbstractRoutingDataSource  然后实现determineCurrentLookupKey()这个方法,这个方法返回哪个key对应的dataSource,你就访问到了哪个数据源。

 

Spring配置里

先配置好dataSource,dataSourceRead和dataSourceWrite

<bean id="dynamicDataSource" class="com.goglezon.dao.DynamicDataSource">  
   <property name="targetDataSources">     
      <map key-type="java.lang.String">     
         <entry key="read" value-ref="dataSourceRead"/>     
         <entry key="write" value-ref="dataSourceWrite"/>     
      </map>     
   </property>     
   <property name="defaultTargetDataSource" ref="dataSource"/>    
</bean> 

Got it。

 

JDK8

主结构为Node<K,V>数组。数组下标为(size()-1)&hash。注意TreeNode为Node子类。所以数组中实际存储的可能为Node,也可能为TreeNode红黑树结构。

Node(int hash, K key, V value, Node<K,V> next) {
    this.hash = hash;
    this.key = key;
    this.value = value;
    this.next = next;
}

当冲突小于阈值时,数组中存储Node链表。

当大于阈值时,数组中存储的是TreeNode。存储时有将Node转换为TreeNode的操作过程。

static final class TreeNode<K,V> extends LinkedHashMap.Entry<K,V> {
    TreeNode<K,V> parent;  // red-black tree links
    TreeNode<K,V> left;
    TreeNode<K,V> right;
    TreeNode<K,V> prev;    // needed to unlink next upon deletion
    boolean red;
    TreeNode(int hash, K key, V val, Node<K,V> next) {
        super(hash, key, val, next);
    }
}
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
    treeifyBin(tab, hash);

网上有人说是将自动HashMap转换为TreeMap是严重错误,实际是Node转为TreeNode。

Entry<K,V> extends HashMap.Node<K,V>;

TreeNode 继承 LinkedHashMap.Entry 继承 Node

 

resize() to double currentCapacity

default init capacity 16

default loadFactor 0.75

threshHold=loadFactor*capacity