spring原始碼閱讀(2)-aop之原始碼解析篇
經過一個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都是執行時建立代理的方式