AOP 学习笔记

AOP: 面向切面编程

百度百科上官方的解释是:在Spring中提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事务(transaction)管理)进行内聚性的开发。应用对象只实现它们应该做的——完成业务逻辑——仅此而已。它们并不负责(甚至是意识)其它的系统级关注点,例如日志或事务支持。
主要功能
日志记录,性能统计,安全控制,事务处理,异常处理等等。
主要意图
将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。

因此在实现AOP时,就无法避免使用代理(proxy)技术。JDK本身提供了JDKProxy,还可以通过cglib-nodep-2.1.3.jar使用cglibProxy。spring的实现思路是,如果方法本身实现了某个接口,则使用jdkProxy,否者使用cglibProxy。

代理的具体使用方法:

在生成对象时,可以通过调用getProxy方法传入类类型或者一个实例对象来获得代理,代理对象可以调用原对象的成员及方法;通过代理调用方法并不是执行方法本身,而是跳转到代理代理机制中执行。jdkProxy和cjlibProxy都给出了接口,用户可以在这里实现方法的执行以及拦截器添加等逻辑。
使用jdkProxy需要实现下面的方法:
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
}
使用cglibProxy需要实现下面的方法:
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxyObject) throws Throwable {
}
在这两个接口中实现需要实现的事务,但是不影响程序的逻辑。
下面的代码通过doInvok(klass, object, method, args)实现拦截器的添加,method便是需要拦截的方法,通过反射机制进行执行。

public class ProxyBulider <T> implements IProxyBulider {
    private BeanDefinitionHolder beanDefinitionHolder;
    private T proxyObject;
//     必须实例化一个BeanDefinitionHolder并传入
    public ProxyBulider(BeanDefinitionHolder beanDefinitionHolder) {
        this.beanDefinitionHolder = beanDefinitionHolder;
    }

    @Override
    public BeanDefinitionHolder getBeanDefinitionBeanDefinition() {
        return this.beanDefinitionHolder;
    }

    @Override
    public <T> T getCGLProxy(BeanDefinitionHolder beanDefinitionHolder) {
       this.proxyObject = cjlProxy(beanDefinitionHolder.getObject(), beanDefinitionHolder.getBeanClass());
        return (T) proxyObject;
    }

    @Override
    public <T> T getJDKProxy(BeanDefinitionHolder beanDefinitionHolder) {
        this.proxyObject = jdkProxy(beanDefinitionHolder.getObject(), beanDefinitionHolder.getBeanClass());
        return (T) proxyObject;
    }

    @Override
    public <T> T getProxy() {
        return (T) this.proxyObject;
    }

    private <T> T jdkProxy(Object object, Class<?> klass) {
        InvocationHandler invocationHandler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                return doInvok(klass, object, method, args);
            }
        };
        return (T) Proxy.newProxyInstance(klass.getClassLoader(), klass.getDeclaredClasses(), invocationHandler);
    }

    private <T> T cjlProxy(Object object, Class<?> klass) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(klass);
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxyObject) throws Throwable {
                return doInvok(klass, object, method, args);
            }
        });
        return (T) enhancer.create();
    }

//    如有对应的拦截器链,则执行相应的拦截器,若没有,则直接执行对应的方法
    private Object doInvok(Class<?> klass, Object object, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException {
        Object result = null;
        IntercepterFactory intercepterFactory = new IntercepterFactory();
        IntercepterTargetDefinition itd = new IntercepterTargetDefinition(klass, method);
        IntercepterList interBeforeList = intercepterFactory.getBeforeList(itd);
        IntercepterList interAfterList = intercepterFactory.getAfterList(itd);
        IntercepterList interExceptionList = intercepterFactory.getExceptionList(itd);
//        System.out.println("前置拦截前:" + args[0]);
        if(interBeforeList == null) {

        } else {
            if((boolean) interBeforeList.doBefore(args) == false)
            return result;
        }

//        System.out.println("前置拦截后:" + args[0]);
        try {
            result =  method.invoke(object, args);
            if(interAfterList == null) {
                return result;
            } else {
                return interAfterList.doAfter(result);
            }
        } catch (Throwable throwable) {
            interExceptionList.doException(throwable);
        }
        return result;
    }
}

如何添加拦截器?

