Spring容器10AOP JDK+CGLIB

源码参考:github上的code4craft/tiny-spring项目。

tiny-spring-step-10-invite-cglib-and-aopproxy-factory

源码解析

警告:请参考github上的源码,不然理解起来比较困难。

  1. 切点(Pointcut)和通知(Advice)
  2. 整合到Spring容器中

在这里插入图片描述

目录结构

  1. AbstractAopProxy
    实现AopProxy,依赖了代理的元数据信息。
  2. AdvisedSupport
    代理的元数据信息,记录对哪个对象的哪个方法进行了增强。
  3. Advisor
    通知器的抽象,管理通知
  4. AopProxy
    AOP代理的抽象
  5. AspectJAroundAdvice
    通知的具体实现
  6. AspectJAwareAdvisorAutoProxyCreator
    将代理整合到spring中,使用了BeanPostProcessor, BeanFactoryAware
  7. AspectJExpressionPointcut
    切点的具体实现
  8. AspectJExpressionPointcutAdvisor
    切点通知器的实现,管理切点和通知
  9. BeanFactoryAware
    提供BeanFactory
  10. Cglib2AopProxy
    Cglib的AopProxy实现
  11. ClassFilter
    类过滤器抽象
  12. JdkDynamicAopProxy
    Jdk的AopProxy实现
  13. MethodMatcher
    方法匹配抽象
  14. Pointcut
    切点抽象
  15. PointcutAdvisor
    切点通知器抽象
  16. ProxyFactory
    Proxy创建工厂
  17. ReflectiveMethodInvocation
    方法处理,Joinpoint的具体实现
  18. TargetSource
    目标对象的信息

切点(Pointcut)

Pointcut是对AOP对切点的高级抽象。主要作用是类的过滤以及方法的匹配

public interface Pointcut {

    ClassFilter getClassFilter();

    MethodMatcher getMethodMatcher();

}
public interface MethodMatcher {

    boolean matches(Method method, Class targetClass);
}
public interface ClassFilter {

    boolean matches(Class targetClass);
}

实现类:AspectJExpressionPointcut

public class AspectJExpressionPointcut implements Pointcut, ClassFilter, MethodMatcher {

	private PointcutParser pointcutParser;

	private String expression;

	private PointcutExpression pointcutExpression;

	private static final Set<PointcutPrimitive> DEFAULT_SUPPORTED_PRIMITIVES = new HashSet<PointcutPrimitive>();

	static {
		DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.EXECUTION);
		DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.ARGS);
		DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.REFERENCE);
		DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.THIS);
		DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.TARGET);
		DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.WITHIN);
		DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_ANNOTATION);
		DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_WITHIN);
		DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_ARGS);
		DEFAULT_SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_TARGET);
	}

	public AspectJExpressionPointcut() {
		this(DEFAULT_SUPPORTED_PRIMITIVES);
	}

	public AspectJExpressionPointcut(Set<PointcutPrimitive> supportedPrimitives) {
		pointcutParser = PointcutParser
				.getPointcutParserSupportingSpecifiedPrimitivesAndUsingContextClassloaderForResolution(supportedPrimitives);
	}

	protected void checkReadyToMatch() {
		if (pointcutExpression == null) {
			pointcutExpression = buildPointcutExpression();
		}
	}

	private PointcutExpression buildPointcutExpression() {
		return pointcutParser.parsePointcutExpression(expression);
	}

	public void setExpression(String expression) {
		this.expression = expression;
	}

	@Override
	public ClassFilter getClassFilter() {
		return this;
	}

	@Override
	public MethodMatcher getMethodMatcher() {
		return this;
	}

	@Override
	public boolean matches(Class targetClass) {
		checkReadyToMatch();
		return pointcutExpression.couldMatchJoinPointsInType(targetClass);
	}

	@Override
	public boolean matches(Method method, Class targetClass) {
		checkReadyToMatch();
		ShadowMatch shadowMatch = pointcutExpression.matchesMethodExecution(method);
		if (shadowMatch.alwaysMatches()) {
			return true;
		} else if (shadowMatch.neverMatches()) {
			return false;
		}
		// TODO:其他情况不判断了!见org.springframework.aop.aspectj.RuntimeTestWalker
		return false;
	}
}

管理切点的工具:PointcutAdvisor

