java动态代理实现

情景

需要在A类的a方法、B类的b方法等调用之前验证条件C,最直接的方法就是每个方法的前面都添加一个验证C的方法,但是当大量的方法需要验证,显然不利于维护。

此时,可以用动态代理的方式处理验证方法。将需要验证的方法进行代理,即每次调用代理方法之前都去执行C方法进行验证。

实现

JDK动态代理

特点:需要提出被代理方法的公共接口,被代理类实现。仅能对接口中方法进行代理。

1.创建接口

/**
 * jdk代理接口
 *
 * @author fengzhen
 * @version v1.0, 2017/9/7 14:22
 */
public interface Hello {
    void hello(String name);
}

2.被代理类实现接口

/**
 * 被代理对象Hello接口实现者
 *
 * @author fengzhen
 * @version v1.0, 2017/9/7 14:23
 */
public class HelloImpl implements Hello{
    @Override
    public void hello(String name) {
        System.out.println(name + "hello world!");
    }

    public void world(String s){
        System.out.println(s + "  world peaceful!");
    }
}

3.创建代理类

/**
 * 代理类
 *
 * @author fengzhen
 * @version v1.0, 2017/9/7 14:25
 */
public class HelloProxy implements InvocationHandler {

    private Hello mHello;

    /**
     * 绑定代理对象,并返回一个代理类
     *
     * @author fengzhen
     * @version v1.0, 2017/9/7 14:29
     */
    public Object getInstance(Hello hello){
        mHello = hello;
        return Proxy.newProxyInstance(
                hello.getClass().getClassLoader(),
                hello.getClass().getInterfaces(),
                this);
    }

    /**
     * 对代理方法进行处理
     *
     * @param o 被代理对象
     * @param method 被代理方法
     * @param objects 方法参数
     * @author fengzhen
     * @version v1.0, 2017/9/7 15:48
     */
    @Override
    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
        System.out.println("before hello");
        Object invoke = method.invoke(mHello, objects);
        System.out.println("after hello");
        return invoke;
    }
}

4.结果

调用代理:

  //JDK动态代理
  HelloProxy helloProxy = new HelloProxy();
  Hello hel = null;
  try {
      Hello hello = (Hello) Class.forName("practice.dynamicAgency.HelloImpl").newInstance();
      hel = (Hello) helloProxy.getInstance(hello);
      hel.hello("sss");
  } catch (Exception e) {
      e.printStackTrace();
  }

结果展示:

before hello
ssshello world!
after hello

cglib动态代理

特点:不用实现接口。被代理类的所有方法都被代理。

1.导包

下载地址:http://www.java2s.com/Code/Jar/c/Downloadcloudcglibjar.htm

2.直接创建代理类

/**
 * cglib动态代理  代理者
 *
 * @author fengzhen
 * @version v1.0, 2017/9/7 14:54
 */
public class HelloProxy implements MethodInterceptor{

    private Object target;

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

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("before hello");
        Object invoke = method.invoke(target, objects);
        System.out.println("after hello");
        return invoke;
    }
}

3.结果

   // cglib动态代理
   practice.cglibAgency.Hello target = new practice.cglibAgency.Hello();
   practice.cglibAgency.Hello hello =
           (practice.cglibAgency.Hello) new practice.cglibAgency.HelloProxy()
           .getInstance(target);
   hello.hello("ad ");
   hello.world("ddf");

结果:

before hello
ad   hello world!
after hello
before hello
ddf  world peaceful!
after hello

cglib动态代理 + 方法拦截器

使得代理类不必实现接口MethodInterceptor,单独起到类似工厂的作用,同时分离开MethodInterceptor,具体的代理方法中对方法进行处理。

1.创建代理

/**
 * 代理创建工厂类
 *
 * @author fengzhen
 * @version v1.0, 2017/9/13 11:53
 */
public class ProxyFactory {

    /**
     * 创建代理类
     *
     * @author fengzhen
     * @version v1.0, 2017/9/13 11:53
     */
    public static <T> T getInstance(Class<T> target) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target);
        enhancer.setCallback(new MethodInterceptorImpl());
        return (T) enhancer.create();
    }
}

2.方法拦截接口分离实现

/**
 * cglib方法拦截实现
 *
 * @author fengzhen
 * @version v1.0, 2017/9/12 18:39
 */
public class MethodInterceptorImpl implements MethodInterceptor {

    private Interceptor mInterceptor = null;

    public void setmInterceptor(Interceptor mInterceptor) {
        this.mInterceptor = mInterceptor;
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) {
        Object invoke = null;
        try {

            // 预处理
            if (mInterceptor != null) {
                mInterceptor.befor(o, method, objects, methodProxy);
            }

            invoke = methodProxy.invokeSuper(o, objects);

            // 返回结果处理
            if (mInterceptor != null) {
                invoke = mInterceptor.after(invoke);
            }
        } catch (Throwable throwable) {

            // 异常处理
            if (mInterceptor != null) {
                invoke = mInterceptor.throwErr(throwable);
            }
        }
        return invoke;
    }
}

3.拦截实现

/**
 * 拦截器
 *
 * @author fengzhen
 * @version v1.0, 2017/9/13 11:24
 */
public interface Interceptor {
    /**
     * 方法之前,对参数进行预处理
     *
     * @author fengzhen
     * @version v1.0, 2017/9/13 11:25
     */
    Object befor(Object o, Method method, Object[] objects, MethodProxy methodProxy);

    /**
     * 方法执行之后,对结果进行操作
     *
     * @author fengzhen
     * @version v1.0, 2017/9/13 11:25
     */
    Object after(Object result);

    /**
     * 方法执行之后,出现异常
     *
     * @author fengzhen
     * @version v1.0, 2017/9/13 11:25
     */
    Object throwErr(Throwable throwable);
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值