3种方式实现AOP

一、代理模式实现aop

public interface IHello {
    void sayHello(String name);
}

public class Hello implements IHello {
    @Override
    public void sayHello(String name) {
          System.out.println(name+" say hello");
    }
}

  代理类

public class HelloProxy implements IHello {

    private IHello hello;

    public HelloProxy(IHello hello){
        this.hello=hello;
    }
    @Override
    public void sayHello(String name) {
        System.out.println("before....");
        hello.sayHello(name);
        System.out.println("after....");
    }
}

   客户端

public class Test {

    public static void main(String[] args){
        IHello hello=new HelloProxy(new Hello());
        hello.sayHello("persia");
    }
}


二、JDK的动态代理反射实现aop

    JDK动态代理只能代理接口

/**
 * 使用JDK提供的动态代理
 * @author scipio
 * @created 2013-10-21
 */
public class DynaProxyHello implements InvocationHandler{

    private Object target;


    //动态生成代理对象
    public Object bind(Object target){
        this.target=target;
        return Proxy.newProxyInstance(this.target.getClass().getClassLoader(),this.target.getClass().getInterfaces(),this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before..... ");
         Object result=method.invoke(target,args);
        System.out.println("after.....");
        return result;
    }
}

   客户端

public class Test {

    public static void main(String[] args){
        /**
         * 只能代理接口
         */
        IHello hello= (IHello) new DynaProxyHello().bind(new Hello());
//        Hello hello = (Hello) new DynaProxyHello().bind(new Hello());
        hello.sayHello("persia");

    }
}


三、Aspect方式(JDK实现)

  1、定义拦截后要执行的方法
/**
 * 拦截指定方法后要执行的方法
 * @author scipio
 * @created 2013-10-21
 */
public class CrossCutting {

    public void before(){
        System.out.println("before...");
    }

    public void after(){
        System.out.println("after...");
    }

}

2、模拟Aop
/**
 * 使用java的反射
 * 进行aop功能的模拟
 * @author scipio
 * @created 2013-10-21
 */
public class Aop {

    private static CrossCutting cut=new CrossCutting();
    private static ReflectUtils rfBefore=new ReflectUtils(cut,"before");
    private static ReflectUtils rfAfter=new ReflectUtils(cut,"after");

    public static void beforeAdvice(Object target,String methodName,Object ... params){
        Class cls=target.getClass();
        Method[] methods=cls.getDeclaredMethods();
        for(int i=0;i<methods.length;i++){
            if(methods[i].getName().equals(methodName)){
                rfBefore.invokeMethod();
                new ReflectUtils(target,methodName,params).invokeMethod();
            }
        }
    }

    public static void afterAdvice(Object target,String methodName,Object... params){
        Class cls=target.getClass();
        Method[] methods=cls.getDeclaredMethods();
        for(int i=0;i<methods.length;i++){
            if(methods[i].getName().equals(methodName)){
                new ReflectUtils(target,methodName,params).invokeMethod();
                rfAfter.invokeMethod();

            }
        }
    }

    public static void aroundAdvice(Object target,String methodName,Object... params){
        Class cls=target.getClass();
        Method[] methods=cls.getDeclaredMethods();
        for(int i=0;i<methods.length;i++){
            if(methods[i].getName().equals(methodName)){
                rfBefore.invokeMethod();
                new ReflectUtils(target,methodName,params).invokeMethod();
                rfAfter.invokeMethod();

            }
        }
    }

}

3、拦截对象
/**
 * 要被拦截的方法
 * @author scipio
 * @created 2013-10-21
 */
public interface Crud {
    public void add(String user);
    public void modify(String user);
    public void delete(String user);
}

/**
 * 要被拦截的方法
 * @author scipio
 * @created 2013-10-21
 */
public class CrudImpl implements Crud {
    @Override
    public void add(String user) {
        System.out.println("new user:");
    }

    @Override
    public void modify(String user) {
         System.out.println("modify user");
    }

    @Override
    public void delete(String user) {
        System.out.println("delete user");
    }
}

4、客户端及工具类
public class Test {
    public static void main(String[] args){
        Crud crud=new CrudImpl();
        Aop.beforeAdvice(crud,"modify","persia");
    }
}

/**
 * java反射的一些帮助方法
 * 通过传入的类,拦截要执行的方法名
 * 返回后直接invoke即可
 * 具体见aop
 * 无其他意义,不是经典模式,可以去掉
 * @author scipio
 * @created 2013-10-21
 */
public class ReflectUtils {

    private Class targetClass;
    private Object target;
    private Method targetMethod;
    private Object[] params;