仍然通过注解以及包扫描的方式实现拦截器的读入,以及拦截器链的生成。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
//拦截器类,说明添加该注解的类是一个拦截器类
public @interface Aspect {
}
  • 定义前置、后置、异常三种拦截器
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
//后置拦截器注解
public @interface After {
	Class<?> klass();
	String method();
	Class<?>[] parasType() default {};
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
//前置拦截器注解
public @interface Before {
	Class<?> klass();
	String method();
	Class<?>[] parasType() default {};
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
//异常拦截器注解
public @interface ThrowException {
	Class<?> klass();
	String method();
	Class<?>[] parasType() default {};
}
  • 定义目标方法
    由于不同的类可能存在相同的方法,因此需要具体到哪个类的哪个方法(未考虑方法的重载)。
public class IntercepterTargetDefinition {
    private Class<?> klass;
    private Method method;

    public IntercepterTargetDefinition(Class<?> klass, Method method) {
        this.klass = klass;
        this.method = method;
    }

    public Class<?> getKlass() {
        return klass;
    }

    public Method getMethod() {
        return method;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        IntercepterTargetDefinition that = (IntercepterTargetDefinition) o;
        return Objects.equals(klass, that.klass) &&
                Objects.equals(method, that.method);
    }

    @Override
    public int hashCode() {
        return Objects.hash(klass, method);
    }
}
  • 定义拦截器方法
public class IntercepterMethodDefinition {
    private Class<?> klass;
    private Method method;
    private Object object;

    public IntercepterMethodDefinition(Class<?> klass, Method method, Object object) {
        this.klass = klass;
        this.method = method;
        this.object = object;
    }

    public Class<?> getKlass() {
        return klass;
    }

    public void setKlass(Class<?> klass) {
        this.klass = klass;
    }

    public Method getMethod() {
        return method;
    }

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

    public Object getObject() {
        return object;
    }

    public void setObject(Object object) {
        this.object = object;
    }
}

前置拦截器主要是对成员进行处理,并且可以通过一个boolean类型的返回结果来决定是否还要反射执行目标方法。
后置拦截器主要是对目标方法的返回结果进行处理。
异常拦截器是在目标执行时发生异常后进行一些必要的处理。
拦截器链可以通过职责链模式来生成,对于使用拦截器链的例子目前还没有想到,就不给出例子了。
职责链模式将多个处理对象聚合成一条链状,被处理对象直接交由链头处理,它会在链中被依次传递下去直到处理完成或到达最后一个处理对象为止。

  • 责任链模式
    首先定义一个接口:
public interface IIntercepterList {
    void add(IntercepterList intercepterList);
    boolean doBefore(Object[] args);
    Object doAfter(Object object);
    void doException(Throwable throwable);
}

接口的实现类:

public class IntercepterList implements IIntercepterList {
    private IIntercepterList next;
    private IntercepterMethodDefinition intercepterMethodDefinition;

    public IntercepterList(IntercepterMethodDefinition intercepterMethodDefinition) {
        this.intercepterMethodDefinition = intercepterMethodDefinition;
    }

    @Override
    public void add(IntercepterList intercepter) {
        IntercepterList temp;
        if(this.next != null) {
            temp = (IntercepterList) this.next;
            this.next = intercepter;
            intercepter.next = temp;
        } else {
            this.next = intercepter;
        }
    }

