美文网首页
Javassit动态代理

Javassit动态代理

作者: 阿福德 | 来源:发表于2019-05-07 12:06 被阅读0次
    图片要是侵权了, 麻烦告知,秒删.jpg

    背景

    最近在处理一个生产问题的时候,看到依赖的三方库中用到了javassit 作为动态代理,然后就着手学习了javassit作为动态代理的实现。
    但是网上很多的例子都是错误, 比如有些例子,既然是做动态代理,生产代理的时候,居然不需要使用被代理对象, 我也是醉了。

    动态代理有如下几个对象

    1. 被代理对象
    2. 代理对象(动态生成的,也是代理工厂产生的)
    3. 代理增强
    4. 代理工厂(可以没有)

    废话不多说,直接撸代码。

    javaassit版本

            <dependency>
                <groupId>javassist</groupId>
                <artifactId>javassist</artifactId>
                <version>3.12.1.GA</version>
            </dependency>
    

    被代理对象

    public class Target {
        public int count = 10;
    
        public Target setCount(int count) {
            this.count = count;
            return this;
        }
    
        public void test1(){
            throw new RuntimeException("test throw exception");
        }
        public void test2(){
            System.out.println("test2 success");
        }
    }
    

    代理增强

    import javassist.util.proxy.MethodHandler;
    
    public abstract class Aop implements MethodHandler {
        private Object target;
    
        public Aop(Object target) {
            this.target = target;
        }
    
        public Object getTarget() {
            return target;
        }
    }
    
    //////////////////////////////////////////////////////////////////////////////
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import java.lang.reflect.Method;
    
    public class LogAop extends Aop  {
        private static Logger logger = LoggerFactory.getLogger(LogAop.class);
    
        public LogAop(Object target) {
            super(target);
        }
    
        @Override
        public Object invoke(Object proxy, Method targetMethod, Method proxyMethod, Object[] args)
                throws Throwable {
            String resultMessage = "Fail";
            Long startTime = System.currentTimeMillis();
            logger.info("enter method:" + targetMethod.getName());
            try {
                Object ret = targetMethod.invoke(getTarget(), args);
                resultMessage = "Success";
                return ret;
            }finally {
                logger.info("exist ["+resultMessage+"] method:" + targetMethod.getName()+", cost "+ (System.currentTimeMillis()-startTime)+" ms");
            }
        }
    }
    

    代理工厂

    import javassist.util.proxy.ProxyFactory;
    import javassist.util.proxy.ProxyObject;
    
    
    public class JavassistProxyFactory<T> {
    
        public T getProxy(Aop aop) throws IllegalAccessException, InstantiationException {
            ProxyFactory proxyFactory = new ProxyFactory();
    
            // 让代理类继承自目标类。
            proxyFactory.setSuperclass(aop.getTarget().getClass());
            Class<ProxyObject> classes=proxyFactory.createClass();
            //创建代理对象
            ProxyObject proxyObject=classes.newInstance();
            //为代理类设置
            proxyObject.setHandler(aop);
    
            // 通过字节码技术动态创建子类实例
            return (T) proxyObject;
        }
    }
    

    测试类

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    public class Test {
        private static Logger logger = LoggerFactory.getLogger(LogAop.class);
        public static void main(String[] args) throws IllegalAccessException, InstantiationException {
            JavassistProxyFactory<Target> factory = new JavassistProxyFactory<>();
            Target target = new Target();
            target.setCount(100);
            LogAop aop = new LogAop(target);
            Target proxy = factory.getProxy(aop);
    
            try {
                proxy.test1();
            }catch (Exception e) {
                logger.error("删除失败", e);
            }
            try {
                proxy.test2();
            }catch (Exception e) {
                logger.error("保存失败", e);
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:Javassit动态代理

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