Spring中BeanPostProcessors【2】优雅实现业务分离
2017-01-24 10:02
501 查看
1 概述
BeanPostProcessors可以在spring IoC容器初始化受管Bean前、属性设置后对该Bean先做一些预处理,或者在容器销毁受管Bean之前自己释放资源。《Spring中BeanPostProcessors【1】简单预处理》一文有实例说明。本文介绍一个具体案例,优雅实现业务分离。
2 基础类
设想一个系统中分很多模块,对于模块又有不同的操作命令,对于不同模块的不同命令场景,会有不同的处理。当然通过if else判断可以实现,但可读性和优雅性太差。下面采取注解+BeanPostProcessors的方式优雅实现。
【1】注解类
【2】常量类
【3】业务类
3 核心类
总体思路是利用模块号+命令号对应不同的方法和实现类,方法和实现类被存在对应列表中。
传入模块号和命令号,即可获取对应的方法名和实现类,执行即可。
4 Spring文件
5 测试
BeanPostProcessors可以在spring IoC容器初始化受管Bean前、属性设置后对该Bean先做一些预处理,或者在容器销毁受管Bean之前自己释放资源。《Spring中BeanPostProcessors【1】简单预处理》一文有实例说明。本文介绍一个具体案例,优雅实现业务分离。
2 基础类
设想一个系统中分很多模块,对于模块又有不同的操作命令,对于不同模块的不同命令场景,会有不同的处理。当然通过if else判断可以实现,但可读性和优雅性太差。下面采取注解+BeanPostProcessors的方式优雅实现。
【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】常量类
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; }
【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"); } }
相关文章推荐
- 简单模拟 spring的bean容器的实现
- 创建ApplicationContext与BeanFactory时的区别-Spring源码学习之容器的基本实现
- Spring学习笔记 使用annotation配置实现Bean的auto-wiring (自动绑定)
- 【Spring:FactoryBean接口】实现FactoryBean接口,Spring在初始化bean时有何不同
- Spring中用注解实现bean的定义以及作用域
- Spring基于注解实现Bean定义支持如下三种注解
- Spring 的 BeanPostProcessor接口实现
- 通过Spring @PostConstruct 和 @PreDestroy 方法 实现初始化和销毁bean之前进行的操作
- Spring的ApplicationContext.getBean()的具体实现
- spring4.0.2+mybatis3.2.4+sharding-jdbc1.4.2实现分库分表、读写分离及事物支持
- Spring中Bean多种实现切换方案
- Spring如何实现管理Bean的。
- 通过Spring @PostConstruct 和 @PreDestroy 方法 实现初始化和销毁bean之前进行的操作
- Spring 的 BeanPostProcessor接口实现
- spring源码初步学习-容器(BeanFactory)基本实现
- 通过Spring @PostConstruct 和 @PreDestroy 方法 实现初始化和销毁bean之前进行的操作
- Spring配置多数据源实现数据库读写分离
- SpringSession集成redis实现session共享(No bean named 'springSessionRepositoryFilter' available)
- spring3零配置注解实现Bean定义(包括JSR-250、JSR-330)
- 通过Spring @PostConstruct 和 @PreDestroy 方法 实现初始化和销毁bean之前进行的操作