什么是AOP?
当然AOP的概念网上一查一大堆,我就不在这贴概念了,大家可以自己看看,在这我就说说自己理解的AOP。
AOP(Aspect Oriented Programming)面向切面编程,即在不影响原有功能的情况下,进行的一次横向扩展。
面向切面和横向扩展我们可以这么理解:有一个分装好的类,我们需要在类的方法执行前后插入额外的代码,要求是不破坏原始类,一种方法是我们可以去继承这个类每个方法前面去增强,但是若是多个方法,每个方法前都去写同样的增强代码不符合我们程序人的身份,所以我们使用AOP的方法,将方法(切入点)和通知(增强功能)组成一个切面再去加入这个对象(使用代理)。
代理,大家可以看看博主另一篇关于代理
模拟AOP代码思路
思路如下:
- 抽象类: Interceptor 这个类中的两个成员,决定了该拦截器是拦截哪个类的哪个方法的。给出三种拦截的抽象方法。
- 类: InterceptorAdpter 这个类继承了上面的抽象方法,给出默认拦截处理,以后由工具使用者来决定要覆盖哪种方法。
- 类:Proxy 这个类负责将代理对象,原对象,还有他自己的拦截器链联系起来。我这里实现的AOP较粗糙,每个代理对象拥有一套自己的拦截器链。对拦截器的增加和删除也在这其中完成。
- 类:ProxyFactory 这个类主要是用来生成代理对象(JDK和CGLIB方式)。
- 类:FactoryProxyBean 这个类用来将类名和Proxy联系起来,以及处理其中拦截链的关系。
具体代码
- 拦截器抽象方法 Interceptor
package MyIntrceptor;
import java.lang.reflect.Method;
/**
* @author quan
* @create 2020-06-22 10:18
*/
public abstract class Interceptor {
private Class<?> klass;
private Method method;
public Interceptor() {
}
public Interceptor(Class<?> klass, Method method) {
this.klass = klass;
this.method = method;
}
public Class<?> getKlass() {
return klass;
}
public void setKlass(Class<?> klass) {
this.klass = klass;
}
public Method getMethod() {
return method;
}
public void setMethod(Method method) {
this.method = method;
}
public abstract boolean before(Object[] args);
public abstract Object after(Object result);
public abstract void dealException(Throwable th);
}
- Proxy
package MyProxy;
import MyException.InterceptorAlReadyExistException;
import MyIntrceptor.Interceptor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
/**
* 装着原对象 代理对象 以及拦截器链
* @author quan
* @create 2020-06-22 10:26
*/
public class Proxy {
private Object proxy;
private Object object;
private List<Interceptor> interceptorList;
public Proxy() {
interceptorList = new ArrayList<>();
}
public Object getProxy() {
return proxy;
}
public void setProxy(Object proxy) {
this.proxy = proxy;
}
public Object getObject() {
return object;
}
public void setObject(Object object) {
this.object = object;
}
public List<Interceptor> getInterceptorList() {
return interceptorList;
}
public void setInterceptorList(List<Interceptor> interceptorList) {
this.interceptorList = interceptorList;
}
//前置拦截
public boolean doBefore(Method method, Object[] args) {
for (Interceptor interceptor : interceptorList) {
if (!interceptor.getMethod().equals(method)) {
continue;
}
if (!interceptor.before(args)) {
return false;
}
}
return true;
}
//后置拦截
public Object doAfter(Method method, Object result) {
for (int i = interceptorList.size()-1; i >= 0; i--) {
Interceptor interceptor = interceptorList.get(i);
if (!interceptor.getMethod().equals(method)) {
continue;
}
result = interceptor.after(result);
}
return result;
}
//异常拦截
public void doException(Method method, Throwable th) throws Throwable {
for (Interceptor interceptor : interceptorList) {
if (!interceptor.getMethod().equals(method)) {
continue;
}
interceptor.dealException(th);
throw th;
}
}
// 当该类拦截器存在时无法添加新拦截器
// 这里会抛出一个自定义异常
public void addInterceptor(Interceptor interceptor) throws InterceptorAlReadyExistException {
String interceptorName = interceptor.getClass().getName();
if (interceptorList.contains(interceptor)) {
throw new InterceptorAlReadyExistException("拦截器" + interceptorName +"已存在");
}
interceptorList.add(interceptor);
}
// 移除拦截器
public void removeInterceptor(Interceptor interceptor) {
if (!interceptorList.contains(interceptor)) {
return;
}
interceptorList.remove(interceptor);
}
}
- ProxyFactory 重点类,真正实现面的织入
package MyProxy;
import MyIntrceptor.Interceptor;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* 用JDKProxy和Cglib两种方式生成
* @author quan
* @create 2020-06-22 10:51
*/
public class ProxyFactory {
private Proxy myProxy;
public Proxy getMyProxy() {
return myProxy;
}
public void setMyProxy(Proxy myProxy) {
this.myProxy = myProxy;
}
public <T> T getCglibProxy(Class<?> klass, Object object) {
myProxy = new Proxy();
Object proxy = cglibProxy(myProxy, klass, object);
myProxy.setProxy(proxy);
myProxy.setObject(object);
return (T) proxy;
}
private <T> T cglibProxy(Proxy myProxy, Class<?> klass, Object object) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(klass);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
return doInvoker(myProxy, object, method, objects);
}
});
return (T) enhancer.create();
}
public <T> T getJdkKProxy(Class<?> klass, Object object) {
myProxy = new Proxy();
Object proxy = JdkProxy(myProxy, klass, object);
myProxy.setProxy(proxy);
myProxy.setObject(object);
return (T) proxy;
}
private <T> T JdkProxy(Proxy myProxy, Class<?> klass, Object object) {
ClassLoader classLoader = klass.getClassLoader();
Class<?>[] interfaces = klass.getInterfaces();
return (T) java.lang.reflect.Proxy.newProxyInstance(classLoader, interfaces, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return doInvoker(myProxy, object, method, args);
}
});
}
private <T> T doInvoker(Proxy proxy, Object object, Method method, Object[] args) throws Throwable {
Object result = null;
boolean b = proxy.doBefore(method, args);
if (!b) return null;
try {
result = method.invoke(object, args);
result = proxy.doAfter(method, result);
} catch (Throwable th) {
proxy.doException(method, th);
}
return (T) result;
}
- FactoryProxyBean
package MyProxy;
import MyException.InterceptorAlReadyExistException;
import MyIntrceptor.Interceptor;
import java.util.HashMap;
import java.util.Map;
/**
* @author quan
* @create 2020-06-22 10:46
*/
public class FactoryProxyBean {
/**
* 用来存放名字和类的映射关系
*/
private static final Map<String, Proxy> beanMap = new HashMap<>();
public FactoryProxyBean() {
}
public <T> T creatCglibProxy(Object object) {
Object proxy = cglibProxy(object.getClass(), object);
return (T) proxy;
}
public <T> T creatCglibProxy(Class<?> klass) throws InstantiationException, IllegalAccessException {
Object proxy = cglibProxy(klass, klass.newInstance());
return (T) proxy;
}
public <T> T creatJdkProxy(Class<?> klass) throws InstantiationException, IllegalAccessException {
Object proxy = jdkProxy(klass, klass.newInstance());
return (T) proxy;
}
public <T> T creatJdkProxy(Object object) {
Object proxy = jdkProxy(object.getClass(), object);
return (T) proxy;
}
private <T> T jdkProxy(Class<?> klass, Object o) {
String klassName = klass.getName();
Proxy proxy = beanMap.get(klassName);
if (proxy != null) {
return (T) proxy.getProxy();
}
ProxyFactory proxyFactory = new ProxyFactory();
T jdkKProxy = proxyFactory.getJdkKProxy(klass, o);
proxy = proxyFactory.getMyProxy();
beanMap.put(klassName, proxy);
return jdkKProxy;
}
private <T> T cglibProxy(Class<?> klass, Object o) {
String klassName = klass.getName();
Proxy proxy = beanMap.get(klassName);
if (proxy != null) {
return (T) proxy.getProxy();
}
ProxyFactory proxyFactory = new ProxyFactory();
T cglibProxy = proxyFactory.getCglibProxy(klass, o);
proxy = proxyFactory.getMyProxy();
beanMap.put(klassName, proxy);
return cglibProxy;
}
// 这里是面向使用者
// 对某类添加拦截器
public void addInterceptor(Class<?> klass, Interceptor interceptor) throws InterceptorAlReadyExistException {
if (!interceptor.getKlass().equals(klass)) {
return;
}
beanMap.get(klass.getName()).addInterceptor(interceptor);
}
public void removeInterceptor(Class<?> klass, Interceptor interceptor) {
if (!interceptor.getKlass().equals(klass)) {
return;
}
beanMap.get(klass.getName()).removeInterceptor(interceptor);
}
}
以上就是AOP面向切面编程的思想,其实本质上还是代理模式和反射机制,在不破坏这个类代码的同时对这个类进行横向扩展(例如拦截或添加日志的操作),实现了松耦合!
当然我这个是简单版的AOP,仅仅为了阐述其内部基本原理,但AOP思想就是这么回事。
最后来做个测试:
package test;
import MyException.InterceptorAlReadyExistException;
import MyProxy.FactoryProxyBean;
import java.lang.reflect.Method;
import java.util.concurrent.CountDownLatch;
/**
* @author quan
* @create 2020-06-22 11:35
*/
public class Test implements Runnable {
private static CountDownLatch countDownLatch = new CountDownLatch(10);
private int a;
private int b;
public Test(int a, int b) {
this.a = a;
this.b = b;
}
public static void main(String[] args) throws NoSuchMethodException, InterceptorAlReadyExistException, InterruptedException {
for (int i = 1; i <= 10; i++) {
Test test = new Test(50, i);
Thread thread = new Thread(test);
thread.start();
}
countDownLatch.await();
System.out.println("allfinished");
}
@Override
public void run() {
Class<?> klass = TsetObject.class;
Method method = null;
try {
method = klass.getDeclaredMethod("div", new Class<?>[]{Integer.class, Integer.class});
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
TestInterceptor testInterceptor = new TestInterceptor(klass, method);
FactoryProxyBean factoryProxyBean = new FactoryProxyBean();
try {
TsetObject o = factoryProxyBean.creatCglibProxy(klass);
factoryProxyBean.addInterceptor(klass, testInterceptor);
Integer div = o.div(a, b);
System.out.println(div);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
本作品采用 知识共享署名-相同方式共享 4.0
国际许可协议 进行许可