美文网首页程序员
Java及Spring框架中的AOP技术汇总--使用JDK反射对

Java及Spring框架中的AOP技术汇总--使用JDK反射对

作者: 随风而行之青衫磊落险峰行 | 来源:发表于2018-02-10 14:31 被阅读194次

    上一篇中我们使用接口方式,利用虚函数动态绑定机制实现了一个代理模式,来进行方法的拦截(AOP)处理。

    本篇换成使用JDK内置的方式来进行方法(AOP)拦截

    1. 同前篇,定义IGreet接口:
    package blf_aop_demo;
    /*
    1. 从java语言的角度来演示aop的两种实现(基于接口实现和基于类实现)
    2. spring
    */
    public interface IGreet {
        void sayHello(String name);
    
        void sayGoodBye(String name);
    }
    
    1. 同前篇,实现IGreet接口:
    package blf_aop_demo;
    
    public class GreetImp implements IGreet {
        public void sayHello(String name) {
            System.out.println("Hello " + name);
        }
    
        public void sayGoodBye(String name) {
            System.out.println("GoodBye " + name);
        }
    }
    
    1. 不同前篇,而是实现JDK中的java.lang.reflect.InvocationHandler接口:
    package blf_aop_demo;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    //JDKProxy
    public class ReflectGreetProxy implements InvocationHandler {
    
        //注意: 这里使用了Object类型,提升到java类结构体系的最高层
        //java中一切都是Object,万物之源!
        
        private Object target;// 真实的,被代理的对象
    
        // 私有够着方法,用于限制new出本对象
        // 只能被下面的工厂方法使用
        private ReflectGreetProxy(Object target) {
            this.target = target;
        }
    
        public static Object newInstance(Object obj) {
            //使用Proxy静态方法
            //Proxy是java reflect包中的一个静态类(全部是静态方法)
            //Proxy作用是利用反射,自动生成target类的代理类一切必要的内容
            //很关键一点,obj.getClass().getInterfaces(),意味着使用JDK中的反射Proxy只能基于接口继承的对象
            return java.lang.reflect.Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),
                    new ReflectGreetProxy(obj));
        }
    
        // Method method:調用的方法
        // Object[] args:方法要傳入的參數
        // invoke实现对GreetImpl中方法的调用,同时也可以在这里加入自己想要实现的操作
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            // TODO Auto-generated method stub
            Object result;
            try
            {
                //自定義的處理
                System.out.println("--before method " + method.getName());
                //調用GreetImpl中方法
                result = method.invoke(target, args);
            }catch(InvocationTargetException e)
            {
                throw e.getTargetException();
            }catch(Exception e)
            {
                throw new RuntimeException("unexpected invocation exception: " + e.getMessage());
            }finally
            {
                System.out.println("--after method " + method.getName());
            }
            return result;
        }
    }
    

    4.测试代码:

     public static void testReflectGreet(){
            //生成一个真实对象
            IGreet real = new GreetImp();
            //从真实对象生成一个代理对象
            IGreet greet = (IGreet)ReflectGreetProxy.newInstance(real);
            
            //此时调用的是代理对象上的say系列方法
            //代理对象内部会调用public Object invoke(Object proxy, Method method, Object[] args)
            //对其所有方法进行拦截
            greet.sayHello("jackyBu");
            greet.sayGoodBye("jackyBu");
        }
    
    public static void main(String[] args) {
            System.out.println("blf_aop_demo_test");
            testReflectGreet();
        }
    
    1. 测试结果:
    blf_aop_demo_test
    --before method sayHello
    Hello jackyBu
    --after method sayHello
    --before method sayGoodBye
    GoodBye jackyBu
    --after method sayGoodBye
    
    • 我们会看到,代理对象会对真实对象的所有方法进行拦截,如果我有选择性的拦截,那就可以通过过滤被拦截方法的名称就可以了,例如你只想拦截sayHello,而不想拦截sayGoodBye,则进行方法名判定就可以了。

    • 相对于自己实现,使用JDK反射Proxy方式更加简单,特别是在真实对象有很多方法时,优势就显示出来了

    • 唯一的限制:

    很关键一点,obj.getClass().getInterfaces(),意味着使用JDK中的反射Proxy只能代理基于接口继承的对象
    JDK代理要求被代理的类必须实现接口,有很强的局限性

    从上面这句注释可以了解到,jdk反射Proxy只能对接口进行方法拦截,不能对的方法进行拦截

    下一篇我们来解决如何实现类的动态代理

    相关文章

      网友评论

        本文标题:Java及Spring框架中的AOP技术汇总--使用JDK反射对

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