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

此文章为本人原创,转载请说明出处。
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(一)面向切面编程理解和动态代理)