public interface PointcutAdvisor extends Advisor{
	//切点通知器管理了切点和通知
   Pointcut getPointcut();
}

通知(Advice)

Advice是对AOP的高层级抽象,主要作用的增强逻辑的实现。advice的实现是MethodInterceptor
通知器:管理通知的工具

public interface Advisor {

    Advice getAdvice();
}

相关方法的调用关系

在这里插入图片描述

AOP代理

是对代理的高级抽象

public interface AopProxy {

    Object getProxy();
}

抽象实现类

public abstract class AbstractAopProxy implements AopProxy {

    protected AdvisedSupport advised;

    public AbstractAopProxy(AdvisedSupport advised) {
        this.advised = advised;
    }
}

JDK具体的实现

public class JdkDynamicAopProxy extends AbstractAopProxy implements InvocationHandler {

    public JdkDynamicAopProxy(AdvisedSupport advised) {
        super(advised);
    }

	@Override
	public Object getProxy() {
		return Proxy.newProxyInstance(getClass().getClassLoader(), advised.getTargetSource().getInterfaces(), this);
	}

	@Override
	public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
		MethodInterceptor methodInterceptor = advised.getMethodInterceptor();
		MethodMatcher methodMatcher = advised.getMethodMatcher();
		if (methodMatcher!= null && methodMatcher.matches(method, advised.getTargetSource().getTarget().getClass())) {
			return methodInterceptor.invoke(new ReflectiveMethodInvocation(advised.getTargetSource().getTarget(),method, args));
		} else {
			return method.invoke(advised.getTargetSource().getTarget(), args);
		}
	}

}

CGLIB具体实现

public class Cglib2AopProxy extends AbstractAopProxy {

	public Cglib2AopProxy(AdvisedSupport advised) {
		super(advised);
	}

	@Override
	public Object getProxy() {
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(advised.getTargetSource().getTargetClass());
		//getInterfaces() 获得这个对象所实现的所有接口
		enhancer.setInterfaces(advised.getTargetSource().getInterfaces());
		enhancer.setCallback(new DynamicAdvisedInterceptor(advised));
		Object enhanced = enhancer.create();
		return enhanced;
	}

	private static class DynamicAdvisedInterceptor implements MethodInterceptor {

		private AdvisedSupport advised;

		private org.aopalliance.intercept.MethodInterceptor delegateMethodInterceptor;

		private DynamicAdvisedInterceptor(AdvisedSupport advised) {
			this.advised = advised;
			this.delegateMethodInterceptor = advised.getMethodInterceptor();
		}

		@Override
		public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
			if (advised.getMethodMatcher() == null|| advised.getMethodMatcher().matches(method, advised.getTargetSource().getTargetClass())) {
				return delegateMethodInterceptor.invoke(new CglibMethodInvocation(advised.getTargetSource().getTarget(), method, args, proxy));
			}
			return new CglibMethodInvocation(advised.getTargetSource().getTarget(), method, args, proxy).proceed();
		}
	}

	private static class CglibMethodInvocation extends ReflectiveMethodInvocation {

		private final MethodProxy methodProxy;

		public CglibMethodInvocation(Object target, Method method, Object[] args, MethodProxy methodProxy) {
			super(target, method, args);
			this.methodProxy = methodProxy;
		}

		@Override
		public Object proceed() throws Throwable {
			return this.methodProxy.invoke(this.target, this.arguments);
		}
	}

}

被代理的对象

public class TargetSource {

	private Class<?> targetClass;

    private Class<?>[] interfaces;

	private Object target;
}

AspectJAroundAdvice是通知的具体实现:增强逻辑的实现
AspectJExpressionPointcut是切点的具体实现:类过滤,方法匹配
AspectJExpressionPointcutAdvisor是切点通知器的具体实现:管理切点和通知

与容器整合AspectJAwareAdvisorAutoProxyCreator,在bean初始化的前后实现创建代理对象。

public class AspectJAwareAdvisorAutoProxyCreator implements BeanPostProcessor, BeanFactoryAware {

