发现问题
我们先来看看开发过程中有可能会遇到什么问题,而AOP又能为我们带来什么的好处,通过这种方式,能够真正的理解什么是AOP,为什么要用AOP
假设我们要实现一个计算器功能,要求
1. 能够实现基本的加减乘除计算功能
2. 要求实现日志功能
写一个计算器接口
package com.zj.aop;
public interface Calcultor {
int add(int a, int b);
int sub(int a, int b);
}
实现类
package com.zj.aop;
public class CalcultorImpl implements Calcultor{
@Override
public int add(int a, int b) {
System.out.println("Log:method add begin:"+a+" and "+b);
int result = a + b;
System.out.println("Log:method add end:"+a+" and "+b);
return result;
}
@Override
public int sub(int a, int b) {
System.out.println("Log:method sub begin:"+a+" and "+b);
int result = a - b;
System.out.println("Log:method add end:"+a+" and "+b);
return result;
}
}
问题
- 为了方便,这里只写出加减两个方法
- 也许你已经发现问题了,我们为了实现日志,在核心代码的前后都加上了System.out.println(),但是如果有一百个方法,难道一个个加上去吗?
- 就算你有耐心一个个加上去,哪天需求变化了,对输出的日志有了其他要求,又得一个个改过去,这时候你还有耐心去改吗
使用动态代理解决以上问题
实现类中不输出日志
package com.zj.aop;
public class CalcultorImpl implements Calcultor{
@Override
public int add(int a, int b) {
int result = a + b;
return result;
}
@Override
public int sub(int a, int b) {
int result = a - b;
return result;
}
}
写一个代理类
package com.zj.aop;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
public class CalcultorProxy {
//要代理的对象
private Calcultor target;
public CalcultorProxy(Calcultor target){
this.target = target;
}
public Calcultor getCalcultorProxy() {
Calcultor proxy = null;
//代理对象由哪个类加载器加载
ClassLoader loader = target.getClass().getClassLoader();
//代理对象的类型,即其中有哪些方法
Class[] interfaces = new Class[]{Calcultor.class};
InvocationHandler h = new InvocationHandler() {
/**
* proxy:正在返回的代理的对象,一般不去使用它
* method: 被调用的方法
* args: 被调用方法的参数
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
String methodName = method.getName();
//日志
System.out.println("Log:method "+methodName+" begin:"+Arrays.asList(args));
//调用方法,返回结果
Object result = method.invoke(target,args);
//日志
System.out.println("Log:method "+methodName+" end:"+Arrays.asList(args));
return result;
}
};
proxy = (Calcultor) Proxy.newProxyInstance(loader, interfaces, h);
return proxy;
}
}
public static void main(String[] args) {
// Calcultor calcultor = new CalcultorImpl();
// calcultor.add(1, 2);
// calcultor.sub(3, 1);
Calcultor target = new CalcultorImpl();
Calcultor proxy = new CalcultorProxy(target).getCalcultorProxy();
proxy.add(1, 2);
proxy.sub(3, 1);
}
结果
成功实现日志功能,而不影响Calcultor的核心实现代码
但是这样还是相对麻烦,而且对程序员要求高一些,那么重点来了,使用AOP来解决上面的问题
使用AOP解决上述问题,请看下一个笔记