初识动态代理-jdk,CGLIB,拦截器

像代理服务器一样,你想访问真实服务器不直接访问而是通过一个中转站,代理服务器访问;
调用真实对象的一个方法不直接调用,而是通过产生的一个代理对象调用。
人家是动态编程,需要在原来的方法的功能基础上再添加一些功能,而不用改变这个方法的签名,原来调用这个方法的类依然能正常工作。搜索
比如,现在要把一段文本发送给另一个人,普通方法是 void send(File a),现在我们弄出个特性,就像 Spring AOP 那样,在 send 之前给这个 a 压缩一下。原来的程序没有压缩功能,现在我们需要添加的话而不改变原来所有的代码的话就得用类似 AOP 这样的代码来处理。

代理分为两步:第一,先产生一个代理对象,并和真实的对象关联起来,产生代理关系;第二,实现代理对象的代理逻辑方法,这里一般都是由一个实现一个接口做的,JDK动态代理用java.lang.reflect.InvocationHandler这个接口;CGLIB用org.springframework.cglib.proxy.MethodInterceptor接口。

首先是JDK动态代理的代码:因为JDK动态代理必须借助一个接口才能实现产生代理对象:
定义一个接口

public interface Youplando {
public void dosomething(String string);
}
package 设计模式;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

class Youwanttodo implements Youplando{

    @Override
    public void dosomething(String string) {
        // TODO Auto-generated method stub
        System.out.println("我想做"+string);
    }
}

/**
 * @author Administrator
 * JDK代理分为两步:
 * 1.代理对象和真实对象简历代理关系
 * 2.实现代理对象的代理逻辑方法
 */
class JDKproxyExample implements InvocationHandler{
    //真实对象
    private Object target = null;

    /**
     * JDK代理第一步:~~~~~
     * newProxyInstance的三个参数:第一个是target本身的类加载器;
     * 第二个是代理对象下挂在哪些接口下
     * 第三个是实现方法逻辑的代理类,这里就是JDKproxyExample这个当前类,必须实现InvocationHandler接口,重写invoke方法
     * @param target 真实的对象
     * @return 代理对象
     */
    public Object bind(Object target) {
        this.target = target;
        return Proxy.newProxyInstance
                (target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }

    /**
     * JDK代理第二步:~~~~~
     * @param proxy 代理对象,
     * @param method 调用的方法
     * @param args[] 方法参数列表
     * @return Object 代理结果
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //相当于反射调用了真实对象的方法
        System.out.println("调用真实方法前哦");
        Object object = method.invoke(target, args);
        System.out.println("调用真实方法后哦");
        return object;
    }
}

public class JDKproxy {
    public static void main(String[] args) {
        //先实例化JDKproxyExample,用它来代理
        JDKproxyExample jdk = new JDKproxyExample();
        //真实对象
        Youwanttodo realinstance = new Youwanttodo();
        //产生代理对象proxy;
        Youplando proxy = (Youplando) jdk.bind(realinstance);
        //代理对象调用方法
        proxy.dosomething("我我想做的");
    }
}

CGLIB动态代理,不需要接口,但是是spring的代理包:

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
package Test;

import java.lang.reflect.Method;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

class Iwangtodo{
    public void Iwangtodo(String string) {
        System.out.println("i really wang to be"+string);
    }
}

class CglibProxyExample implements MethodInterceptor{

    /**
     * 还是第一步!!!!!!!!!!
     * 生成CGLIB代理对象
     * @param cls 真实对象
     * @return 代理对象
     */
    public Object getProxy(Class cls) {
        //CGLIB enhancer增强类对象
        Enhancer enhancer = new Enhancer();
        //设置增强类型
        enhancer.setSuperclass(cls);
        //定义代理逻辑对象为当前对象,要求当前对象实现MethodInterceptor方法
        enhancer.setCallback(this);
        //返回代理对象
        return enhancer.create();
    }

    /**
     * 还是第二部!!!!!!!!!
     * 生成CGLIB代理对象
     * @param proxy 代理对象
     * @param method 调用方法
     * @param arg 方法参数
     * @param methodproxy 方法代理
     * @return 代理结果
     */
    public Object intercept(Object proxy, Method method, Object[] arg,
            MethodProxy methodproxy) throws Throwable {
        // TODO Auto-generated method stub
        System.out.println("调用真实方法前");
        Object result = methodproxy.invokeSuper(proxy, arg);
        System.out.println("调用真实方法后");
        return result;
    }
}

public class CGLIBproxy {
    public static void main(String[] args) {
        //代理实例
        CglibProxyExample cglib = new CglibProxyExample();
        //用代理实例产生一个代理对象
        Iwangtodo iwangtodo = (Iwangtodo) cglib.getProxy(Iwangtodo.class);
        //代理对象调用方法
        iwangtodo.Iwangtodo("攻城狮!!");
    }
}

拦截器代码:

package 设计模式;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/*实现了拦截器接口*/
class InterceptorImp implements Interceptor{
    @Override
    public boolean before(Object proxy, Object target, Method method, Object[] args) {
        // TODO Auto-generated method stub
        System.out.println("反射前");
        return false;
    }

    @Override
    public void around(Object proxy, Object target, Method method, Object[] args) {
        // TODO Auto-generated method stub
        System.out.println("取代了被代理对象的方法");
    }

    @Override
    public void after(Object proxy, Object target, Method method, Object[] args) {
        // TODO Auto-generated method stub
        System.out.println("反射后");
    }

}

/*被调用方法的类,实现了接口*/
class Youwanttodo implements Youplando{
    @Override
    public void dosomething(String string) {
        // TODO Auto-generated method stub
        System.out.println("我想做"+string);
    }
}

/*JDK动态代理中使用拦截器*/
public class InterceptorJdkProxy implements InvocationHandler {

    private Object target;//真实对象
    private String interceptorClass = null;//拦截器全限定名

    //传入真实对象,和拦截器名字
    public InterceptorJdkProxy(Object target,String interceptorClass) {
        // TODO Auto-generated constructor stub
        this.target = target;
        this.interceptorClass = interceptorClass;
    }

    /*第一步,取得代理对象*/
    public static Object bind(Object target,String interceptorClass) {
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), 
                target.getClass().getInterfaces(), new InterceptorJdkProxy(target,interceptorClass));
    }

    /*第二步实现代理逻辑方法*/
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // TODO Auto-generated method stub
        if (interceptorClass==null) {
            //如果没有拦截器,调用真实对象的方法了
            return method.invoke(target, args);
        }
        //返回代理结果
        Object result = null;
        /*生成拦截器*/
        Interceptor interceptor = (Interceptor) Class.forName(interceptorClass).newInstance();
        if (interceptor.before(proxy, target, method, args)) {
            //before为true;反射方法
            result = method.invoke(target, args);
        }else {
            //before为false
            interceptor.around(proxy, args, method, args);
        }
        //后置方法
        interceptor.after(proxy, target, method, args);
        return result;
    }

    public static void main(String[] args) {
        //代理对象
        Youplando proxy = (Youplando) InterceptorJdkProxy.bind(new Youwanttodo(), "设计模式.InterceptorImp");
        proxy.dosomething("a goodboy");
    }

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

obession

觉得有用可以打赏咖啡一杯~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值