zoukankan      html  css  js  c++  java
  • Java动态代理知识

    切面:  包括切点和增强,切点是执行点的表示,增强包括增强逻辑代码和方位信息,其实增强也是一个一般的切面,只是此切面针对所有类的所有方法。(Spring目前只支持方法级别的增强)

    两种动态代理实现切面技术

               1.JDK动态代理  主要针对接口类型数据

                     把横切代码安置在MyInnovacationHandler中                

    public class MyInnovacationHandler implements InvocationHandler {
    
        private Waiter waiter;
    //设置要调用的对象
    public MyInnovacationHandler(Waiter waiter) { this.waiter = waiter; } @Override
    // proxy表示代理对象 method表示要代理的方法 args表示目标方法参数
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("模拟调用 how are you " + args[0]);
    //调用目标对象 Object object
    = method.invoke(waiter, args); return object; } }

        调用JDK动态代理的代码

    public static void textJDKProxy() {
    //Waiter 表示接口 Waiter waiter
    = new NaviWaiter(); MyInnovacationHandler handler = new MyInnovacationHandler(waiter); Waiter proxy = (Waiter) Proxy.newProxyInstance(waiter.getClass().getClassLoader(), waiter.getClass().getInterfaces(), handler); proxy.greetTo("张"); proxy.serveTo("刘"); }

              2. CGLIB动态代理技术:针对类数据代理,采用底层字节码技术,可以为一个类创建子类,在子类中采用拦截的技术拦截所有父类方法的调用 并顺势织入横切逻辑。

                 代理创建对象代码如下

    public class CGlibProxy implements MethodInterceptor {
        private Enhancer enhancer = new Enhancer();
    
        public Object getProxy(Class clazz) {
    //        设置父类的字节码
            enhancer.setSuperclass(clazz);
    //        设置使用本对象的invoke方法
            enhancer.setCallback(this);
    //        通过字节码技术动态创建子类实例
            return enhancer.create();
        }
    
        /**
         * @param o           表示目标类的实例
         * @param method      目标类方法的反射对象
         * @param objects     d动态入参数
         * @param methodProxy 方法代理
         * @return
         * @throws Throwable
         */
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
    //        织入横切代码
            PerFormanceMonitor.begin(o.getClass().getName() + "." + method.getName());
    //        调用目标方法
            Object object = methodProxy.invokeSuper(o, objects);
            //  织入横切代码
            PerFormanceMonitor.end();
            return object;
        }
    }

        调用代码

    public static void proxy2() {
             //创建CGlibProxy代理对象
            CGlibProxy cGlibProxy = new CGlibProxy();
    //获得代理对象 其实就是此类的子类 ForumServiceImpl forumService
    = (ForumServiceImpl) cGlibProxy.getProxy(ForumServiceImpl.class);
    //调用方法 forumService.removeFrume(
    10); forumService.removeTopic(10); }

          注意:      两种动态代理方法的区别:JDK代理只针对接口类型数据,此中方法创建代理对象比CGlibProxy快,但代理对象的性能没有CGlibProxy方式高,所以在对象创建不频繁时(即sigleton),建议使用CGlibProxy方式实现动态代理.

              针对CGlibProxy方式,只是通过创建子类的方式实现,因此对于Final类型类或具有final变量的类而言,这就容易出现问题。所以并非所有对象都能创建代理

  • 相关阅读:
    Qt中暂停线程的执行(主线程和工作线程共用一把锁,一旦主线程将它锁上,工作线程就无法运行了,这也是一个办法)
    罗振宇 知识就是力量:怎样逼自己成为一个上进的人
    GammaRay 是一个允许你查看 Qt 应用程序甚至在某种程度上修改它的独特应用,可谓是 Debugger 的良好补充
    VSCode高效开发插件
    微软白板Excel xls列号数字转字母
    如何渡过中年危机
    增量数据同步中间件
    N位N进制里有多少个N
    Orchard Core学习一
    Consul做服务发现
  • 原文地址:https://www.cnblogs.com/09120912zhang/p/7806424.html
Copyright © 2011-2022 走看看