您的位置:首页 > 编程语言 > Java开发

java代理(静态代理和jdk动态代理以及cglib代理)

2017-08-25 17:35 676 查看
转自http://blog.csdn.net/fighterandknight/article/details/51200470

说到代理,脑袋中浮现一大堆代理相关的名词,代理模式,静态代理,jdk代理,cglib代理等等。

记忆特别深刻的是,一次面试中,一位面试官问我,spring的AOP核心采用的设计模式是什么什么模式,阅读过24种设计模式,以及阅读过spring源代码的我竟然答错了,回想起来,真是日了狗了,学过那么多遍的东西都忘记了,结果是装逼失败,自己要狠下心来,把代理都搞懂!

代理模式简述

代理模式是常用的Java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。 

静态代理

由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。下面通过例子展示。

定义接口

[java] view
plain copy

/**  

 * 定义一个账户接口  

 *   

 * @author Fighter 

 * @date 2016-04-20 

 *   

 */    

public interface Count {    

    // 查看账户方法    

    public void queryCount();    

    

    // 修改账户方法    

    public void updateCount();    

    

}   

实现接口

[java] view
plain copy

/**  

 * 委托类(包含业务逻辑)  

 *   

 * @author Fighter 

 * @date 2016-04-20 

 *   

 */    

public class CountImpl implements Count {    

    

    @Override    

    public void queryCount() {    

        System.out.println("查看账户方法...");    

    

    }    

    

    @Override    

    public void updateCount() {    

        System.out.println("修改账户方法...");    

    

    }    

    

}     

添加代理

[java] view
plain copy

/**  

 * 这是一个代理类(增强CountImpl实现类)  

 *   

 * @author Fighter 

 * @date 2016-04-20 

 *   

 */    

public class CountProxy implements Count {    

    private CountImpl countImpl;    

    

    /**  

     * 覆盖默认构造器  

     *   

     * @param countImpl  

     */    

    public CountProxy(CountImpl countImpl) {    

        this.countImpl = countImpl;    

    }    

    

    @Override    

    public void queryCount() {    

        System.out.println("事务处理之前");    

        // 调用委托类的方法;    

        countImpl.queryCount();    

        System.out.println("事务处理之后");    

    }    

    

    @Override    

    public void updateCount() {    

        System.out.println("事务处理之前");    

        // 调用委托类的方法;    

        countImpl.updateCount();    

        System.out.println("事务处理之后");    

    

    }    

    

}     

测试

[java] view
plain copy

/**  

 *测试Count类  

 *   

 * @author Fighter 

 * @date 2016-04-20 

 *   

 */    

public class TestCount {    

    public static void main(String[] args) {    

        CountImpl countImpl = new CountImpl();    

        CountProxy countProxy = new CountProxy(countImpl);    

        countProxy.updateCount();    

        countProxy.queryCount();    

    

    }    

}     

JDK动态代理

特点:只能对实现了接口的类生产代理,不能针对类

定义接口

[java] view
plain copy

/** 

 * 创建业务接口,包含业务可以提供对外的接口 

 *  

 * @author Fighter 

 * @date 2016-04-19 

 * 

 */  

public interface UserService{  

      

    /** 

     * 目标方法  

     */  

    public void add();  

}  

定义实现类

[java] view
plain copy

/** 

 * 创建业务接口实现类 

 *  

 * @author Fighter 

 * @date 2016-04-19 

 * 

 */  

public class UserServiceImpl implements UserService{  

    @Override  

    public void add() {  

     System.out.println("----------add----------");  

          

    }  

}  

定义代理

[java] view
plain copy

/** 

 * 自定义简单的Invocation,对接口提供的方法进行增强 

 *  

 * @author Fighter 

 * @date 2016-04-19 

 */  

public class MyInvocationHandler implements InvocationHandler {  

      

      

    //目标对象  

    private Object target;  

      

    /** 

     * 构造方法 

     * @param target 目标对象 

     */  

    public MyInvocationHandler(Object target) {  

        super();  

        this.target=target;  

    }  

       

    <span style="white-space:pre">    </span>/** 

     * 执行目标对象的方法  

     */  

    public Object invoke(Object proxy, Method method, Object[] args)  

            throws Throwable {  

          

         //在目标方法执行前简单打印一下  

         System.out.println("----------before----------");  

           

         //执行目标方法对象  

         Object result=method.invoke(target, args);  

           

         //在目标方法执行之后简单打印一下  

         System.out.println("----------after----------");  

          

         return result;  

    }  

      

      

    /** 

     * 获取目标对象的代理对象 

     * @return 代理对象 

     */  

    public Object getProxy(){  

        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),   

                this.target.getClass().getInterfaces(),this);  

    }  

      

      

}  

jdk动态代理测试

[java] view
plain copy

public class ProxyTest{  

      

    @Test  

    public void testProxy() throws Throwable{  

        //实例化目标对象  

        UserService userService=new UserServiceImpl();  

          

        //实例化Invocation  

        MyInvocationHandler invocationHandler=new MyInvocationHandler(userService);  

          

        //根据目标生成代理对象  

        UserService proxy=(UserService)invocationHandler.getProxy();  

          

        //调用代理对象方法  

        proxy.add();  

    }  

}  

CGLIB动态代理示例

JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。 

CGLIB是一个强大的高性能的代码生成包。被广泛的许多AOP框架使用,如Spring的AOP和dynaop,为他们提供方法的interceptor(拦截),最流行的是OR
Mapping工具hibernate也是使用CGLIB来代理单端的single-ended(多对一和一对一)关联(对集合的延迟抓取是采用其他机制实现)。EsayMock和jMock是通过模仿(moke)对象来测试java代码的包。他们都是通过使用CGLIB来为那些没有接口的类创建模仿(moke)对象。

我们先通过demo来快速了解CGLIB的使用示例。

定义实现类

[java] view
plain copy

/**  

 * 这个是没有实现接口的实现类  

 *   

 * @author student  

 *   

 */    

public class BookFacadeImpl {    

    public void addBook() {    

        System.out.println("增加图书的普通方法...");    

    }    

}   

定义代理

[java] view
plain copy

/**  

 * 使用cglib动态代理  

 *   

 * @author student  

 *   

 */    

public class BookFacadeCglib implements MethodInterceptor {    

    private Object target;    

    

    /**  

     * 创建代理对象  

     *   

     * @param target  

     * @return  

     */    

    public Object getInstance(Object target) {    

        this.target = target;    

        Enhancer enhancer = new Enhancer();    

        enhancer.setSuperclass(this.target.getClass());    

        // 回调方法    

        enhancer.setCallback(this);    

        // 创建代理对象    

        return enhancer.create();    

    }    

    

    @Override    

    // 回调方法    

    public Object intercept(Object obj, Method method, Object[] args,    

            MethodProxy proxy) throws Throwable {    

        System.out.println("事物开始");    

        proxy.invokeSuper(obj, args);    

        System.out.println("事物结束");    

        return null;    

    

    

    }    

    

}    

编写Cglib测试

[java] view
plain copy

public class TestCglib {    

        

    public static void main(String[] args) {    

        BookFacadeCglib cglib=new BookFacadeCglib();    

        BookFacadeImpl bookCglib=(BookFacadeImpl)cglib.getInstance(new BookFacadeImpl());    

        bookCglib.addBook();    

    }    

}    

总结

当阅读到spring的AOP章节的时候发现其中使用了代理的一些方法,在此复习一下代理的一些实现以及操作。代理-Spring AOP的核心设计模式。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: