动态代理两种实现方式

代理模式,在Java中使用较多的一种模式,而Spring的AOP就是通过动态代理技术实现的。
动态代理实现的两种方式:

方式一:JDK中自带的动态代理机制,通过定义一个接口,被代理类和动态代理类实现这个接口

TargetInterface.java

/**
 * 公共接口
 * @author jayzh
 *
 */
public interface TargetInterface {
    public void targetMethodA();

    public void targetMethodB(String param);
}

RealObject.java

/**
 * 被代理类
 * @author jayzh
 *
 */
public class RealObject implements TargetInterface {

    @Override
    public void targetMethodA() {
        System.out.println("Do something in method A.");
    }

    @Override
    public void targetMethodB(String param) {
        System.out.println("Do something in method B, Param is " + param + ".");
    }

}

ProxyHandler.java

/**
 * 动态代理类
 * @author jayzh
 *
 */
public class ProxyHandler implements InvocationHandler {

    private Object delegate;

    public ProxyHandler(Object delegate) {
        this.delegate = delegate;
    }

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

}

DynamicProxyExample.java

public class DynamicProxyExample {
    public static void main(String[] args) {
        // 被代理对象
        RealObject obj = new RealObject();

        // 动态代理类
        ProxyHandler handler = new ProxyHandler(obj);

        // 获取代理实例
        TargetInterface proxy = (TargetInterface) Proxy.newProxyInstance(
                obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),
                handler);

        proxy.targetMethodA();

        proxy.targetMethodB("DynamicProxyExample");
    }
}

运行结果

JDK动态代理

使用此种方式实现动态代理需要通过接口来实现,若某个类未实现接口则无法被代理。

方式二:使用cglib实现,通过继承某个类,在子类中拦截所有父类方法的调用并加入相关逻辑来实现动态代理

SimpleObject.java

/**
 * 未实现接口的类
 * @author jayzh
 *
 */
public class SimpleObject {
    public void hello() {
        System.out.println("Hello World!");
    }

    public void filter() {
        System.out.println("This is a filter method!");
    }

    public final void finalMethod() {
        System.out.println("This is a final method!");
    }
}

CglibProxy.java

/**
 * Cglib动态代理类
 * @author jayzh
 *
 */
public class CglibProxy implements MethodInterceptor {

    private Enhancer enhancer = new Enhancer();

    public Object getProxy(Class<?> clazz) {
        enhancer.setSuperclass(clazz);
        enhancer.setCallbacks(new Callback[]{this, NoOp.INSTANCE});
        enhancer.setCallbackFilter(new CallbackFilter() {
            @Override
            public int accept(Method method) {
                if ("filter".equals(method.getName())) {
                    return 1;
                }
                return 0;
            }
        });
        return enhancer.create();
    }

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

}

CglibProxyExample.java

public class CglibProxyExample {
    public static void main(String[] args) {
        // 创建Cglib代理类
        CglibProxy proxy = new CglibProxy();
        SimpleObject obj = (SimpleObject) proxy.getProxy(SimpleObject.class);
        // 普通方法
        obj.hello();
        // 匹配CallbackFilter的方法
        obj.filter();
        // final方法
        obj.finalMethod();
    }
}

运行结果

Cglib动态代理

同时Cglib也提供了方法过滤器(CallbackFilter)来对方法进行过滤。
需要注意的是使用此种方式被final修饰的方法或类是无法被代理的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值