zoukankan      html  css  js  c++  java
  • 关于jdk代理和cglib代理

      简单的说说两个代理的不同,CGLIB代理可以视为JDK代理的补充,JDK的代理是基于接口来实现的,也就是说使用JDK代理的类必须包含至少一个接口,调用代理的方法时,会不断地找寻接口中与调用方法匹配的值,然后通过反射找到此接口的方法,调用InvocationHandler的invoke方法拦截代理。

      再说CGLIB,与JDK不同,CGLIB不要求代理类必有什么接口的,它通过制造一个类,通过继承的方式实现代理类,类似于钩子回调,也就是说CGLIB要求代理的类不能是final调用的方法也不能是final的。通过查看各开源框架,也能够发现使用CGLIB代理,反射,泛型等乱七八糟的方法比较多。

    cglib有两种可选方式,继承和引用。第一种是基于继承实现的动态代理,所以可以直接通过super调用target方法,但是这种方式在spring中是不支持的,因为这样的话,这个target对象就不能被spring所管理,所以cglib还是才用类似jdk的方式,通过持有target对象来达到拦截方法的效果。通过CGLIB代理可以很大程度的增强代理方法。如spring中AOP相关的拦截方法,和hibernate中,毕竟hibernate中有大量的缓存机制和ORM工具方法。当然我并没有说JDK代理要比CGLIB好。在框架中二中代理都被大量的使用,并且在spring中如spring AOP中默认是使用JDK代理实现来实现接口,你可以强制使用CGLIB。在使用struts2框架时,你可能碰到过一种莫名奇妙的场景,就是使用ActionAware接口时,调用代理方法报错找不到有关的方法,这很可能是因为Spring关注到你的action实现了某个接口,于是为你使用JDK代理,进而使你调用的方法不被找到。

    那么接下来请参照下面两段代码,进一步理解

    首先是基础工作,一个接口:

    public interface UserService {
        Boolean addUser(User user);
    }

    实现类

    public class UserServiceImpl implements UserService {
    
        @Autowired
        private UserMapper userMapper;// 插入用户 用户id用uuid
        @Override
        public Boolean addUser(User user) {
            user.setRole_id(11001);
            user.setActivecode(UUID.randomUUID().toString().replace("-", ""));
            user.setUser_id(UUID.randomUUID().toString().replace("-", ""));
            user.setRegister(new Date());
            return true;//此处请无视// TODO
    
        }
    }

    这里是代理的实现

    package com.dabai.test
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
     
     
    public class MyInvocationHandler implements InvocationHandler {
        private Object target;
     
        MyInvocationHandler() {
            super();
        }
     
        MyInvocationHandler(Object target) {
            super();
            this.target = target;
        }
     
        @Override
        public Object invoke(Object o, Method method, Object[] args) throws Throwable {
            if("getName".equals(method.getName())){
                System.out.println("start--" + method.getName());
                Object result = method.invoke(target, args);
                System.out.println("end--" + method.getName());
                return result;
            }else{
                Object result = method.invoke(target, args);
                return result;
            }
     
        }
    } 

    这里调用

    package com.dabai.test.jdk;
     
    package com.dabai.mytwo.service;
    package com.dabai.mytwo.service.impl;
    
    import com.dabai.mytwo.entity.User;
    import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; public class Proxy_Jdk { public static void main(String[] args) { UserService userService = new UserServiceImpl(); InvocationHandler invocationHandler = new MyInvocationHandler(userService); UserService userServiceProxy = (UserService)Proxy.newProxyInstance(userService.getClass().getClassLoader(), userService.getClass().getInterfaces(), invocationHandler); userServiceProxy.addUser(new User()); } }

    接下来是CGLIB代理

    package com.dabai.test.cglib;
     
     
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
     
    import java.lang.reflect.Method;
     
     
    public class CglibProxy implements MethodInterceptor {
        @Override
        public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
            System.out.println("start cg----" + methodProxy.getSuperName());
            System.out.println(method.getName());
            Object obj = methodProxy.invokeSuper(o, args);
            System.out.println("end----" + methodProxy.getSuperName() );
            return obj;
        }
    }
    package com.dabai.test.cglib;
     
    package com.dabai.mytwo.service;
    package com.dabai.mytwo.service.impl
    import net.sf.cglib.proxy.Enhancer;
     
     
     
    public class Proxy_Cglib {
        public static void main(String[] args) {
            CglibProxy cglibProxy = new CglibProxy();
     //在此处增强代理方法
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(UserServiceImpl.class);
            enhancer.setCallback(cglibProxy);
     
            UserService userService = (UserService)enhancer.create();
            userService.addUser(new User());
        }
    }
  • 相关阅读:
    Understand each field of AWR [ID 884046.1]
    Linux iptables 防火墙 添加删除 端口
    SCSI 总线和协议
    How to create physical standby database with 11g RMAN DUPLICATE FROM ACTIVE DATABASE [ID 747250.1]
    How to create physical standby database with 11g RMAN DUPLICATE FROM ACTIVE DATABASE [ID 747250.1]
    Linux iptables 防火墙 添加删除 端口
    Oracle alert log 按天 存放 脚本
    文件系统 和 网络附接存储(NAS: Network Attached Storage)
    SCSI 总线和协议
    IP(Internet Protocal) 地址 说明
  • 原文地址:https://www.cnblogs.com/notably/p/10800796.html
Copyright © 2011-2022 走看看