AdvisedSupport.java 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. package cn.nosum.framework.aop.support;
  2. import cn.nosum.framework.aop.aspect.Advice;
  3. import cn.nosum.framework.aop.config.AopConfig;
  4. import cn.nosum.util.StringUtils;
  5. import java.lang.reflect.Method;
  6. import java.util.HashMap;
  7. import java.util.Map;
  8. import java.util.regex.Pattern;
  9. import java.util.regex.Matcher;
  10. public class AdvisedSupport {
  11. // 保存读取到的配置
  12. private AopConfig config;
  13. private Object target;
  14. private Class targetClass;
  15. private Pattern pointCutClassPattern;
  16. private Map<Method,Map<String,Advice>> methodCache;
  17. public AdvisedSupport(AopConfig config) {
  18. this.config = config;
  19. }
  20. // 解析配置文件的方法
  21. private void parse() {
  22. // 把 Spring 的 Expression 变成Java能够识别的正则表达式
  23. String pointCut = config.getPointCut()
  24. .replaceAll("\\.", "\\\\.")
  25. .replaceAll("\\\\.\\*", ".*")
  26. .replaceAll("\\(", "\\\\(")
  27. .replaceAll("\\)", "\\\\)");
  28. // 保存专门匹配 Class 的正则
  29. String pointCutForClassRegex = pointCut.substring(0, pointCut.lastIndexOf("\\(") - 4);
  30. pointCutClassPattern = Pattern.compile("class " + pointCutForClassRegex.substring(pointCutForClassRegex.lastIndexOf(" ") + 1));
  31. if (pointCutMath()){
  32. // 缓存
  33. this.methodCache = new HashMap<Method, Map<String, Advice>>();
  34. // 保存专门匹配方法的正则
  35. Pattern pointCutPattern = Pattern.compile(pointCut);
  36. try{
  37. // 切面类,用户自己定义
  38. Class aspectClass = Class.forName(this.config.getAspectClass());
  39. Map<String,Method> aspectMethods = new HashMap<String, Method>();
  40. // 取得切面类中的所有方法
  41. for (Method method : aspectClass.getMethods()) {
  42. aspectMethods.put(method.getName(),method);
  43. }
  44. // 取得目标代理对象的所有方法
  45. for (Method method : this.targetClass.getMethods()) {
  46. String methodString = method.toString();
  47. // 截取方法名称
  48. if(methodString.contains("throws")){
  49. methodString = methodString.substring(0,methodString.lastIndexOf("throws")).trim();
  50. }
  51. // 判断是否在切面的范围
  52. Matcher matcher = pointCutPattern.matcher(methodString);
  53. if(matcher.matches()){
  54. Map<String,Advice> advices = new HashMap<String, Advice>();
  55. // 增加方法执行前的切面
  56. if(StringUtils.isNotEmpty(config.getAspectBefore())){
  57. advices.put("before",new Advice(aspectClass.newInstance(),aspectMethods.get(config.getAspectBefore())));
  58. }
  59. // 增加方法执行后的切面
  60. if(StringUtils.isNotEmpty(config.getAspectAfter())){
  61. advices.put("after",new Advice(aspectClass.newInstance(),aspectMethods.get(config.getAspectAfter())));
  62. }
  63. // 增加方法执行异常的切面
  64. if(StringUtils.isNotEmpty(config.getAspectAfterThrow())){
  65. Advice advice = new Advice(aspectClass.newInstance(),aspectMethods.get(config.getAspectAfterThrow()));
  66. // 设置要捕获的异常
  67. advice.setThrowName(config.getAspectAfterThrowingName());
  68. advices.put("afterThrow",advice);
  69. }
  70. // 跟目标代理类的业务方法和 Advices 建立一对多关联关系,以便在 Proxy 类中获得
  71. this.methodCache.put(method,advices);
  72. }
  73. }
  74. }catch(Exception e){
  75. e.printStackTrace();
  76. }
  77. }
  78. }
  79. // 根据一个目标代理类的方法,获得其对应的通知
  80. public Map<String,Advice> getAdvices(Method method) throws NoSuchMethodException {
  81. //享元设计模式的应用
  82. Map<String,Advice> cache = methodCache.get(method);
  83. if(null == cache){
  84. // 如果是通过父类的接口调用,无法根据key进行获取,此时,取得子类方法,并且调用
  85. Method m = targetClass.getMethod(method.getName(),method.getParameterTypes());
  86. cache = methodCache.get(m);
  87. // 缓存
  88. this.methodCache.put(method,cache);
  89. }
  90. return cache;
  91. }
  92. // IOC 中的对象初始化时调用,决定要不要生成代理类的逻辑
  93. public boolean pointCutMath() {
  94. return pointCutClassPattern.matcher(this.targetClass.toString()).matches();
  95. }
  96. public void setTargetClass(Class<?> targetClass) {
  97. this.targetClass = targetClass;
  98. parse();
  99. }
  100. public void setTarget(Object target) {
  101. this.target = target;
  102. }
  103. public Class getTargetClass() {
  104. return targetClass;
  105. }
  106. public Object getTarget() {
  107. return target;
  108. }
  109. }