经过一个aop术语介绍和动态代理的深入讲解,我们终于可以来看aop的源码了,下面跟着博主一点点剖析spring aop源码的实现吧
我们知道spring使用中我们只要做好相关的配置,spring自动帮我们做好了代理的相关工作。
我们从三个方面入手吧
1、配置
2、创建代理
3、获取代理类
配置
我们从AopNamespaceHandler入手,这个是自定义配置的实现类
public void init() {
this.registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
this.registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
}
对aop的aspectj的配置很熟悉了吧
我们来看看AspectJAutoProxyBeanDefinitionParser的parse方法吧,这个是ioc加载自定义配置调用的方法
public BeanDefinition parse(Element element, ParserContext parserContext) {
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
}
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {
//注册AspectJAnnotationAutoProxyCreator
BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
//处理proxy-target-class和expose-proxy
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
//注册组件
registerComponentIfNecessary(beanDefinition, parserContext);
}
//注册的是AnnotationAwareAspectJAutoProxyCreator
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
这里我们注意,springaop自动帮我们注册了AnnotationAwareAspectJAutoProxyCreator
另外target-proxy-class:spring提供了两种代理的,jdk和cglib(建议使用jdk),这个属性就是配置使用哪个代理模式的true-cglib,false-jdk
expose-proxy:解决那日不自我调用无法增强
创建代理
我们看看AnnotationAwareAspectJAutoProxyCreator的UML类关系图
可以看出AbstractAutoProxyCreator实现了BeanPostProcessor方法,看到这个我想我们应该知道去关注什么方法吧,对postProcessAfterInitialization是创建bean的时候会执行的方法
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.containsKey(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
什么缓存之类的我们先不看了,因为这个时候还没有
if (beanName != null && this.targetSourcedBeans.containsKey(beanName)) {
return bean;
}
// 获取bean的切面
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
//创建代理对象
Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
}
return bean;
}
我们先来看看增强的获取:
1、
protected Object[] getAdvicesAndAdvisorsForBean(Class beanClass, String beanName, TargetSource targetSource) {
List advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
2、
protected List<Advisor> findEligibleAdvisors(Class beanClass, String beanName) {
//寻找所有的增强
List<Advisor> candidateAdvisors = findCandidateAdvisors();
//匹配适应的增强,无法找到返回null
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
//排序增强
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
在过来看看代理的创建
protected Object createProxy(
Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
ProxyFactory proxyFactory = new ProxyFactory();
//添加代理接口
if (!shouldProxyTargetClass(beanClass, beanName)) {
// Must allow for introductions; can't just set interfaces to
// the target's interfaces only.
Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, this.proxyClassLoader);
for (Class<?> targetInterface : targetInterfaces) {
proxyFactory.addInterface(targetInterface);
}
}
//添加增强
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
for (Advisor advisor : advisors) {
proxyFactory.addAdvisor(advisor);
}
proxyFactory.setTargetSource(targetSource);
return proxyFactory.getProxy(this.proxyClassLoader);
}
直接看getProxy()
public Object getProxy(ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
我先看看createAopFactory创建了什么代理类
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
//判断配置,optimize配置为true或者proxy-target-class=true
//且目标类是一个接口使用jdk
//或者使用cglib
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class targetClass = config.getTargetClass();
if (targetClass.isInterface()) {
return new JdkDynamicAopProxy(config);
}
return CglibProxyFactory.createCglibProxy(config);
}
//optimize配置为false并且proxy-target-class=false直接使用jdk代理
else {
return new JdkDynamicAopProxy(config);
}
}
看到了吧,这里就决定了代理的创建方式,optimize为false且proxy-target-class=false,且不存在使用代理接口直接使用jdk,否则再判断如果目标类是一个接口,则使用jdk,否则使用cglib。
先剖析Jdk的getProxy
我们来看下JdkDynamicAopProxy的类关系图
从上图可知,JdkDynamicAopProxy实现了InvocationHandler,也就是代理的逻辑操作在这里面实现
再看看getProxy这个函数
public Object getProxy(ClassLoader classLoader) {
Class[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
这里的return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);就是创建代理类了
我们看看jdk的关键InvocationHandler的实现吧
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// Service invocations on ProxyConfig with the proxy config...
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
//此属性
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// May be null. Get as late as possible to minimize the time we "own" the target,
// in case it comes from a pool.
target = targetSource.getTarget();
if (target != null) {
targetClass = target.getClass();
}
// 获取当前方法的增强的拦截链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// Check whether we have any advice. If we don't, we can fallback on direct
// reflective invocation of the target, and avoid creating a MethodInvocation.
if (chain.isEmpty()) {
//没有拦截链直接调用方法
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);
}
else {
// 封装拦截链
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// 执行拦截链
retVal = invocation.proceed();
}
// Massage return value if necessary.
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// Special case: it returned "this" and the return type of the method
// is type-compatible. Note that we can't help if the target sets
// a reference to itself in another returned object.
retVal = proxy;
} else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException("Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
}
}
这里比较重要的就是拦截链了,我们接下来剖析一下拦截链的执行
public Object proceed() throws Throwable {
// 执行完所有拦截器链后,执行切点方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
//获取下一个拦截器,通过索引递增
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
//匹配失败,不执行啥
return proceed();
}
}
else {
//普通拦截器直接调用拦截器,处理引介增强
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
这里就是通过一个索引遍历列表的,注意一下这个InterceptorAndDynamicMethodMatcher类
class InterceptorAndDynamicMethodMatcher {
final MethodInterceptor interceptor;
final MethodMatcher methodMatcher;
public InterceptorAndDynamicMethodMatcher(MethodInterceptor interceptor, MethodMatcher methodMatcher) {
this.interceptor = interceptor;
this.methodMatcher = methodMatcher;
}
}
其实就是一个方法匹配拦截器,这里我们在回到上面的创建拦截器链的方法,看看怎么创建拦截器的
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, Class targetClass) {
List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
//获取所有的增强器
for (Advisor advisor : config.getAdvisors()) {
//判断增强是否有切点
if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (config.isPreFiltered() ||
//类过滤器匹配
pointcutAdvisor.getPointcut().getClassFilter().matches(targetClass)) {
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
//方法匹配器匹配
if (MethodMatchers.matches(mm, method, targetClass, hasIntroductions)) {
if (mm.isRuntime()) {
// Creating a new object instance in the getInterceptors() method
// isn't a problem as we normally cache created chains.
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
//引介增强
else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(targetClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
//普通方法
else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
其实这个拦截器链的处理和process()加起来就决定了哪些增强方法会被处理。
Cglib
public Object getProxy(ClassLoader classLoader) {
Class<?> rootClass = this.advised.getTargetClass();
Class<?> proxySuperClass = rootClass;
if (ClassUtils.isCglibProxyClass(rootClass)) {
proxySuperClass = rootClass.getSuperclass();
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for (Class<?> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}
Enhancer enhancer = createEnhancer();
enhancer.setSuperclass(proxySuperClass);
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new MemorySafeUndeclaredThrowableStrategy(UndeclaredThrowableException.class));
enhancer.setInterceptDuringConstruction(false);
//获取回调
Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
//设置回调
enhancer.setCallbacks(callbacks);
//创建代理类
proxy = enhancer.create();
return proxy;
}
上面代码一目了然了,基本上就是一个cglib动态代理的配置创建代码,我们需要想jdk部分那样找到代理的处理部分,在cglib中是callback
getCallBack
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
retVal = methodProxy.invoke(target, args);
}
else {
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
基本和jdk的流程差不多,首先创建一个拦截器链,然后遍历。
至此aop的源码我们分析完毕,我们来做个总结吧:
1、springaop默认使用的是jdk的代理方式,如果想使用cglib,可配置<aop:aspectj-autoproxy proxy-target-class=true/>
2、这里有必要提一提jdk的运行性能没有cglib高,比cglib差8倍,但创建代理的性能比cglib高10倍,对于无需频繁创建代理比较适合使用cglib模式,反之jdk模式比较适合
3、jdk和cglib都是运行时创建代理的方式