在網(wǎng)站里文本鏈接怎么做關(guān)鍵詞com
書接上文,上文說到,specificInterceptors 不為空則執(zhí)行createProxy方法創(chuàng)建代理對(duì)象,即下圖的createProxy方法開始執(zhí)行,生成代理對(duì)象,生成代理對(duì)象有兩種方式,JDK和CGLIB。
createAopProxy就是決定使用哪種方式生成動(dòng)態(tài)代理對(duì)象,方法執(zhí)行流程和代碼如下:
/*** 真正的創(chuàng)建代理,判斷一些列條件,有自定義的接口的就會(huì)創(chuàng)建jdk代理,否則就是cglib* @param config the AOP configuration in the form of an* AdvisedSupport object* @return* @throws AopConfigException*/@Overridepublic AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {// 這段代碼用來判斷選擇哪種創(chuàng)建代理對(duì)象的方式// config.isOptimize() 是否對(duì)代理類的生成使用策略優(yōu)化 其作用是和isProxyTargetClass是一樣的 默認(rèn)為false// config.isProxyTargetClass() 是否使用Cglib的方式創(chuàng)建代理對(duì)象 默認(rèn)為false// hasNoUserSuppliedProxyInterfaces目標(biāo)類是否有接口存在 且只有一個(gè)接口的時(shí)候接口類型不是SpringProxy類型if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {// 上面的三個(gè)方法有一個(gè)為true的話,則進(jìn)入到這里// 從AdvisedSupport中獲取目標(biāo)類 類對(duì)象Class<?> targetClass = config.getTargetClass();if (targetClass == null) {throw new AopConfigException("TargetSource cannot determine target class: " +"Either an interface or a target is required for proxy creation.");}// 判斷目標(biāo)類是否是接口 如果目標(biāo)類是接口的話,則還是使用JDK的方式生成代理對(duì)象// 如果目標(biāo)類是Proxy類型 則還是使用JDK的方式生成代理對(duì)象if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {return new JdkDynamicAopProxy(config);}// 配置了使用Cglib進(jìn)行動(dòng)態(tài)代理或者目標(biāo)類沒有接口,那么使用Cglib的方式創(chuàng)建代理對(duì)象return new ObjenesisCglibAopProxy(config);}else {// 使用JDK的提供的代理方式生成代理對(duì)象return new JdkDynamicAopProxy(config);}}
此處使用ObjenesisCglibAopProxy方式
getProxy:168, CglibAopProxy (org.springframework.aop.framework)
創(chuàng)建代理對(duì)象方法及注釋如下:
/*** 獲取cglib的代理對(duì)象* @param classLoader the class loader to create the proxy with* (or {@code null} for the low-level proxy facility's default)* @return*/@Overridepublic Object getProxy(@Nullable ClassLoader classLoader) {if (logger.isTraceEnabled()) {logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());}try {// 從advised中獲取ioc容器中配置的target對(duì)象Class<?> rootClass = this.advised.getTargetClass();Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");Class<?> proxySuperClass = rootClass;//如果目標(biāo)對(duì)象已經(jīng)是CGLIB 生成代理對(duì)象(就是比較類名稱中有 $$ 字符串),那么就取目標(biāo)對(duì)象的父類作為目標(biāo)對(duì)象的類if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {proxySuperClass = rootClass.getSuperclass();// 獲取原始父類的接口Class<?>[] additionalInterfaces = rootClass.getInterfaces();for (Class<?> additionalInterface : additionalInterfaces) {this.advised.addInterface(additionalInterface);}}// Validate the class, writing log messages as necessary.// 打印出不能代理的方法名,CGLIB 是使用繼承實(shí)現(xiàn)的,所以final , static 的方法不能被增強(qiáng)validateClassIfNecessary(proxySuperClass, classLoader);// Configure CGLIB Enhancer...// 創(chuàng)建及配置EnhancerEnhancer enhancer = createEnhancer();if (classLoader != null) {enhancer.setClassLoader(classLoader);if (classLoader instanceof SmartClassLoader &&((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {enhancer.setUseCache(false);}}// 配置超類,代理類實(shí)現(xiàn)的接口,回調(diào)方法等enhancer.setSuperclass(proxySuperClass);enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));// 獲取callbacksCallback[] callbacks = getCallbacks(rootClass);Class<?>[] types = new Class<?>[callbacks.length];for (int x = 0; x < types.length; x++) {types[x] = callbacks[x].getClass();}// fixedInterceptorMap only populated at this point, after getCallbacks call aboveenhancer.setCallbackFilter(new ProxyCallbackFilter(this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));enhancer.setCallbackTypes(types);// Generate the proxy class and create a proxy instance.// 通過 Enhancer 生成代理對(duì)象,并設(shè)置回調(diào)return createProxyClassAndInstance(enhancer, callbacks);}catch (CodeGenerationException | IllegalArgumentException ex) {throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +": Common causes of this problem include using a final class or a non-visible class",ex);}catch (Throwable ex) {// TargetSource.getTarget() failedthrow new AopConfigException("Unexpected AOP exception", ex);}}
rootClass是需要被代理的對(duì)象,Enhancer該類用于生成代理對(duì)象,代理如何生成:CGLIB和JDK兩種生成方式。
getProxy:168, CglibAopProxy (org.springframework.aop.framework)
getProxy:116, ProxyFactory (org.springframework.aop.framework)
createProxy:519, AbstractAutoProxyCreator (org.springframework.aop.framework.autoproxy)
wrapIfNecessary:383, AbstractAutoProxyCreator (org.springframework.aop.framework.autoproxy)
postProcessAfterInitialization:319, AbstractAutoProxyCreator (org.springframework.aop.framework.autoproxy)
applyBeanPostProcessorsAfterInitialization:529, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
initializeBean:2273, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
doCreateBean:736, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBean:630, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
lambda$doGetBean$0:417, AbstractBeanFactory (org.springframework.beans.factory.support)
getObject:-1, 71399214 (org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$12)
getSingleton:370, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
doGetBean:414, AbstractBeanFactory (org.springframework.beans.factory.support)
getBean:260, AbstractBeanFactory (org.springframework.beans.factory.support)
preInstantiateSingletons:993, DefaultListableBeanFactory (org.springframework.beans.factory.support)
finishBeanFactoryInitialization:1024, AbstractApplicationContext (org.springframework.context.support)
refresh:614, AbstractApplicationContext (org.springframework.context.support)
<init>:150, ClassPathXmlApplicationContext (org.springframework.context.support)
<init>:87, ClassPathXmlApplicationContext (org.springframework.context.support)
main:15, TestAop (com.mashibing.aop.xml)
一級(jí)緩存里是MyCalculator的代理對(duì)象 后續(xù)執(zhí)行就是這個(gè)代理對(duì)象的方法,然后跳轉(zhuǎn)到
intercept:709, CglibAopProxy$DynamicAdvisedInterceptor (org.springframework.aop.framework)
這個(gè)方法
@Override@Nullablepublic Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {Object oldProxy = null;boolean setProxyContext = false;Object target = null;TargetSource targetSource = this.advised.getTargetSource();try {if (this.advised.exposeProxy) {// Make invocation available if necessary.oldProxy = AopContext.setCurrentProxy(proxy);setProxyContext = true;}// Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...target = targetSource.getTarget();Class<?> targetClass = (target != null ? target.getClass() : null);// 從advised中獲取配置好的AOP通知List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);Object retVal;// Check whether we only have one InvokerInterceptor: that is,// no real advice, but just reflective invocation of the target.// 如果沒有aop通知配置,那么直接調(diào)用target對(duì)象的調(diào)用方法if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {// We can skip creating a MethodInvocation: just invoke the target directly.// Note that the final invoker must be an InvokerInterceptor, so we know// it does nothing but a reflective operation on the target, and no hot// swapping or fancy proxying.Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);// 如果攔截器鏈為空則直接激活原方法retVal = methodProxy.invoke(target, argsToUse);}else {// We need to create a method invocation...// 通過cglibMethodInvocation來啟動(dòng)advice通知retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();}retVal = processReturnType(proxy, target, method, retVal);return retVal;}finally {if (target != null && !targetSource.isStatic()) {targetSource.releaseTarget(target);}if (setProxyContext) {// Restore old proxy.AopContext.setCurrentProxy(oldProxy);}}}@Overridepublic boolean equals(@Nullable Object other) {return (this == other ||(other instanceof DynamicAdvisedInterceptor &&this.advised.equals(((DynamicAdvisedInterceptor) other).advised)));}
chain = {ArrayList@2276} size = 6
0 = {ExposeInvocationInterceptor@2242}
1 = {AspectJAfterThrowingAdvice@2282} “org.springframework.aop.aspectj.AspectJAfterThrowingAdvice: advice method [public static void com.mashibing.aop.xml.util.LogUtil.logException(org.aspectj.lang.JoinPoint,java.lang.Exception)]; aspect name ‘logUtil’”
2 = {AfterReturningAdviceInterceptor@2283}
3 = {AspectJAfterAdvice@2284} “org.springframework.aop.aspectj.AspectJAfterAdvice: advice method [public static void com.mashibing.aop.xml.util.LogUtil.logFinally(org.aspectj.lang.JoinPoint)]; aspect name ‘logUtil’”
4 = {AspectJAroundAdvice@2285} “org.springframework.aop.aspectj.AspectJAroundAdvice: advice method [public java.lang.Object com.mashibing.aop.xml.util.LogUtil.around(org.aspectj.lang.ProceedingJoinPoint) throws java.lang.Throwable]; aspect name ‘logUtil’”
5 = {MethodBeforeAdviceInterceptor@2286}
執(zhí)行的就是上面6個(gè)的通知,通過索引下標(biāo)挨個(gè)執(zhí)行
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
執(zhí)行順序如下:
本文主要講解springAop如何創(chuàng)建動(dòng)態(tài)代理對(duì)象以及使用哪種方式創(chuàng)建的依據(jù);在執(zhí)行方法跳轉(zhuǎn)到生成的代理對(duì)象中,然后生成攔截器鏈去執(zhí)行