Spring中BeanPostProcessors【2】优雅实现业务分离

1 概述
BeanPostProcessors可以在spring IoC容器初始化受管Bean前、属性设置后对该Bean先做一些预处理,或者在容器销毁受管Bean之前自己释放资源。《Spring中BeanPostProcessors【1】简单预处理》一文有实例说明。本文介绍一个具体案例,优雅实现业务分离。


2 基础类

设想一个系统中分很多模块,对于模块又有不同的操作命令,对于不同模块的不同命令场景,会有不同的处理。当然通过if else判断可以实现,但可读性和优雅性太差。下面采取注解+BeanPostProcessors的方式优雅实现。

2.1 注解类

package com.xy.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Module {

	/**
	 * 模块号
	 */
	short moduleId();
}


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface BizCommand {

	/**
	 * 命令号
	 */
	short cmdId();
}


2.2 常量类

package com.xy.constants;
public interface ConstantCmd {

	// 添加
	public short ADD = 1;

	// 删除
	public short DELETE = 2;
}

public interface ConstantModule {

	// 学生模块
	public short STUDENT = 1;
	
	// 教师模块
	public short TEACHER = 2;
}


2.3 业务类

package com.xy.service;
import com.xy.annotation.BizCommand;
import com.xy.annotation.Module;
import com.xy.constants.ConstantCmd;
import com.xy.constants.ConstantModule;

@Module(moduleId = ConstantModule.STUDENT)
public interface StuService {

	@BizCommand(cmdId = ConstantCmd.ADD)
	public void add(String name);
	
	@BizCommand(cmdId = ConstantCmd.DELETE)
	public void delete(String name);
}


import org.springframework.stereotype.Component;

@Component // 该类需要被Spring托管
public class StuServiceImpl implements StuService {

	public void add(String name) {
		System.out.println("I am student add method.add name:" + name);
	}

	public void delete(String name) {
		System.out.println("I am student delete method.delete name:" + name);
	}

}

3 核心类

总体思路是利用模块号+命令号对应不同的方法和实现类,方法和实现类被存在对应列表中。

传入模块号和命令号,即可获取对应的方法名和实现类,执行即可。

package com.xy.scanner;

import java.lang.reflect.Method;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
import com.xy.annotation.BizCommand;
import com.xy.annotation.Module;

@Component // 该类也需要被Spring托管
public class BizScanner implements BeanPostProcessor {

	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

		// 容器管理的类信息(stuServiceImpl)
		Class<? extends Object> clazz = bean.getClass();

		// 该类实现的接口(stuService)
		Class<?>[] interfaces = clazz.getInterfaces();

		if (null != interfaces && interfaces.length > 0) {
			for (Class<?> interFace : interfaces) {
				
				// 获取接口注解
				// 模块信息
				Module module = interFace.getAnnotation(Module.class);
				if (null == module)
					continue;

				// 该接口所有方法
				Method[] methods = interFace.getMethods();
				if (null != methods && methods.length > 0) {
					for (Method method : methods) {
						// 命令信息
						BizCommand bizCommand = method.getAnnotation(BizCommand.class);
						if (null == bizCommand)
							continue;

						// 模块号
						short moduleId = module.moduleId();
						// 命令号
						short cmdId = bizCommand.cmdId();
						if (BizInvokerManager.getInvoker(moduleId, cmdId) == null) {
							BizInvokerManager.addInvoker(moduleId, cmdId, BizInvoker.valueOf(method, bean));
						} else {
							System.out.println("重复命令:" + "module:" + moduleId + " " + "cmdId:" + cmdId);
						}
					}
				}
			}
		}
		return bean;
	}
}


import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 命令执行器
 */
public class BizInvoker {

	/**
	 * 方法
	 */
	private Method method;

	/**
	 * 目标对象(实现类)
	 */
	private Object target;

	/**
	 * 封装执行器
	 * 
	 * @param method 方法 com.xy.service.StuService.add
	 * @param target 目标 com.xy.service.StuServiceImpl@273e07bd
	 * @return 执行器
	 */
	public static BizInvoker valueOf(Method method, Object target) {
		BizInvoker invoker = new BizInvoker();
		invoker.setMethod(method);
		invoker.setTarget(target);
		return invoker;
	}

	/**
	 * 调用方法
	 * 
	 * @param paramValues 参数
	 * @return 执行结果
	 */
	public Object invoke(Object... paramValues) {
		try {
			// method 方法 com.xy.service.StuService.add
			// target 目标 com.xy.service.StuServiceImpl@273e07bd
			return method.invoke(target, paramValues);
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		return null;
	}

	public Method getMethod() {
		return method;
	}

	public void setMethod(Method method) {
		this.method = method;
	}

	public Object getTarget() {
		return target;
	}

	public void setTarget(Object target) {
		this.target = target;
	}
}


import java.util.HashMap;
import java.util.Map;

/**
 * 命令执行器管理者
 */
public class BizInvokerManager {

	/**
	 * 命令调用器(第1个short是模块号,第2个short是命令号)
	 */
	private static Map<Short, Map<Short, BizInvoker>> invokers = new HashMap<Short, Map<Short, BizInvoker>>();

	/**
	 * 添加命令调用
	 * 
	 * @param module 模块号
	 * @param cmd 命令号
	 * @param invoker 调用器
	 */
	public static void addInvoker(short moduleId, short cmdId, BizInvoker invoker) {
		Map<Short, BizInvoker> map = invokers.get(moduleId);
		if (null == map) {
			map = new HashMap<Short, BizInvoker>();
			invokers.put(moduleId, map);
		}
		map.put(cmdId, invoker); // 改变引用,将命令号存入
	}

	/**
	 * 获取命令调用
	 * 
	 * @param module 模块号
	 * @param cmd 命令号
	 */
	public static BizInvoker getInvoker(short moduleId, short cmdId) {
		Map<Short, BizInvoker> map = invokers.get(moduleId);
		if (map != null) {
			return map.get(cmdId);
		}
		return null;
	}

}


4 Spring文件

<context:component-scan base-package="com.xy.scanner" />
<context:component-scan base-package="com.xy.service" />

5 测试

package com.xy.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.xy.constants.ConstantCmd;
import com.xy.constants.ConstantModule;
import com.xy.scanner.BizInvoker;
import com.xy.scanner.BizInvokerManager;

public class TestBean {

	public static void main(String[] args) {
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
		System.out.println(ac);

		BizInvoker invoker1 = BizInvokerManager.getInvoker(ConstantModule.STUDENT, ConstantCmd.ADD);
		invoker1.invoke("xy1");

		System.out.println("========================");

		BizInvoker invoker2 = BizInvokerManager.getInvoker(ConstantModule.STUDENT, ConstantCmd.DELETE);
		invoker2.invoke("xy2");
	}
}
发布了535 篇原创文章 · 获赞 1162 · 访问量 450万+

猜你喜欢

转载自blog.csdn.net/woshixuye/article/details/54705884