    @Override
    public boolean doBefore(Object[] args) {
        try {
            boolean result = (boolean)intercepterMethodDefinition.getMethod()
                    .invoke(intercepterMethodDefinition.getObject(), args);
            if (result == false) {
                return false;
            } else if (this.next != null) {
                return next.doBefore(args);
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return true;
    }

    @Override
    public Object doAfter(Object object) {
        if (this.next != null) {
            object =  next.doAfter(object);
        }
        try {
            intercepterMethodDefinition.getMethod()
                    .invoke(intercepterMethodDefinition.getObject(), object);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public void doException(Throwable throwable) {
        try {
            intercepterMethodDefinition.getMethod()
                    .invoke(intercepterMethodDefinition.getObject(), throwable);
            if (this.next != null) {
                next.doException(throwable);
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}

首先生成一个头节点,以后生成的新的对象通过void add(IntercepterList intercepterList)注入到前一个对象的成员中,形成一条链。然后再通过next成员调用相应的方法,形成链式调用。在这里插入图片描述

  • 拦截器工厂,提供了三种拦截器的map,以及添加拦截器,获取拦截器的方法。
//拦截器工厂,对指定方法添加拦截器
public class IntercepterFactory implements IIntercepterFactory {
    private static final Map<IntercepterTargetDefinition, IntercepterList> beforeMap;
    private static final Map<IntercepterTargetDefinition, IntercepterList> afterMap;
    private static final Map<IntercepterTargetDefinition, IntercepterList> exceptionMap;

    static {
        beforeMap = new ConcurrentHashMap<>();
        afterMap = new ConcurrentHashMap<>();
        exceptionMap = new ConcurrentHashMap<>();
    }

    @Override
    public void addBeforeIntercepter(IntercepterTargetDefinition interTarget, IntercepterMethodDefinition interMethod) {
        IntercepterList intercepterList = new IntercepterList(interMethod);
        if (getBeforeList(interTarget) == null) {
            beforeMap.put(interTarget, intercepterList);
        } else {
            getBeforeList(interTarget).add(intercepterList);
        }
    }

    @Override
    public void addAfterIntercepter(IntercepterTargetDefinition interTarget, IntercepterMethodDefinition interMethod) {
        IntercepterList intercepterList = new IntercepterList(interMethod);
        if (getAfterList(interTarget) == null) {
            afterMap.put(interTarget, intercepterList);
        } else {
            getAfterList(interTarget).add(intercepterList);
        }
    }

    @Override
    public void addExceptionIntercepter(IntercepterTargetDefinition interTarget, IntercepterMethodDefinition interMethod) {
        IntercepterList intercepterList = new IntercepterList(interMethod);
        if (getExceptionList(interTarget) == null) {
            exceptionMap.put(interTarget, intercepterList);
        } else {
            getExceptionList(interTarget).add(intercepterList);
        }
    }

    @Override
    public IntercepterList getBeforeList(IntercepterTargetDefinition interceTarget) {
        return beforeMap.get(interceTarget);
    }

    @Override
    public IntercepterList getAfterList(IntercepterTargetDefinition interceTarget) {
        return afterMap.get(interceTarget);
    }

    @Override
    public IntercepterList getExceptionList(IntercepterTargetDefinition interceTarget) {
        return exceptionMap.get(interceTarget);
    }

}

默认拦截器工厂,进行包扫描以及对类的处理,拦截方法的添加。

public class DefaultIntercepterFactory {
    private IntercepterFactory intercepterFactory;
    private final String BEFORE = "before";
    private final String AFTER = "after";
    private final String EXCEPTION = "exception";

    public DefaultIntercepterFactory() {
        this.intercepterFactory = new IntercepterFactory();
    }

    public void intercepterScan(String packagePath) {
        new PackageScanner() {
            @Override
            public void dealClass(Class<?> klass) {
                try {
                    doDealClass(klass);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }.packageScanner(packagePath);
    }

    private void doDealClass(Class<?> klass) throws Exception {
        if(klass.isAnnotationPresent(Aspect.class)) {
            Object object = klass.newInstance();
            Method[] methods = klass.getMethods();
            for (Method method : methods) {
                dealMethod(method, object);
            }
        }
    }

    private void dealMethod(Method method, Object object) throws Exception {
        if(method.isAnnotationPresent(Before.class)) {
            if(!method.getReturnType().equals(boolean.class)) {
                return;
            }
            Before before = method.getAnnotation(Before.class);
            Class<?> targetClass = before.klass();
            String targetMethodName = before.method();
            Class<?>[] parasType = before.parasType();
            doDealMethod(object, method, targetClass, targetMethodName, BEFORE, parasType);
        } else if(method.isAnnotationPresent(After.class)) {
            if(!method.getReturnType().equals(Object.class)) {
                return;
            }
            After after = method.getAnnotation(After.class);
            Class<?> targetClass = after.klass();
            String methodName = after.method();
            Class<?>[] parasType = after.parasType();
            doDealMethod(object, method, targetClass, methodName, AFTER, parasType);
        } else if(method.isAnnotationPresent(ThrowException.class)) {
            if(!method.getReturnType().equals(void.class)) {
                return;
            }
            ThrowException throwException = method.getAnnotation(ThrowException.class);
            Class<?> targetClass = throwException.klass();
            String methodName = throwException.method();
            Class<?>[] parasType = throwException.parasType();
            doDealMethod(object, method, targetClass, methodName, EXCEPTION, parasType);
        }
    }

    private void doDealMethod(Object object, Method method, Class<?> targetClass, String targetMethodName, String type,
                              Class<?>[] parasType) throws Exception {
        try {
            Method targetMethod = targetClass.getMethod(targetMethodName, parasType);
            IntercepterTargetDefinition intercepterTargetDefinition =
                    new IntercepterTargetDefinition(targetClass, targetMethod);
            IntercepterMethodDefinition intercepterMethodDefinition =
                    new IntercepterMethodDefinition(targetClass, method, object);
            if(type.equals(BEFORE)) {
                intercepterFactory.addBeforeIntercepter(intercepterTargetDefinition, intercepterMethodDefinition);
            } else if(type.equals(AFTER)) {
                intercepterFactory.addAfterIntercepter(intercepterTargetDefinition, intercepterMethodDefinition);
            } else if(type.equals(EXCEPTION)) {
                intercepterFactory.addExceptionIntercepter(intercepterTargetDefinition, intercepterMethodDefinition);
            }
        } catch (NoSuchMethodException e) {
            throw new NoSuchMethodException("找不到对应的方法" + targetMethodName +
                    "(" + method.getParameterTypes() + ")");
        }
    }
}

测试:

Aspect
public class AIntercepter {
    @Before(klass = A.class, method = "fun", parasType = {B.class})
    public boolean aBeforeIntercepter(B b) {
        System.out.println("传入的b中的num的值:" + b.getNum());
        b.setNum(123);
        System.out.println("这是A的前置拦截!");
        return true;
    }

    @Before(klass = A.class, method = "fun", parasType = {B.class})
    public boolean aBeforeIntercepter1(B b) {
        System.out.println("传入的b中的num的值2:" + b.getNum());
        b.setNum(456);
        System.out.println("这是A的前置拦截2!");
        return true;
    }

    @After(klass = A.class, method = "fun", parasType = {B.class})
    public Object aAfterIntercepter(Object object) {
        System.out.println("这是A的后置拦截!");
        return object;
    }

    @After(klass = A.class, method = "fun", parasType = {B.class})
    public Object aAfterIntercepter1(Object object) {
        System.out.println("这是A的后置拦截2!");
        return object;
    }
    @ThrowException(klass = A.class, method = "fun", parasType = {B.class})
    public void aExceptionIntercepter1(Throwable throwable) {
        System.out.println("异常拦截!");
    }

    @ThrowException(klass = A.class, method = "fun", parasType = {B.class})
    public void aExceptionIntercepter2(Throwable throwable) {
        System.out.println("异常拦截2!");
    }
}
@Component
public class A {
    @Autowired
    private B b;

    public A() {
    }

    public void setB(B b) {
        this.b = b;
    }

    public B getB() {
        return b;
    }

    public void fun(B b) throws Exception {
//        System.out.println("自动注入的num:" + this.num);

        System.out.println("这是fun方法");
        throw new Exception();
    }

    @Override
    public String toString() {
        return "这是A - >B\n" + b;
    }
}
@Component
public class B {
    @Autowired
    private C c;
    @Autowired(value = "123")
    private int num;

    public B() {
    }

    public void setC(C c) {
        this.c = c;
    }

    public C getC() {
        return c;
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    @Bean
    public D autowiredD() {
        return new D();
    }

    @Override
    public String toString() {
        return "这是B - >C\n" + c;
    }
}
public class Demo {
    public static void main(String[] args) {
        DefaultBeanFactory defaultBeanFactory = new DefaultBeanFactory();
        defaultBeanFactory.packageScan("com.xxy.test");
        DefaultIntercepterFactory defaultIntercepterFactory = new DefaultIntercepterFactory();
        defaultIntercepterFactory.intercepterScan("com.xxy.test");
        B b = new B();
        b.setNum(0);
        A a = defaultBeanFactory.getproxy(A.class);
        try {
            a.fun(b);
        } catch (Exception e) {
        }
        System.out.println(b.getNum());
    }
}

结果:
传入的b中的num的值:0
这是A的前置拦截!
传入的b中的num的值2:123
这是A的前置拦截2!
这是fun方法
异常拦截!
异常拦截2!
456

存在的问题,拦截器链种并不能保证拦截器的顺序,还需要想办法进行解决。
这是在学习了ioc之后做出的一些尝试性练习,如果有错误的地方还请各位大佬给予指正,谢谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值