	private AbstractBeanFactory beanFactory;

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws Exception {
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws Exception {
		if (bean instanceof AspectJExpressionPointcutAdvisor) {
			return bean;
		}
		if (bean instanceof MethodInterceptor) {
			return bean;
		}
		List<AspectJExpressionPointcutAdvisor> advisors = beanFactory
				.getBeansForType(AspectJExpressionPointcutAdvisor.class);
		for (AspectJExpressionPointcutAdvisor advisor : advisors) {
			if (advisor.getPointcut().getClassFilter().matches(bean.getClass())) {
                ProxyFactory advisedSupport = new ProxyFactory();
				advisedSupport.setMethodInterceptor((MethodInterceptor) advisor.getAdvice());
				advisedSupport.setMethodMatcher(advisor.getPointcut().getMethodMatcher());

				TargetSource targetSource = new TargetSource(bean, bean.getClass(), bean.getClass().getInterfaces());
				advisedSupport.setTargetSource(targetSource);

				return advisedSupport.getProxy();
			}
		}
		return bean;
	}

	@Override
	public void setBeanFactory(BeanFactory beanFactory) throws Exception {
		this.beanFactory = (AbstractBeanFactory) beanFactory;
	}
}

调用顺序

在这里插入图片描述

测试

这个测试非常具有代表性

public class JdkDynamicAopProxyTest {

	@Test
	public void testInterceptor() throws Exception {
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("tinyioc.xml");
		HelloWorldService helloWorldService = (HelloWorldService) applicationContext.getBean("helloWorldService");
		helloWorldService.helloWorld();
		//在AspectJAwareAdvisorAutoProxyCreator中已经对bean做了CGlib代理,所以获取的是代理对象,
		//因为CGlib针对的是类,所以代理对象类型是HelloWorldServiceImpl
		System.out.println("class =" + helloWorldService.getClass().getName());//us.codecraft.tinyioc.HelloWorldServiceImpl$$EnhancerByCGLIB$$635bc03b
		System.out.println(helloWorldService instanceof Cglib2AopProxy);//false
		System.out.println(helloWorldService instanceof JdkDynamicAopProxy);//false
		System.out.println(helloWorldService instanceof HelloWorldService);//true
		System.out.println(helloWorldService instanceof HelloWorldServiceImpl);//true

		AdvisedSupport advisedSupport = new AdvisedSupport();
		TargetSource targetSource = new TargetSource(helloWorldService, HelloWorldServiceImpl.class,HelloWorldService.class);
		advisedSupport.setTargetSource(targetSource);

		TimerInterceptor timerInterceptor = new TimerInterceptor();
		advisedSupport.setMethodInterceptor(timerInterceptor);

		JdkDynamicAopProxy jdkDynamicAopProxy = new JdkDynamicAopProxy(advisedSupport);
		HelloWorldService helloWorldServiceProxy = (HelloWorldService) jdkDynamicAopProxy.getProxy();

		helloWorldServiceProxy.helloWorld();
		//上面已经使用了代理,而下面又创建了代理对象,而且是JDK实现的,
		//因为重新new JdkDynamicAopProxy(),所以获取的是新的代理对象。又因为JDK是针对接口做代理的,所以判断代理的类型是HelloWorldService
		System.out.println("class = = " + helloWorldServiceProxy.getClass().getName());//com.sun.proxy.$Proxy2
		System.out.println(helloWorldServiceProxy instanceof Cglib2AopProxy);//false
		System.out.println(helloWorldServiceProxy instanceof JdkDynamicAopProxy);//false
		System.out.println(helloWorldServiceProxy instanceof HelloWorldService);//true
		System.out.println(helloWorldServiceProxy instanceof HelloWorldServiceImpl);//false		

	}
}

tinyioc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
	http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
	http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">

    <bean id="outputService" class="us.codecraft.tinyioc.OutputServiceImpl">
    </bean>

    <bean id="helloWorldService" class="us.codecraft.tinyioc.HelloWorldServiceImpl">
        <property name="text" value="Hello World!"></property>
        <property name="outputService" ref="outputService"></property>
    </bean>

    <bean id="autoProxyCreator" class="us.codecraft.tinyioc.aop.AspectJAwareAdvisorAutoProxyCreator"></bean>

    <bean id="timeInterceptor" class="us.codecraft.tinyioc.aop.TimerInterceptor"></bean>

    <bean id="aspectjAspect" class="us.codecraft.tinyioc.aop.AspectJExpressionPointcutAdvisor">
        <property name="advice" ref="timeInterceptor"></property>
        <property name="expression" value="execution(* us.codecraft.tinyioc.*.*(..))"></property>
    </bean>

</beans>
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值