Spring源码中的一段设计

模式类型


        在Spring的源码里看到下面一段代码,使用方法感觉挺巧妙的,记录下来一下。

ReflectiveAspectJAdvisorFactory:

	private List getAdvisorMethods(Class aspectClass) {
		final List methods = new LinkedList();
		// 设计巧妙的地方正是这个地方:ReflectionUtils.MethodCallback()
		// 1,MethodCallback是一个类内部定义的接口,这样可以明确这个接口是为这个类服务的。
		// 2,当前类想得取符合自己想要的条件的对象,这些条件只有自己需要,所以在这里写条件的实现。
		//       当前类没有Method对象集合,把这些条件告诉有集合的对象:我把我的条件给你,请你把符合这些条件的对象给我。
		ReflectionUtils.doWithMethods(aspectClass, new ReflectionUtils.MethodCallback() {
			@Override
			public void doWith(Method method) throws IllegalArgumentException {
				// Exclude pointcuts
				if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
					methods.add(method);
				}
			}
		});
		Collections.sort(methods, METHOD_COMPARATOR);
		return methods;
	}

下面看一下ReflectionUtils.doWithMethods里面调用的doWithMethods方法的实现:
	public static void doWithMethods(Class clazz, MethodCallback mc, MethodFilter mf) {
		// Keep backing up the inheritance hierarchy.
		Method[] methods = getDeclaredMethods(clazz);
		for (Method method : methods) {
			if (mf != null && !mf.matches(method)) {
				continue;
			}
			try {
				// 这个地方就是调用我们写的回调函数的地方
				// 这里持有Method集合
				mc.doWith(method);
			}
			catch (IllegalAccessException ex) {
				throw new IllegalStateException("Not allowed to access method '" + method.getName() + "': " + ex);
			}
		}
		if (clazz.getSuperclass() != null) {
			doWithMethods(clazz.getSuperclass(), mc, mf);
		}
		else if (clazz.isInterface()) {
			for (Class superIfc : clazz.getInterfaces()) {
				doWithMethods(superIfc, mc, mf);
			}
		}
	}

模式的使用

    
        这样的模式使用在什么地方呢?感觉这个模式和模板模式有点像,把共同的处理集中起来,把特殊处理写成接口,让使用它的地方自己实现。实现接口的地方可以做自己想做的事,例如:
  • 定制条件,取得其它集合中符合条件数据
  • 执行我们要想做的处理
“执行我们想要做的处理”这个使用方法,曾经做过一次。使用Mybatis和Mysql的系统上,要做批量插入。DAO方法是用注解(@Insert)写的,例如:
    @(Insert "Insert Into XXX ......")
    void insertUserInfo(User user);

很多地方要这么写,于是写了一个抽象类,抽象类的作用:
  • 控制循环。例如:10000插入后次执行一次Batch
  • 暴露一个回调让使用者去实现,只要把自己要执行的DAO方法写里面就可以。

实现如下:
public abstract class AbstractBatchCommit {

    /**
     * 执行每N条记录更新一次数据库
     * @author shijiapeng
     * @date 2016年9月22日
     * @param list
     */
    public void commitBatch(List list) {
        try{
            // 声明存储N条记录的List
            List commitList = new ArrayList(Constants.BATCH_COMMIT_SIZE);
            for(int idx = 0; idx < list.size(); idx++){
                commitList.add(list.get(idx));
                // 每N条数据执行更新一歆 
                if(idx !=0 && (idx + 1)%Constants.BATCH_COMMIT_SIZE == 0){
                    // 批量更新数据库
                    callSQL(commitList);
                    // 清空list
                    commitList.clear();
                }
            }
            
            // 小于N条,或者N条以上的零头时,执行一次
            if(!commitList.isEmpty()){
                callSQL(commitList);
            }
            
        } catch(Exception e){
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
    
    /*
     * 调用SQL语句
     */
    public abstract void callSQL(List list) throws SQLException;
}







你可能感兴趣的:(spring,设计模式)