zoukankan      html  css  js  c++  java
  • Spring(六)动态代理

    在上一篇博客中简单写了一下静态代理,这里主要讲一下动态代理

    动态代理主要有两种

    JDK动态代理   CGLIB动态代理

    那这两种代理有什么区别呢?

    (根据自己的理解总结)

    1.JDK动态代理

    他的特点是:目标对象必须有接口

    他的实质是:创建了接口的一个实现类

    他运行的时机:程序运行时

    2.CGLIB动态代理

    他的特点是:在一个类型没有接口的情况下进行代理

    他的实质是:在内存中构建目标类型的子类

    他运行的时机是:编译时

    简单介绍完这两种代理后,就用个例子具体看怎么实现动态代理

    先做JDK动态代理

    准备一个接口ISomeService,接口中有一个方法doSome(),和一个这个接口的实现类SomeServiceImpl,并重写其中的方法,具体代码如下

    复制代码
    package demo15;
    
    /**
     * Created by mycom on 2018/3/8.
     */
    public interface ISomeService
    {
        public void doSome();
    }
    复制代码
    复制代码
    package demo15;
    
    /**
     * Created by mycom on 2018/3/8.
     */
    public class SomeServiceImpl implements ISomeService {
        public void doSome() {
            System.out.println("十点十分的复习");
        }
    }
    复制代码

    使用JDK动态代理不需要再配置文件中进行配置,所以现在直接进行测试,但是测试的时候不能使用单测,而是使用main方法进行测试

    复制代码
    package demo15;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    /**
     * Created by mycom on 2018/3/8.
     */
    public class Test {
        public static void main(String[] args) {
            //首先创建一个接口的实现类
            final SomeServiceImpl service=new SomeServiceImpl();
            //在调用方法之前想使用动态代理记录一下日志,生成动态代理,返回的是接口
            ISomeService proxyInstance =(ISomeService) Proxy.newProxyInstance(service.getClass().getClassLoader(),
                    service.getClass().getInterfaces(), new InvocationHandler() {
                        /**
                         *
                         * @param proxy  代理对象
                         * @param method  目标类型的方法
                         * @param args  方法的参数
                         * @return
                         * @throws Throwable
                         */
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            //在这里记录一下日志
                            System.out.println("before=====");
                            //调用method 的
                            method.invoke(service,args);//相当于执行目标类型的方法
                            System.out.println("after=======");
                            return null;
                        }
                    });
    
            //调用动态代理中的方法中的方法
            proxyInstance.doSome();
        }
    }
    复制代码

    运行的结果如下

    这说明运行时先执行了invoke方法,再执行接口中doSome的方法,实验成功!

    使用CGLIB动态代理实现上述中的运行结果,如何实现呢?

    这时就不用再创建接口了,(在这里我就使用上面的SomeServiceImpl这个类了,这个类中不用做改动),我直接进行测试了,测试还和上面一样,使用main方法测试,不用配置文件

    复制代码
    package demo09;
    
    
    import org.springframework.cglib.proxy.Enhancer;
    import org.springframework.cglib.proxy.MethodInterceptor;
    import org.springframework.cglib.proxy.MethodProxy;
    
    import java.lang.reflect.Method;
    
    /**
     * Created by mycom on 2018/3/8.
     */
    public class Test {
        public static void main(String[] args) {
            final SomeServiceImpl service=new SomeServiceImpl();
            Enhancer enhancer=new Enhancer();
            enhancer.setSuperclass(service.getClass());
            enhancer.setCallback(new MethodInterceptor() {
                /**
                 *
                 * @param o 代理对象
                 * @param method 目标类型的方法
                 * @param objects 目标方法的参数
                 * @param methodProxy 代理类的方法   是一个新的参数
                 * @return
                 * @throws Throwable
                 */
                public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                    System.out.println("before=====");
                    methodProxy.invoke(service,objects);
                    System.out.println("after=====");
                    return null;
                }
            });
            SomeServiceImpl proxy =(SomeServiceImpl) enhancer.create();
            proxy.doSome();
        }
    }
    复制代码

    运行结果和上面的一样,这就是两种方法实现动态代理!

  • 相关阅读:
    爬取豆瓣电影信息
    MongoDB的聚合操作以及与Python的交互
    matplotlib简单示例
    MongoDB基本操作
    K近邻算法
    Scrapy爬取博客园精华区内容
    爬虫失败
    Markdown基本使用方法
    UITableViewCell高度自适应变化
    KVO和NSNotification
  • 原文地址:https://www.cnblogs.com/a157/p/8537934.html
Copyright © 2011-2022 走看看