代理的坎坷路

2017/11/07 - Java

静态代理

此处就不累述了,就是简单的引用被代理对象,在调用方法前后hook。

缺点

  • 随着需求的增加和变动,容易导致proxy的膨胀。
  • 目标对象一定要实现接口。

jdk动态代理

原理同静态代理。只是proxy类是动态生成的,不用用户亲自写代码。Proxy类引用了被代理类,并实现了委托接口,调用接口通过反射方式并进行hook。

优点

  • 适合频繁、反复地创建代理对象。

缺点

  • 目标对象一定要实现接口

demo

public interface IFly {
    String flying();
}

public class Bird implements IFly {
    @Override
    public String flying() {
        LOGGER.info("flying");
        return "flying";
    }

}

public class ProxyFactory {
    private Object target;
    public ProxyFactory(Object target) {
        this.target = target;
    }

    public Object getProxyInstance() {
        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new InvocationHandler(){

                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    LOGGER.info("invoke start");
                    Object obj = method.invoke(target, args);
                    LOGGER.info("invoke end");
                    return obj;
                    }
                });
    }

}

public class Main {
    public static void main(String[] args) {
        IFly f = new Bird();
        IFly proxy = (IFly) new ProxyFactory(f).getProxyInstance();
        proxy.flying();
    }
}

cglib代理

运行时动态生成字节码(相当于生成了一个全新的被代理类,而不是通过引用的方式),调用方法时直接调用(FastMethod),而不是通过反射,提升了效率,但生成代理类的效率会比JDK动态代理慢。

demo

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.2.5</version>
</dependency>
//Bird类同上

public class DynamicProxy implements MethodInterceptor {
    Object target;

    public Object getProxyObject(Object target) {
        this.target = target;
        Enhancer enhancer = new Enhancer();
        enhancer.setCallback(this);
        enhancer.setSuperclass(target.getClass());
        return enhancer.create();
    }

    @Override
    public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        LOGGER.info("invoke start");
        LOGGER.info(methodProxy.getSuperName());
        Object result = methodProxy.invoke(target, args);
        LOGGER.info("invoke end");
        return result;
    }
}


public class Main {
    public static void main(String[] args) {
        Bird bird = (Bird) new DynamicProxy().getProxyObject(new Bird());
        bird.flying();
    }
}

应用场景

切面编程AOP

其他

  • JDK动态代理生成 代理对象class:System.setProperty(“sun.misc.ProxyGenerator.saveGeneratedFiles”, “true”);
  • cglib 生成代理对象class:System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, “/users/mdm/Documents/workspace2/CG/”);
  • 字节码查看工具:JD-GUI
  • 反编译class工具:jad

如果文章对您有帮助,欢迎扫描下方二维码赞助(一分也是爱噢),谢谢

Search

    一分也是爱噢 一分也是爱

    目录