Spring之模拟实现AOP的功能(模拟Before,After,Around,AfterThrowing,AfterReturn)

1.声明

当前的内容用于模拟当前Spring的AOP功能,主要用于本人理解或者学习之用!

基本的代理实现主要通过这两个是实现:Proxy和InvocationHandler

2.定义基本的接口和实例

fly接口


public interface Fly {
	void fly();
}

鸭子

public class Duck implements Fly {

	@Override
	public void fly() {
		System.out.println("鸭子嘎嘎的飞!");
	}

}

3.定义抽象的执行类AbstractInvocationHandler

public abstract class AbstractInvocationHandler implements InvocationHandler {
	private Object target;

	public AbstractInvocationHandler(Object target) {
		this.target = target;
	}

	public Object getTarget() {
		return target;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		if (Proxy.class.isAssignableFrom(target.getClass())) {
			// System.out.println("这个类就是代理类,代理类不能执行,出现死循环的情况");// 这里需要获取实际对象,所以当前的
			// 需要将target转换为实际的对象
			//Object realObj = getRealObj(target);
			//method.invoke(realObj, args);
		}
		Object result = method.invoke(target, args);// 看到这个发现了一个问题,这里的invoke的对象必须是传入进来的对象
		return result;
	}

	// 用于获取当前类的实际类型而不是代理类型
	public Object getRealObj(Object target) {
		while (true) {
			if (Proxy.class.isAssignableFrom(target.getClass())) {
				InvocationHandler invocationHandler = Proxy.getInvocationHandler(target);
				if (invocationHandler instanceof AbstractInvocationHandler) {
					AbstractInvocationHandler h = (AbstractInvocationHandler) invocationHandler;
					target = h.getTarget();
				}
			} else {
				return target;
			}
		}
	}

}

至于这里获取代理对象的实际对象,通过迭代方式是实现,本人思想:实际执行对象外面为代理对象,代理对象外面为外面的代理对象…(所以执行的时候,个人认为需要解除代理)

4.定义JdkInvocationHandler


public class JdkInvocationHandler extends AbstractInvocationHandler {

	public JdkInvocationHandler(Object target) {
		super(target);
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		if (Proxy.class.isAssignableFrom(getTarget().getClass())) {
			// System.out.println("这个类就是代理类,代理类不能执行,出现死循环的情况");// 这里需要获取实际对象,所以当前的
			// 需要将target转换为实际的对象
			Object realObj = getRealObj(getTarget());
			method.invoke(realObj, args);
		}
		Object result = method.invoke(getTarget(), args);// 看到这个发现了一个问题,这里的invoke的对象必须是传入进来的对象
		return result;
	}
}

5.测试JdkInvocationHandler

@Test
	public void testJdkProxy() {
		Duck duck = new Duck();
		Fly instance = (Fly) JdkProxyFactory.instance(duck, new JdkInvocationHandler(duck));
		instance.fly();
	}

结果:鸭子嘎嘎的飞!

@Test
	public void testJdkProxy2() {
		Duck duck = new Duck();
		Fly instance = (Fly) JdkProxyFactory.instance(duck, new JdkInvocationHandler(duck));
		Fly instance2 = (Fly) JdkProxyFactory.instance(instance, new JdkInvocationHandler(instance)); // 由于执行的instance不能是原来的代理对象,所以我们要解析这个代理,获取实际的对象

		Fly instance3 = (Fly) JdkProxyFactory.instance(instance2, new JdkInvocationHandler(instance2));

		instance3.fly();
	}

结果:
鸭子嘎嘎的飞!
鸭子嘎嘎的飞!
鸭子嘎嘎的飞!

该方法的缺点,每次执行都找到实际对象进行执行,嵌套的越多就需要查询的越多,比较繁琐,不能实现类似aop的功能

6.创建和实现AOP的功能

由于上面的方法并不能实现该方法,考虑为每个aop类都实现invocationHandler接口,通过注入AOP实例的方式实现

AOP和其实现类


public interface Aop {
	void invoke();
}

==AfterAop ==

public class AfterAop implements Aop {
	private String str;

	public AfterAop(String str) {
		this.str = str;
	}

	@Override
	public void invoke() {
		System.out.println(str);
	}
}

public class AfterThrowingAop implements Aop{

	@Override
	public void invoke() {
		System.out.println("异常通知。。。");
	}
	
}

其他的都跟 AfterAop差不多,所以这里不写了

7.实现各种Before,After,Around,AfterThrowing,AfterReturn的InvocationHandler

Before

public class BeforeInvocationHandler extends AbstractInvocationHandler {
	private final Aop aop;

	public BeforeInvocationHandler(Object target, BeforeAop aop) {
		super(target);
		this.aop = aop;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		aop.invoke();
		Object result = super.invoke(proxy, method, args);// 看到这个发现了一个问题,这里的invoke的对象必须是传入进来的对象
		return result;
	}

}

After

public class AfterInvocationHandler extends AbstractInvocationHandler {
	private final Aop aop;

	public AfterInvocationHandler(Object target, AfterAop aop) {
		super(target);
		this.aop = aop;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		try {
			Object result = super.invoke(proxy, method, args);
			return result;
		} finally {
			aop.invoke();
		}

	}

}

Around

public class AroundInvocationHandler extends AbstractInvocationHandler {
	private final Aop aop;

	public AroundInvocationHandler(Object target, AroundAop aop) {
		super(target);
		this.aop = aop;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		aop.invoke();
		Object result = super.invoke(proxy, method, args);// 看到这个发现了一个问题,这里的invoke的对象必须是传入进来的对象
		aop.invoke();
		return result;

	}
}

AfterThrowing

public class AfterThrowingInvocationHandler extends AbstractInvocationHandler {
	private final Aop aop;

	public AfterThrowingInvocationHandler(Object target, AfterThrowingAop aop) {
		super(target);
		this.aop = aop;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		try {
			Object result = super.invoke(proxy, method, args);
			throw new IllegalArgumentException("抛出异常。。。");
		} catch (Exception ex) {
			ex.printStackTrace();
			aop.invoke();
			return null;
		}

	}

}

AfterReturn

public class AfterReturnInvovationHandler extends AbstractInvocationHandler {

	private final Aop aop;

	public AfterReturnInvovationHandler(Object target, AfterReturnAop aop) {
		super(target);
		this.aop = aop;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object result = super.invoke(proxy, method, args);
		aop.invoke();
		return result;// 如果执行中出现了异常就会报错
	}

}

8.测试7中的内容

@Test
	public void testAroundAndBefore() {
		Duck duck = new Duck();
		Fly fly = (Fly) JdkProxyFactory.instance(duck, new AroundInvocationHandler(duck, new AroundAop("环绕通知。。。")));
		fly = (Fly) JdkProxyFactory.instance(fly, new AfterInvocationHandler(fly, new AfterAop("后置增强")));
		fly = (Fly) JdkProxyFactory.instance(fly, new AfterThrowingInvocationHandler(fly, new AfterThrowingAop()));
		fly.fly();
	}

结果
在这里插入图片描述
在这里插入图片描述

通过这种嵌套的方式为某个方法或者日志实现切面基本上算是实现了!,但是存在问题,如何为当前类的特定的方法实现不同的代理,这个还在思考(应该需要进行方法判断,或者其他的)

9.总结

1.当前内容中实现了基本的动态代理方式,如果按照循环方式应该就可以实现一部分的功能

2.越通过自己的实现越发现springaop编程的强大

以上纯属个人见解,如有问题请联系本人!

发布了242 篇原创文章 · 获赞 44 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/weixin_45492007/article/details/105472037
今日推荐