美文网首页
Aop(一)面向切面编程理解和动态代理

Aop(一)面向切面编程理解和动态代理

作者: whoisje | 来源:发表于2018-07-23 19:33 被阅读0次

    此文章为本人原创,转载请说明出处。
    https://www.jianshu.com/p/517416271be5
    作者:敲破电脑问到底

    面向切面编程的理解

    • 什么是面向切面的编程呢,可能你比较熟悉的是面向纵面编程,当很多类中有很多重复的代码时,可以通过把重复的代码集中到一个父类中,利用继承机制,可以有效避免大量重复的代码书写。可是这种方法不是万能的。
    • 程序村有一个程序员每天吃早饭和晚饭之前都需要刷牙。
    package com.jack.aop;
    
    /**
     * @author wangwenj
     */
    public class Programmer implements People {
        public String name;
    
        /**
         * init name
         *
         * @param name name
         */
        public Programmer(String name) {
            this.name = name;
        }
    
        /**
         * eat something
         */
        @Override
        public void eatBreakfast() {
            Washing.brushTeeth(name);
            System.out.println(name+" is eating breakfast");
            
        }
    
        /**
         * eat at night
         */
        @Override
        public void eatDinner() {
            Washing.brushTeeth(name);
            System.out.println(name+" is eating dinner");
        }
    }
    

    Washing是他刷牙的方法

    package com.jack.aop;
    
    /**
     * @author wangwenj 
     */
    public class Washing{
        /**
         * 刷牙
         * @param name 名字
         */
        public static void brushTeeth(String name) {
            System.out.println(name+" is brushing teeth now.");
        }
    }
    
    

    所以程序员的每天是这样的

    public class Daily {
        public static void main(String[] args){
            People programmer = new Programmer("old wang");
            programmer.eatBreakfast();
            programmer.eatDinner();
        }
    }
    

    结果是下面这样的

    old wang is brushing teeth now.
    old wang is eating breakfast
    old wang is brushing teeth now.
    old wang is eating dinner
    
    • 程序员发现在eatBreakfasteatDinner方法中都需要刷牙Washing.brushTeeth(name),聪明的程序员觉得这样太麻烦了,于是他想能不能将这些重复的业务抽象出来,可是这是方法级的重复代码,用继承的方式貌似也不行,他突然想到他的老师傅说过的一个概念:面向切面编程,这种重复的代码像树的年轮一样围绕在业务代码的周围,面向切面编程希望某种方式,将这些代码一块一块分离开来,接下来看看聪敏的程序员是怎样做的
    • 程序员定义了一个类WashingHandle它继承了InvocationHandler
    package com.jack.aop;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    public class WashingHandler implements InvocationHandler {
        /**
         * 目标对象
         */
        public Object target;
        private String name;
    
        public WashingHandler(Object target, String name) {
            this.target = target;
            this.name = name;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            /**
             * 把brushTeeth统一植入到method的前面
             */
            Washing.brushTeeth(name);
            /**
             * 调用method
             */
            method.invoke(target, args);
            return null;
        }
    }
    

    这样他就不用重复的写刷牙的代码

    package com.jack.aop;
    
    /**
     * @author wangwenj
     */
    public class Programmer implements People {
        public String name;
    
        /**
         * init name
         *
         * @param name name
         */
        public Programmer(String name) {
            this.name = name;
        }
    
        /**
         * eat something
         */
        @Override
        public void eatBreakfast() {
            //Washing.brushTeeth(name);
            System.out.println(name+" is eating breakfast");
    
        }
    
        /**
         * eat at night
         */
        @Override
        public void eatDinner() {
            //Washing.brushTeeth(name);
            System.out.println(name+" is eating dinner");
        }
    }
    
    

    然后他的日常变成了这样

    package com.jack.aop;
    
    import java.lang.reflect.Proxy;
    
    /**
     * @author wangwenj
     * daily eat
     */
    public class Daily {
        public static void main(String[] args) {
            People people = new Programmer("old wang");
            WashingHandler handler = new WashingHandler(people, "old wang");
            People programmer = (People) Proxy.newProxyInstance(people.getClass().getClassLoader(), people.getClass().getInterfaces(), handler);
            programmer.eatBreakfast();
            programmer.eatDinner();
        }
    }
    
    

    结果和原来的一样

    old wang is brushing teeth now.
    old wang is eating breakfast
    old wang is brushing teeth now.
    old wang is eating dinner
    
    • 程序员的方法叫做动态代理,利用sdk动态代理机制,把把相同的代码围绕在业务的周围,用代理的方式调用方法。不过这种方式需要实现一个接口,从getInterfaces()就可以看出来了。
    • 明天介绍一种不需要创建接口的代理方式GGLIb

    相关文章

      网友评论

          本文标题:Aop(一)面向切面编程理解和动态代理

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