    public ReflectUtils(Object target,String methodName,Object ... params){
        this.target=target;
        this.targetClass=target.getClass();
        this.params=params;
        Class[] cls=new Class[params.length];
        for(int i=0;i<params.length;i++){
            cls[i]=params[i].getClass();
        }
        try {
            this.targetMethod=targetClass.getMethod(methodName,cls);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }

    public void invokeMethod(){
        try {
            this.targetMethod.invoke(target,params);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}


四、Aspect方式(Cglib实现)

1、拦截后要执行的方法
/**
 * 通过cglib进行拦截
 * @author scipio
 * @created 2013-10-21
 */
public class AroundCutting implements MethodInterceptor{

    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("before...."+method);
        //直接invoke会造成stack over flow
//        Object result = proxy.invoke(o, args);
        Object result = proxy.invokeSuper(o, args);
        System.out.println("after..."+method);
        return result;
    }

}

2、Cglib模拟aop
/**
 * cglib实现aop
 * @author scipio
 * @created 2013-10-21
 */
public class CglibAOP {

    private Enhancer enhancer = new Enhancer();

    /**
     * 使用Cglib进行动态代理,是创建一个子类继承至目标类,所以不需要像GDK动态代理那样提供一个接口,这样节约了类的个数。
     * JDK动态代理的特点:不能代理类,只能代理接口
     * CGLIB动态代理的特点:能代理类和接口,不能代理final类
     *  动态代理的本质:用来实现对目标对象进行增强,最终表现为类,只不过是动态创建子类,不用手工生成子类。
     * @param clz
     * @return
     */

    private MethodInterceptor interceptor;

    public CglibAOP(MethodInterceptor interceptor){
        this.interceptor=interceptor;
    }

    public Object getProxy(Class clz){
        //生成指定类对象的子类,也就是重写类中的业务函数
        enhancer.setSuperclass(clz);
        //这里是回调函数,加入intercept()函数
        enhancer.setCallback(interceptor);
        //创建这个子类对象
        return enhancer.create();
    }


}

3、被拦截对象
/**
 * 要被拦截的方法
 * @author caibosi
 * @created 2013-10-21
 */
public class CrudImpl {

    public void add(String user) {
        System.out.println("new user:");
    }

    //用static方法的话,则拦截不了
    public void modify(String user) {
         System.out.println("modify user"+user);
    }


    public void delete(String user) {
        System.out.println("delete user");
    }
}

4、客户端
public class Test {

    public static void main(String[] args){
         CglibAOP aop=new CglibAOP(new AroundCutting());
         CrudImpl crud= (CrudImpl) aop.getProxy(CrudImpl.class);
         crud.modify("modify name");
    }
}

5、高级回调功能
/**
 * cglib callback filter
 * 根据不同方法进行不同的拦截
 * @author scipio
 * @created 2013-10-24
 */
public class CglibCallbacks {

    public static void main(String[] args){
        //声明cglib增强类
        Enhancer enhancer = new Enhancer();
        //设置被代理类
        enhancer.setSuperclass(CrudImpl.class);
        //set callbacks
        Callback[] callbacks = new Callback[]{
              NoOp.INSTANCE,new AddCallback(),new ModifyCallback(),new DeleteCallback()
        };
        //设定拦截方法
        enhancer.setCallbacks(callbacks);
        //设定方法对应的拦截
        enhancer.setCallbackFilter(new DaoFilter());
        //通过增强类获取代理类
        CrudImpl proxyCrud = (CrudImpl)enhancer.create();
        proxyCrud.modify("persia");
        proxyCrud.add("linda");
        proxyCrud.delete("susan");

    }
}

class AddCallback implements MethodInterceptor{

    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("before....cutting add method");
        Object result = proxy.invokeSuper(o, args);
        System.out.println("after...cutting add method");
        return result;
    }
}
class ModifyCallback implements MethodInterceptor{

    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("before....cutting modify method");
        Object result = proxy.invokeSuper(o, args);
        System.out.println("after...cutting modify method");
        return result;
    }
}

class DeleteCallback implements MethodInterceptor{

    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("before....cutting delete method");
        Object result = proxy.invokeSuper(o, args);
        System.out.println("after...cutting delete method");
        return result;
    }
}

/**
 * 此方法用来决定哪个方法
 * 被那个callback拦截
 * 返回index,对应callbacks数组
 */
class DaoFilter implements CallbackFilter{

    @Override
    public int accept(Method method) {
        String methodName = method.getName();
        System.out.println("method:"+methodName);
        if(methodName.equals("delete")){
             return 3;
        }else if(methodName.equals("add")){
             return 1;
        }else if (methodName.equals("modify")){
             return 2;
        }
        //0对应了NoOp.INSTANCE的callback,表示不做任何事情
        return 0;
    }
}


五、要点

1、JDK只能基于接口动态代理

2、Cglib基于接口和非final类代理,不能代理static方法


转载于:https://my.oschina.net/scipio/blog/283274

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值