【Java】手写实现AOP及感悟发现
什么是AOP?
AOP即面向切面编程,能够让我们在不影响原有功能的情况下,对程序进行横向扩展,面向切面?横向扩展?第一次接触这两个词的时候我也是一脸懵逼。
说说我的理解:如果现有某个类的某个方法是已经封装好的,现在我们需要在执行这个方法的时候加点自己的东西,对原方法的执行进行干预。当然要求是不能破坏原类。这时需要AOP思想,把这个方法,即切点扩展成一个面来进行操作。(生成该类的代理,对代理进行操作)
例如:给这个方法加日志,执行方法前进行拦截等。
实现代理的方法
JDK的方法和CGLIB的方法
1.JDK方法:利用java.lang.reflect.Proxy类,但局限在于需要被代理的对象必须实现一个接口,如果被代理对象没有实现任何接口,或者被代理的业务方法没有相应的接口,就无法得到代理对象,这个时候就需要CGLIB方式产生代理对象。
2.CGLIB方法:原理实际上是动态生成被代理类的子类字节码,由于其字节码都是按照jvm编译后的class文件的规范编写的,因而其可以被jvm正常加载并运行,当然他也有局限,如果被代理类的方法被声明final类型,那么Cglib代理是无法正常工作的,因为final类型方法不能被重写。
下面先给出实现代理的两种方法的代码
private <T> T cglibProxy(Class<?> klass, Object object) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(klass);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
return doInvoker(object, method, args);
}
});
return (T) enhancer.create();
}
private <T> T jdkProxy(Class<?> klass, Object object) {
ClassLoader classLoader = klass.getClassLoader();
Class<?>[] interfaces = klass.getInterfaces();
return (T) Proxy.newProxyInstance(classLoader, interfaces, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return doInvoker(object, method, args);
}
});
}
以上就是实现代理的两种方式,这里有个doInvoker方法,即根据反射机制实现对原方法的调用!这里指的一提的就是:当我们使用代理对象执行方法的时候,其内部调用方法的对象其实还是原对象,并不是代理对象执行该方法!
手写实现AOP代理的思路
这是我实现AOP的思路:
- 抽象类:FyIntercepter 这个类中的两个成员,决定了该***是拦截哪个类的哪个方法的。给出三种拦截的抽象方法。
- 类:FyIntercepterAdapter 这个类继承了上面的抽象方法,给出默认拦截处理,以后由工具使用者来决定要覆盖哪种方法。
- 类:FyProxy 这个类负责将代理对象,原对象,还有他自己的***链联系起来。我这里实现的AOP较粗糙,每个代理对象拥有一套自己的***链。对***的增加和删除也在这其中完成。这里还有一个成员是用来判断该类是否被注入,这个以后会在解决IOC循环依赖注入给出的,在这篇博客中不会被用到。
- 类:ProxyFactory 这个类主要是用来生成代理对象(JDK和CGLIB方式),并对FyProxy进行设置 。
- 类:ProxyBeanFactory 这个类用来将类名和FyProxy联系起来,可以看出来我这里一个类只有与之对应的一个***链
具体代码
- ***抽象方法 FyIntercepter
package com.funyoo.aop.core;
import java.lang.reflect.Method;
public abstract class FyInterceptor {
private Class<?> klass;
private Method method;
public FyInterceptor() {
}
public FyInterceptor(Class<?> klass, Method method) {
this.klass = klass;
this.method = method;
}
public void setKlass(Class<?> klass) {
this.klass = klass;
}
public void setMethod(Method method) {
this.method = method;
}
public Class<?> getKlass() {
return klass;
}
public Method getMethod() {
return method;
}
public abstract boolean before(Object[] args);
public abstract Object after(Object result);
public abstract void dealException(Throwable th);
}
很明显,前置拦截是对参数的操作,返回值boolean类型决定是否继续运行;而后置或滞后拦截是对反射机制执行后结果的操作。
- FyIntercepterAdapter ***适配器
package com.funyoo.aop.core;
import java.lang.reflect.Method;
public class FyInterceptorAdapter extends FyInterceptor {
public FyInterceptorAdapter() {
}
public FyInterceptorAdapter(Class<?> klass, Method method) {
super(klass, method);
}
@Override
public boolean before(Object[] args) {
return true;
}
@Override
public Object after(Object result) {
return result;
}
@Override
public void dealException(Throwable th) {
}
}
给出默认选项,由使用者决定该覆盖哪个拦截方法。
- FyProxy
package com.funyoo.aop.core;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
public class FyProxy {
private Object proxy;
private Object object;
private List<FyInterceptorAdapter> interceptorList;
public FyProxy() {
interceptorList = new ArrayList<>();
}
public Object getProxy() {
return proxy;
}
public Object getObject() {
return object;
}
public void setObject(Object object) {
this.object = object;
}
public List<FyInterceptorAdapter> getInterceptorList() {
return interceptorList;
}
public void setProxy(Object proxy) {
this.proxy = proxy;
}
public void setInterceptorList(List<FyInterceptorAdapter> interceptorList) {
this.interceptorList = interceptorList;
}
// 执行前置拦截的方法
// 通过参数决定是否执行该***的前置拦截
public boolean doBefore(Method method, Object[] args) {
for (FyInterceptorAdapter interceptor : interceptorList) {
if (!interceptor.getMethod().equals(method)) {
continue;
}
if (!interceptor.before(args)) {
return false;
}
}
return true;
}
// 后置拦截
public Object doAfter(Method method, Object result) {
for (FyInterceptorAdapter interceptor : interceptorList) {
if (!interceptor.getMethod().equals(method)) {
continue;
}
return interceptor.after(result);
}
return result;
}
// 异常拦截
public void doDealException(Method method, Throwable th) throws Throwable {
for (FyInterceptorAdapter interceptor : interceptorList) {
if (!interceptor.getMethod().equals(method)) {
continue;
}
interceptor.dealException(th);
throw th;
}
}
// 当该类***存在时无法添加新***
// 这里会抛出一个自定义异常
public void addInterceptor(FyInterceptorAdapter interceptor) throws InterceptorAlreadyExistException {
String interceptorName = interceptor.getClass().getName();
if (interceptorList.contains(interceptor)) {
throw new InterceptorAlreadyExistException("***" + interceptorName +"已存在");
}
interceptorList.add(interceptor);
}
// 删除***
public void removeInterceptor(FyInterceptorAdapter interceptor) {
if (!interceptorList.contains(interceptor)) {
return;
}
interceptorList.remove(interceptor);
}
}
- ProxyFactory 生成代理对象(JDK和CGLIB方式)
package com.funyoo.aop.core;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class ProxyFactory {
private FyProxy fyProxy;
public ProxyFactory() {
}
public FyProxy getFyProxy() {
return fyProxy;
}
// 这里着重说这个方法:
// 用来给上层调用
// 每通过原类和对象,get到一个代理对象的时候,
// 新建一个FyProxy对象,并将其原对象和生成的代理对象set进这个fyProxy
// 达到代理对象和原对象的一一对应关系
// 将原对象set进去
// 为后面完成IOC加上去的。。。
@SuppressWarnings("unchecked")
public <T> T getCglibProxy(Class<?> klass, Object object) {
fyProxy = new FyProxy();
Object proxy = cglibProxy(klass, object);
fyProxy.setProxy(proxy);
fyProxy.setObject(object);
return (T) proxy;
}
@SuppressWarnings("unchecked")
private <T> T cglibProxy(Class<?> klass, Object object) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(klass);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
return doInvoker(object, method, args);
}
});
return (T) enhancer.create();
}
@SuppressWarnings("unchecked")
public <T> T getJdkProxy(Class<?> klass, Object object) {
fyProxy = new FyProxy();
Object proxy = jdkProxy(klass, object);
fyProxy.setProxy(proxy);
fyProxy.setObject(object);
return (T) proxy;
}
@SuppressWarnings("unchecked")
private <T> T jdkProxy(Class<?> klass, Object object) {
ClassLoader classLoader = klass.getClassLoader();
Class<?>[] interfaces = klass.getInterfaces();
return (T) Proxy.newProxyInstance(classLoader, interfaces, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return doInvoker(object, method, args);
}
});
}
// 看!!这个方法是代理对象执行方法时内部的“东西”
// 各种拦截
// 最中间调用方法的object是原对象!
@SuppressWarnings("unchecked")
private <T> T doInvoker(Object object, Method method, Object[] args) throws Throwable {
Object result = null;
fyProxy.doBefore(method, args);
try {
result = method.invoke(object, args);
fyProxy.doAfter(method, result);
} catch (Throwable th) {
fyProxy.doDealException(method, th);
}
return (T) result;
}
}
- ProxyBeanFactory 用来将类名和FyProxy联系起来
package com.funyoo.aop.core;
import java.util.HashMap;
import java.util.Map;
public class proxyBeanFactory {
private static final Map<String, FyProxy> beanMap = new HashMap<>();
public proxyBeanFactory() {
}
@SuppressWarnings("unchecked")
public <T> T creatCglibProxy(Object object) {
Object proxy = cglibProxy(object.getClass(), object);
return (T) proxy;
}
@SuppressWarnings("unchecked")
public <T> T creatCglibProxy(Class<?> klass) throws InstantiationException, IllegalAccessException {
Object proxy = cglibProxy(klass, klass.newInstance());
return (T) proxy;
}
@SuppressWarnings("unchecked")
public <T> T creatJdkProxy(Class<?> klass) throws InstantiationException, IllegalAccessException {
Object proxy = jdkProxy(klass, klass.newInstance());
return (T) proxy;
}
@SuppressWarnings("unchecked")
public <T> T creatJdkProxy(Object object) {
Object proxy = jdkProxy(object.getClass(), object);
return (T) proxy;
}
// 这个类的核心在这里!!
// 对外
// 通过类或者对象获得代理对象(look上面!)
// 并将其加到Map集合里
// 所以现在的Map集合中放入的是每个类和与之对应的Fyproxy(代理对象,原对象,***链)
// 有了这个Map,外面就可以通过Map得到一系列的操作了
当然下面CGLIB和这个一样啦,毕竟提供了两种代理方式啦
@SuppressWarnings("unchecked")
private <T> T jdkProxy(Class<?> klass, Object object) {
String className = klass.getName();
FyProxy fyProxy = beanMap.get(className);
if (fyProxy != null) {
return (T) fyProxy.getProxy();
}
ProxyFactory proxyFactory = new ProxyFactory();
T proxy = proxyFactory.getJdkProxy(klass, object);
beanMap.put(className, proxyFactory.getFyProxy());
return proxy;
}
@SuppressWarnings("unchecked")
private <T> T cglibProxy(Class<?> klass, Object object) {
String className = klass.getName();
FyProxy fyProxy = beanMap.get(className);
if (fyProxy != null) {
return (T) fyProxy.getProxy();
}
ProxyFactory proxyFactory = new ProxyFactory();
T proxy = proxyFactory.getCglibProxy(klass, object);
beanMap.put(className, proxyFactory.getFyProxy());
return proxy;
}
// 这里是面向使用者
// 对某类添加***
public void addInterceptor(Class<?> klass, FyInterceptorAdapter interceptor) throws InterceptorAlreadyExistException {
if (!interceptor.getKlass().equals(klass)) {
return;
}
beanMap.get(klass.getName()).addInterceptor(interceptor);
}
public void removeInterceptor(Class<?> klass, FyInterceptorAdapter interceptor) {
if (!interceptor.getKlass().equals(klass)) {
return;
}
beanMap.get(klass.getName()).removeInterceptor(interceptor);
}
}
这个类就是最高层啦。什么?看图上上面还有beanFactory一层。那一层主要内容是包扫描,根据注解依赖注入,动态生成所有代理对象,这就到IOC了。
- Test
public class Test {
public static void main(String[] args) throws NoSuchMethodException, SecurityException, InterceptorAlreadyExistException {
// 根据某类某方法生成一个***
// 这里的***interceptor是继承FyInterceptorAdapter重写的
Class<?> klass = NormalClass.class;
method = klass.getDeclaredMethod("setName", new Class<?>[] {String.class});
NormalClassInterceptor interceptor = new NormalClassInterceptor(klass, method);
// 创建代理对象
// 添加***
// 用代理对象执行方法(代理对象内部调用方法还是利用原对象经反射机制实现,但代理对象执方
// 法的同时会执行***)
// ***工作!
proxyBeanFactory beanFactory = new proxyBeanFactory();
try {
NormalClass object = beanFactory.creatCglibProxy(NormalClass.class);
beanFactory.addInterceptor(klass, interceptor);
object.setName("");
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
总结
发现没,好麻烦的说,我要获得一个代理对象,并给他添加***要这么多步,那可不可以自动扫描我想拦截的方法并自动生成代理对象,最好,自动把***链也加好了。当然可以,这就要说到IOC了,这个嘛,慢慢实现,还会用到前一篇的包扫描工具,通过注解来进行依赖注入。
以上就是AOP,就是那什么面相切面思想,其实本质上还是代理模式和反射机制,在不伤及这个类的同时对这个类进行拦截或添加日志的操作,松耦合!
我这里实现的比较粗糙和简单啦,但AOP思想就是这么回事。啊~~~反射机制太伟大了。