此文章为本人原创,转载请说明出处。
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
- 程序员发现在
eatBreakfast
和eatDinner
方法中都需要刷牙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