美文网首页
Java代理

Java代理

作者: 胖小白_d797 | 来源:发表于2018-12-21 22:15 被阅读0次

    1.简介

    java 代理主要为了解决在客户端调用服务时,加入一些前置或后置处理逻辑。
    代理类通过提供与委托类相同的接口,在接收到客户端调用后,代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。
    Java代理主要实现方式:

    • 1.jdk动态代理 (动态AOP)
    • 2.cglib动态字节码生成

    2.jdk动态代理

    使用Proxy.newProxyInstance生成动态代理

    // 接口
    public interface IUserDao {
        boolean login(String name, String password) throws RuntimeException;
    }
    // 实现类
    public class UserDaoImpl implements IUserDao {
        @Override
        public boolean login(String name, String password) throws RuntimeException{
            return "wonking".equals(name) && "666".equals(password);
        }
    }
    

    动态代理

    public class ProxyFactory {
    
        private ProxyFactory(){
        }
    
        public static <T> Object getProxyInstance(final T t){
            return Proxy.newProxyInstance(t.getClass().getClassLoader(), t.getClass().getInterfaces(),
                    new InvocationHandler() {
                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                             // 代理类为委托类做的预处理
                            System.out.println("-----begin transaction-----");
                            Object returnValue=null;
                            try{
                                // 调用委托类本身的实现
                                returnValue=method.invoke(t, args);
                            }catch (Exception e){
                                 // 代理类为委托类做的异常处理
                                System.out.println("-----do rollback-----");
                            }
                             // 代理类为委托类做的后处理
                            System.out.println("-----finish transaction-----");
                            return returnValue==null ? false : returnValue;
                        }
                    });
        }
    }
    

    使用代理:

    public class ApplicationProxy {
        public static void main(String[] args) {
            UserDaoImpl target=new UserDaoImpl();
            IUserDao proxy= (IUserDao) ProxyFactory.getProxyInstance(target);
            Object result=proxy.login(null,"666");
        }
    }
    

    2.cglib动态字节码生成

    public class CglibProxyTest {
       
        public static void main(String[] args) {
            IUserDao userDao = new UserDaoImpl();
            //创建一个织入器
            Enhancer enhancer = new Enhancer();
            //设置父类
            enhancer.setSuperclass(IUserDao.class);
            //设置需要织入的逻辑
            enhancer.setCallback(new LogIntercept(userDao));
            //使用织入器创建子类
            IUserDao proxy = (IUserDao) enhancer.create();
            proxy.login(null,"666");
        }
        
        public class LogIntercept implements MethodInterceptor {
    
        private Object targetObj;
    
        public LogIntercept(Object targetObj) {
            this.targetObj = targetObj;
        }
    
        @Override
        public Object intercept(Object target, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            //执行原有逻辑
            Object rev = proxy.invoke(targetObj, args);
            //执行织入的日志
            if (method.getName().equals("login")) {
                System.out.println("记录login日志");
            }
            return rev;
        }
    }
    

    3. 自定义类加载器

    Javassist是一个开源的分析、编辑和创建Java字节码的类库。

    Javassist中最为重要的是ClassPool,CtClass ,CtMethod 以及 CtField这几个类。

    • ClassPool:一个基于HashMap实现的CtClass对象容器,其中键是类名称,值是表示该类的CtClass对象。默认的ClassPool使用与底层JVM相同的类路径,因此在某些情况下,可能需要向ClassPool添加类路径或类字节。
    • CtClass:表示一个类,这些CtClass对象可以从ClassPool获得。
    • CtMethods:表示类中的方法。
    • CtFields :表示类中的字段。
      通过 CtMethods. insertBefore 和 CtMethods. insertAfter 修改类方法实现.
    public class ClassLoaderListener  implements Translator {
        public void start(ClassPool pool) throws NotFoundException, CannotCompileException {
        }
    
        public void onLoad(ClassPool pool, String classname) {
            if (!"com.wulouhua.learn.proxy.service.impl.UserDaoImpl".equals(classname)) {
                return;
            }
            try {
                CtClass cc = pool.get(classname);
                CtMethod m = cc.getDeclaredMethod("login");
                m.insertBefore("{ System.out.println(\"记录日志\"); }");
            } catch (NotFoundException e) {
            } catch (CannotCompileException e) {
            }
        }
    
        public static void main(String[] args) {
            UserDaoImpl dao = new UserDaoImpl();
            dao.login("wonking","666");
        }
    }
    
    public class ClassLoaderBootstrap {
        public ClassLoaderBootstrap() {
        }
    
        public static void main(String[] args) {
            demo(args);
        }
    
        static void demo(String[] args) {
            ClassPool cp = ClassPool.getDefault();
            Loader cl = new Loader();
    
            try {
                cl.addTranslator(cp, new ClassLoaderListener());
                cl.run("com.wulouhua.learn.proxy.service.ways.javassist.ClassLoaderListener", args);
            } catch (NotFoundException var4) {
                var4.printStackTrace();
            } catch (CannotCompileException var5) {
                var5.printStackTrace();
            } catch (Throwable var6) {
                var6.printStackTrace();
            }
    
        }
    }
    
    

    Translator

    相关文章

      网友评论

          本文标题:Java代理

          本文链接:https://www.haomeiwen.com/subject/tmyykqtx.html