java代理浅述

代理

代理主要可以分为:

  • 静态代理
  • JDK自带的动态代理
  • Cglib

静态代理

静态代理比较简单,简单来说就是不想直接调用被代理类,通过代理类来实现功能。如下就是使用了静态代理

定义接口

public interface BookFace {
    public void addBook();
    public void addapple();
}
public class BookFaceImp implements BookFace {
    @Override
    public void addBook()
    {
        System.out.println("增加图书方法");
    }
    @Override
    public void  addapple()
    {
        System.out.println("增加苹果");
    }

}
public class BookFaceStatic implements BookFace{
    private BookFace target;

    public  BookFaceStatic(BookFace target)
    {
        this.target=target;

    }
    @Override
    public void addBook() {
        System.out.println("美术图书");
        target.addBook();

    }

    @Override
    public void addapple() {
        System.out.println("红苹果");
        target.addapple();

    }
}

编写单测:

@Test
    public void test3()
    {
        BookFaceStatic faceStatic=new BookFaceStatic(new BookFaceImp());
        faceStatic.addBook();
        faceStatic.addapple();

 }

输出结果:

上述就是一个简单的静态代理,就是讲需要的被代理类作为参数传入待代理类中。

JDK自带的动态代理

java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。

JDK动态代理只能对实现了接口的类生成代理,而不能针对类。

延续使用上述的接口和接口实现类,核心代码如下:

public class BookFaceProcyJDK  implements InvocationHandler {
    private Object target;

    public  Object getProcy(Object target)
    {
        //获取到是哪个类需要代理
        this.target=target;
        //getInterfaces()获取代理类的接口
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
    }
    //重写invoke方法,InvocationHandler中自动会执行
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("批量执行1");
        Object result=method.invoke(target,args);
        System.out.println("批量执行2");
        return result;
    }
}

编写单测:

   @Test
    public void test1()
    {
        BookFaceImp bookFaceImp=new BookFaceImp();
        BookFaceProcyJDK bookFaceProcy=new BookFaceProcyJDK();
        BookFace bookFace= (BookFace)bookFaceProcy.getProcy(bookFaceImp);
        bookFace.addBook();
        bookFace.addapple();
    }

输出结果:

采坑:
为什么BookFace bookFace= (BookFaceImp)bookFaceProcy.getProcy(bookFaceImp);
不能这样写???

解释:因为代理时相当于新建了一个BookFaceImp1,要么写成(BookFaceImp1)bookFaceProcy.bind(bookFaceImp)或者使用它的父类BookFace,因为不知道到底生成了一个什么名字的BookFaceImp,所以得使用它的父类BookFace。

(代理生成的BookFaceImp1和BookFaceImp是统一层级的)

Cglib

cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法。

延续使用上述的接口和接口实现类,核心代码如下:

  public class BookFaceProcyCglib implements MethodInterceptor {

    private Object target;
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {

        System.out.println("监听开始");
        Object result=method.invoke(target,args);
        System.out.println("监听结束");
        return result;
    }
    public Object getProcy(Object target)
    {
        this.target=target;
        Enhancer enhancer=new Enhancer();
        //设置父类,因为cglib是设置子类
        enhancer.setSuperclass(target.getClass());
        //设置回调
        enhancer.setCallback(this);
        return  enhancer.create();
    }
}

单测:

   @Test
    public void test2()
    {
        BookFaceImp bookFaceImp=new BookFaceImp();
        BookFaceProcyCglib bookFaceProcy=new BookFaceProcyCglib();
        BookFace bookFace= (BookFace)bookFaceProcy.getProcy(bookFaceImp);
        bookFace.addBook();
        bookFace.addapple();
    }

运行结果:

Cglib与jdk自带的动态代理不同是生成的bookFaceImp1的父类是bookFaceImp


所以 BookFace bookFace= (BookFace)bookFaceProcy.getProcy(bookFaceImp)也可以改成 BookFace bookFace= (BookFaceImp)bookFaceProcy.getProcy(bookFaceImp),效果一致

posted @ 2019-07-29 21:41  balvender  阅读(173)  评论(0编辑  收藏  举报