123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- package cn.nosum.framework.aop.support;
- import cn.nosum.framework.aop.aspect.Advice;
- import cn.nosum.framework.aop.config.AopConfig;
- import cn.nosum.util.StringUtils;
- import java.lang.reflect.Method;
- import java.util.HashMap;
- import java.util.Map;
- import java.util.regex.Pattern;
- import java.util.regex.Matcher;
- public class AdvisedSupport {
- // 保存读取到的配置
- private AopConfig config;
- private Object target;
- private Class targetClass;
- private Pattern pointCutClassPattern;
- private Map<Method,Map<String,Advice>> methodCache;
- public AdvisedSupport(AopConfig config) {
- this.config = config;
- }
- // 解析配置文件的方法
- private void parse() {
- // 把 Spring 的 Expression 变成Java能够识别的正则表达式
- String pointCut = config.getPointCut()
- .replaceAll("\\.", "\\\\.")
- .replaceAll("\\\\.\\*", ".*")
- .replaceAll("\\(", "\\\\(")
- .replaceAll("\\)", "\\\\)");
- // 保存专门匹配 Class 的正则
- String pointCutForClassRegex = pointCut.substring(0, pointCut.lastIndexOf("\\(") - 4);
- pointCutClassPattern = Pattern.compile("class " + pointCutForClassRegex.substring(pointCutForClassRegex.lastIndexOf(" ") + 1));
- if (pointCutMath()){
- // 缓存
- this.methodCache = new HashMap<Method, Map<String, Advice>>();
- // 保存专门匹配方法的正则
- Pattern pointCutPattern = Pattern.compile(pointCut);
- try{
- // 切面类,用户自己定义
- Class aspectClass = Class.forName(this.config.getAspectClass());
- Map<String,Method> aspectMethods = new HashMap<String, Method>();
- // 取得切面类中的所有方法
- for (Method method : aspectClass.getMethods()) {
- aspectMethods.put(method.getName(),method);
- }
- // 取得目标代理对象的所有方法
- for (Method method : this.targetClass.getMethods()) {
- String methodString = method.toString();
- // 截取方法名称
- if(methodString.contains("throws")){
- methodString = methodString.substring(0,methodString.lastIndexOf("throws")).trim();
- }
- // 判断是否在切面的范围
- Matcher matcher = pointCutPattern.matcher(methodString);
- if(matcher.matches()){
- Map<String,Advice> advices = new HashMap<String, Advice>();
- // 增加方法执行前的切面
- if(StringUtils.isNotEmpty(config.getAspectBefore())){
- advices.put("before",new Advice(aspectClass.newInstance(),aspectMethods.get(config.getAspectBefore())));
- }
- // 增加方法执行后的切面
- if(StringUtils.isNotEmpty(config.getAspectAfter())){
- advices.put("after",new Advice(aspectClass.newInstance(),aspectMethods.get(config.getAspectAfter())));
- }
- // 增加方法执行异常的切面
- if(StringUtils.isNotEmpty(config.getAspectAfterThrow())){
- Advice advice = new Advice(aspectClass.newInstance(),aspectMethods.get(config.getAspectAfterThrow()));
- // 设置要捕获的异常
- advice.setThrowName(config.getAspectAfterThrowingName());
- advices.put("afterThrow",advice);
- }
- // 跟目标代理类的业务方法和 Advices 建立一对多关联关系,以便在 Proxy 类中获得
- this.methodCache.put(method,advices);
- }
- }
- }catch(Exception e){
- e.printStackTrace();
- }
- }
- }
- // 根据一个目标代理类的方法,获得其对应的通知
- public Map<String,Advice> getAdvices(Method method) throws NoSuchMethodException {
- //享元设计模式的应用
- Map<String,Advice> cache = methodCache.get(method);
- if(null == cache){
- // 如果是通过父类的接口调用,无法根据key进行获取,此时,取得子类方法,并且调用
- Method m = targetClass.getMethod(method.getName(),method.getParameterTypes());
- cache = methodCache.get(m);
- // 缓存
- this.methodCache.put(method,cache);
- }
- return cache;
- }
- // IOC 中的对象初始化时调用,决定要不要生成代理类的逻辑
- public boolean pointCutMath() {
- return pointCutClassPattern.matcher(this.targetClass.toString()).matches();
- }
- public void setTargetClass(Class<?> targetClass) {
- this.targetClass = targetClass;
- parse();
- }
- public void setTarget(Object target) {
- this.target = target;
- }
- public Class getTargetClass() {
- return targetClass;
- }
- public Object getTarget() {
- return target;
- }
- }
|