【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思想就是这么回事。啊~~~反射机制太伟大了。

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值