aop之动态代理

来源:互联网 发布:数学建模与算法的关系 编辑:程序博客网 时间:2024/05/20 18:43

      • 前言
        • Spring的两大特征一个是IOC一个是AOP前者是控制反转主要的思想是依赖注入在action层我们需要service层对象在service层我们需要dao层对象通过Spring通过IOC技术自动我们注入对象AOP的主要思想是在执行业务逻辑的前后我们需要执行一些逻辑比如日志事务等通过动态代理就可以完美解决这些需求本次着重讲一下AOP
      • AOP实现
        • 注解相关
          • 代理相关注解
          • 动作相关注解
          • 目标执行之前注解标记
          • 目标执行之后注解标记
        • 目标接口
          • 目标接口可以有多个下面列出两个目标接口
          • 对应的动作类可以有多个我这里就列出两个doAfter标记的dobefore标记的大同小异
        • 目标类
          • 目标类可以实现多个目标接口
          • interfaces 参数其实也可以不写通过反射可以动态获取所有的接口但是不人性化无法控制目标接口的数量
        • proxy工具类
          • 目标类可以实现多个目标接口
          • MethodInvokeBean该bean的存在是因为method的invok需要该类的实例所以该bean就将会装载一个实例和一个方法实例
        • 测试

前言

Spring的两大特征,一个是IOC,一个是AOP。前者是控制反转,主要的思想是依赖注入,在action层我们需要service层对象,在service层我们需要dao层对象,通过Spring通过IOC技术自动我们注入对象。AOP的主要思想是在执行业务逻辑的前后,我们需要执行一些逻辑,比如日志,事务等,通过动态代理就可以完美解决这些需求。本次着重讲一下AOP。

AOP实现

注解相关

代理相关注解
/** * Created by yzz on 2017/8/13. * mail:yzzstyle@163.com */@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)public @interface proxu {    //目标执行之前需要执行到的类    Class[] aopbefore();    //目标执行之后需要执行到的类    Class[] aopafter();    //需要代理的接口    Class[] interfaces();}
动作相关注解
目标执行之前注解标记
/** * Created by yzz on 2017/8/13. * mail:yzzstyle@163.com */@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)public @interface doBefore {}
目标执行之后注解标记
/** * Created by yzz on 2017/8/13. * mail:yzzstyle@163.com */@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)public @interface doAfter {}

目标接口

目标接口可以有多个,下面列出两个目标接口
package com.yzz.java.proxyer;/** * Created by yzz on 2017/8/13. */public interface IProxy {    void method1();    String method2();    String method3(String arg);}
package com.yzz.java.proxyer;/** * Created by yzz on 2017/8/13. * mail:yzzstyle@163.com */public interface IProxy2 {    void methodIProxy2();}
对应的动作类,可以有多个,我这里就列出两个doAfter标记的,dobefore标记的大同小异
/** * Created by yzz on 2017/8/13. * mail:yzzstyle@163.com */public class After1 {    @doAfter    public void dobefore1(){        Log.e("After1===bobefore1====");    }    @doAfter    public void dobefore2(){        Log.e("After1===bobefore2====");    }}
/** * Created by yzz on 2017/8/13. * mail:yzzstyle@163.com */public class After2 {    @doAfter    public void dobefore1(){        Log.e("After2===bobefore1====");    }    @doAfter    public void dobefore2(){        Log.e("After2===bobefore2====");    }}

目标类

目标类可以实现多个目标接口
interfaces 参数其实也可以不写,通过反射可以动态获取所有的接口,但是不人性化,无法控制目标接口的数量
/** * Created by yzz on 2017/8/13. * mail:yzzstyle@163.com */@proxu(        aopafter = {After1.class,After2.class},        aopbefore = {Before1.class,Before2.class},        interfaces = {IProxy.class,IProxy2.class}        )public class TargetProxy implements IProxy ,IProxy2{    @Override    public void method1() {        Log.e("TargetProxy:method1");    }    @Override    public String method2() {        Log.e("TargetProxy:method2");        return "TargetProxy";    }    @Override    public String method3(String arg) {        Log.e("TargetProxy:method3");        return arg;    }    @Override    public void methodIProxy2() {        Log.e("TargetProxy:methodIProxy2");    }}

proxy工具类

目标类可以实现多个目标接口
MethodInvokeBean该bean的存在是因为method的invok需要该类的实例,所以该bean就将会装载一个实例和一个方法实例。
package com.yzz.java.proxyer;import com.yzz.java.Log;import com.yzz.java.proxy.*;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.util.ArrayList;import java.util.List;/** * Created by yzz on 2017/8/13. * mail:yzzstyle@163.com */public class ProxyUtils {    public static <T> T  doProxy(T t) throws Exception{        boolean isproxu = t.getClass().isAnnotationPresent(proxu.class);        if (!isproxu)return t;        proxu proxu =  t.getClass().getAnnotation(proxu.class);        Class[] interfaces = proxu.interfaces();        Class[] aopafter = proxu.aopafter();        Class[] aopbefore = proxu.aopbefore();        return (T) Proxy.newProxyInstance(                t.getClass().getClassLoader(),                interfaces,                new InvocationHandler() {                    @Override                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {                        //before                        ProxyUtils.invoke(getMethod(aopbefore,doBefore.class));                        method.invoke(t,args);                        //after                        ProxyUtils.invoke(getMethod(aopafter,doAfter.class));                        return "==";                    }                }        );    }    /**     * 执行方法     * @param methods     * @throws Exception     */    private static void invoke(List<MethodInvokeBean> methods) throws Exception{        for (MethodInvokeBean m:methods) {            m.getMethod().invoke(m.getObject());        }    }    /**     * 接收执行类的集合的方法     * @param _class     * @param t     * @return     * @throws Exception     */    private static List<MethodInvokeBean> getMethod(Class[] _class,Class t) throws Exception{        List<MethodInvokeBean> methods = new ArrayList<>();        for (Class ss:_class) {            getMethod(ss,t,methods,ss.newInstance());        }        return methods;    }    /**     * 获取动作类中特定标记的方法     * @param _class     * @param t     * @param methods     * @param object     */    private static void getMethod(Class _class, Class t,List<MethodInvokeBean> methods,Object object){        Method[] m = _class.getMethods();        for (Method mm:m) {            if (mm.isAnnotationPresent(t)){                methods.add(new MethodInvokeBean(object,mm));            }        }    }}

测试

这里写图片描述

这里写图片描述

/** * Created by yzz on 2017/8/13. * mail:yzzstyle@163.com */public class Test {    public static void main(String[] args){        try {//            IProxy2 iProxy2 = ProxyUtils.doProxy(TargetProxy.class.newInstance());//            iProxy2.methodIProxy2();            IProxy iProxy = ProxyUtils.doProxy(TargetProxy.class.newInstance());            iProxy.method1();            iProxy.method2();            iProxy.method3("yzz");        } catch (Exception e) {            e.printStackTrace();        }    }}
原创粉丝点击