spring源碼閱讀--aop實(shí)現(xiàn)原理講解
aop實(shí)現(xiàn)原理簡(jiǎn)介
首先我們都知道aop的基本原理就是動(dòng)態(tài)代理思想,在設(shè)計(jì)模式之代理模式中有介紹過這兩種動(dòng)態(tài)代理的使用與基本原理,再次不再敘述。
這里分析的是,在spring中是如何基于動(dòng)態(tài)代理的思想實(shí)現(xiàn)aop的。為了方便了解接下來的源碼分析,這里簡(jiǎn)單化了一個(gè)流程圖分析aop的基本實(shí)現(xiàn)思想。

so,基于上面的流程,一步步分析spring源碼中的aop實(shí)現(xiàn)方式。
采用一個(gè)簡(jiǎn)單的aop例子,利用基于注解配置方式的切面配置,分析一個(gè)簡(jiǎn)單的Before AOP例子。在spring boot下運(yùn)行以下簡(jiǎn)單例子。
AOP的advisor和advice配置。
@Component
@Aspect
public class AopConfig {
@Pointcut("execution(* com.garine.debug.testcase.model.AopObject..*(..))")
public void mypoint(){
//切面定義
}
@Before("mypoint()")
public void doAround() throws Throwable {
System.out.println("before logic");
}
}
AopObject,被代理攔截對(duì)象。
@Component
public class AopObject {
public void aoped(){
System.out.println("logic");
}
}
代理實(shí)現(xiàn)的處理器(BeanPostProcessor)
首先是第一步內(nèi)容,對(duì)我們?cè)贏opConfig中的AOP配置內(nèi)容進(jìn)行解析并且保存到BeanFactory中,這個(gè)過程就是解析保存切面信息。
代理實(shí)現(xiàn)的源頭–AnnotationAwareAspectJAutoProxyCreator
經(jīng)過一遍的代碼跟蹤,我了解到注解方式的AOP配置,都離不開一個(gè)類–AnnotationAwareAspectJAutoProxyCreator,這個(gè)類繼承了BeanPostProcessor接口,我們都知道BeanPostProcessor的實(shí)現(xiàn)類有多個(gè)執(zhí)行處理節(jié)點(diǎn),其中一個(gè)執(zhí)行節(jié)點(diǎn)就是在Bean實(shí)例化之后。也就是在這個(gè)時(shí)機(jī)AnnotationAwareAspectJAutoProxyCreator攔截bean的初始化過程,根據(jù)提前解析得到的切面信息,對(duì)bean的方法進(jìn)行嘗試適配,如果有匹配則需要進(jìn)行代理創(chuàng)建。
這里先分析的就是AnnotationAwareAspectJAutoProxyCreator,在bean實(shí)例化第一次查詢所有切面信息時(shí),就會(huì)解析保存Aop的信息到實(shí)例中,跟蹤以下代碼。
AbstractApplicationContext#refresh (上下文初始化主干方法)
AbstractApplicationContext#registerBeanPostProcessors (執(zhí)行實(shí)例化并保存所有實(shí)現(xiàn)BeanPostProcessor接口的類)
按照上面的邏輯,registerBeanPostProcessors 會(huì)比一般的bean實(shí)例化邏輯要早執(zhí)行,因此我們接下來只需要分析AnnotationAwareAspectJAutoProxyCreator的初始化過程。
AnnotationAwareAspectJAutoProxyCreator的繼承結(jié)構(gòu)

通過上圖可以知道,AnnotationAwareAspectJAutoProxyCreator是繼承了BeanfactoryAware接口,所以在實(shí)例化時(shí),會(huì)執(zhí)行setFactory方法。而所有切面信息解析的執(zhí)行者BeanFactoryAspectJAdvisorsBuilderAdapter初始化的時(shí)機(jī)也是在setFactory方法。
跟蹤代碼如下。
AbstractAdvisorAutoProxyCreator#setBeanFactory
AnnotationAwareAspectJAutoProxyCreator#initBeanFactory
在這個(gè)方法里面會(huì)新建一個(gè)BeanFactoryAspectJAdvisorsBuilderAdapter,這個(gè)對(duì)象會(huì)根據(jù)Beanfactory內(nèi)的aop配置信息,進(jìn)行解析保存。但是需要注意,此時(shí)雖然新建了BeanFactoryAspectJAdvisorsBuilderAdapter對(duì)象.但是此時(shí)還不會(huì)馬上解析aop配置,需要在第一次個(gè)普通bean實(shí)例化時(shí)才執(zhí)行解析aop配置。解析的方法就是
BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors,會(huì)在初次執(zhí)行AnnotationAwareAspectJAutoProxyCreator調(diào)用postProcessBeforeInitialization時(shí)開始執(zhí)行。
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
super.initBeanFactory(beanFactory);
//aspectJAdvisorsBuilder#buildAspectJAdvisors就是解析配置入口
this.aspectJAdvisorsBuilder =
new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
}
代理對(duì)象(Proxy)的創(chuàng)建
解析并緩存切面
上面提到繼承結(jié)構(gòu)圖中,AnnotationAwareAspectJAutoProxyCreator是實(shí)現(xiàn)了InstantiationAwareBeanPostProcessor接口的,InstantiationAwareBeanPostProcessor接口定義的postProcessBeforeInitialization方法是一個(gè)可以對(duì)已經(jīng)注入依賴屬性的bean對(duì)象實(shí)例進(jìn)行編輯操作的接口,會(huì)在
AbstractAutowireCapableBeanFactory#doCreateBean
AbstractAutowireCapableBeanFactory#initializeBean(String, Object, RootBeanDefinition)
AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInstantiation
方法中執(zhí)行InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation,初次初始化緩存切面信息的話就是在這個(gè)方法里面。。
具體的調(diào)用鏈如上所示。這里的postProcessBeforeInstantiation方法實(shí)際上是AnnotationAwareAspectJAutoProxyCreator的實(shí)例進(jìn)行調(diào)用,AnnotationAwareAspectJAutoProxyCreator實(shí)現(xiàn)InstantiationAwareBeanPostProcessor接口。
下面進(jìn)入InstantiationAwareBeanPostProcessor#postProcessBeforeInitialization方法分析代碼。
AbstractAutoProxyCreator#postProcessBeforeInstantiation
AspectJAwareAdvisorAutoProxyCreator#shouldSkip (關(guān)鍵代碼)
進(jìn)入如下代碼AbstractAutoProxyCreator,這個(gè)實(shí)例也就是之前一開始初始化的AnnotationAwareAspectJAutoProxyCreator實(shí)例,進(jìn)入實(shí)例的shouldSkip 方法
@Override
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
// TODO: Consider optimization by caching the list of the aspect names
//預(yù)先解析緩存切面信息
List<Advisor> candidateAdvisors = findCandidateAdvisors();
for (Advisor advisor : candidateAdvisors) {
if (advisor instanceof AspectJPointcutAdvisor) {
if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {
return true;
}
}
}
return super.shouldSkip(beanClass, beanName);
}
AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors
方法findCandidateAdvisors代碼如下,這里是預(yù)先解析緩存所有切面advisor信息,注意這一步操作是在AbstractAutoProxyCreator#postProcessBeforeInitialization處理,也就是開頭提到的切面解析操作,解析完成就進(jìn)行緩存。
@Override
protected List<Advisor> findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
//這里就是前面提到的BeanFactoryAspectJAdvisorsBuilder解析所有切面信息的調(diào)用點(diǎn)
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
return advisors;
}
然后繼續(xù)在這里先提前看一下是如何解析aop配置的。跟蹤BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors
public List<Advisor> buildAspectJAdvisors() {
List<String> aspectNames = null;
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List<Advisor> advisors = new LinkedList<Advisor>();
aspectNames = new LinkedList<String>();
//查詢出Beanfactory中所有已經(jīng)注冊(cè)的BeanName
String[] beanNames =
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);
for (String beanName : beanNames) {
if (!isEligibleBean(beanName)) {
continue;
}
// We must be careful not to instantiate beans eagerly as in this
// case they would be cached by the Spring container but would not
// have been weaved
Class<?> beanType = this.beanFactory.getType(beanName);
if (beanType == null) {
continue;
}
//判斷Bean是否是切面Bean,isAspect方法判斷[標(biāo)注1]
if (this.advisorFactory.isAspect(beanType)) {
aspectNames.add(beanName);
AspectMetadata amd = new AspectMetadata(beanType, beanName);
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
//解析aop class的配置,包返回Advisor對(duì)象[標(biāo)注2]
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
if (this.beanFactory.isSingleton(beanName)) {
this.advisorsCache.put(beanName, classAdvisors);
}
else {
this.aspectFactoryCache.put(beanName, factory);
}
advisors.addAll(classAdvisors);
}
else {
// Per target or per this.
if (this.beanFactory.isSingleton(beanName)) {
throw new IllegalArgumentException("Bean with name '" + beanName +
"' is a singleton, but aspect instantiation model is not singleton");
}
MetadataAwareAspectInstanceFactory factory =
new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
this.aspectFactoryCache.put(beanName, factory);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
}
this.aspectBeanNames = aspectNames;
return advisors;
}
}
if (aspectNames.isEmpty()) {
return Collections.emptyList();
}
List<Advisor> advisors = new LinkedList<Advisor>();
for (String aspectName : aspectNames) {
List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
if (cachedAdvisors != null) {
advisors.addAll(cachedAdvisors);
}
else {
MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
return advisors;
}
**[標(biāo)注1]如何判斷類是否是aop切面配置類? **
通過以下代碼。
@Override
public boolean isAspect(Class<?> clazz) {
return (hasAspectAnnotation(clazz) && !compiledByAjc(clazz));
}
private boolean hasAspectAnnotation(Class<?> clazz) {
//包含@Aspect注解
return (AnnotationUtils.findAnnotation(clazz, Aspect.class) != null);
}
[標(biāo)注2]如何解析為Advisor對(duì)象?
ReflectiveAspectJAdvisorFactory#getAdvisors 遍歷所有沒被@PointCut注解標(biāo)注的方法,也就是遍歷切面內(nèi)容方法
ReflectiveAspectJAdvisorFactory#getAdvisor 處理所有沒被@PointCut注解標(biāo)注的方法,候選切面內(nèi)容方法
代碼如下。
@Override
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName) {
validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
//解析判斷候選方法是否有@Before,@After,@Around等注解,如果有,就繼續(xù)執(zhí)行新建Advisor對(duì)象。
AspectJExpressionPointcut expressionPointcut = getPointcut(
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
if (expressionPointcut == null) {
return null;
}
//創(chuàng)建advisor
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
最終循環(huán)解析,@Before,@After,@Around等標(biāo)注的方法都會(huì)新建一個(gè)Advisor對(duì)象。新建的Advisor對(duì)象都保存在BeanFactoryAspectJAdvisorsBuilder#advisorsCache中,當(dāng)AnnotationAwareAspectJAutoProxyCreator攔截bean的創(chuàng)建過程時(shí),從這里面適配是否有切面可用。
這里解析得到的Advisor,大概有以下信息。下面的信息中,并沒有對(duì)@PointCut注解做處理,pointCut屬性只得出一個(gè)"mypoint()",此時(shí)還不知道Advisor實(shí)際對(duì)應(yīng)的攔截表達(dá)式。

攔截表達(dá)式還是空的,會(huì)在AnnotationAwareAspectJAutoProxyCreator#postProcessAfterInstantiation第一次執(zhí)行時(shí)解析攔截表達(dá)式。

適配切面
在AbstractAutoProxyCreator#postProcessAfterInitialization執(zhí)行時(shí),找到上面AbstractAutoProxyCreator#postProcessBeforeInitialization緩存的所有的切面信息,之后是如何進(jìn)行切面適配,從而決定是否需要進(jìn)行代理對(duì)象的創(chuàng)建呢?
在調(diào)用AbstractAutoProxyCreator#postProcessAfterInitialization方法時(shí),進(jìn)行切面適配,并且會(huì)根據(jù)適配創(chuàng)建代理對(duì)象。根據(jù)以下調(diào)用鏈。
AbstractAutoProxyCreator#postProcessAfterInitialization
AbstractAutoProxyCreator#wrapIfNecessary
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
//查找匹配切面
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//創(chuàng)建代理對(duì)象
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean
AbstractAdvisorAutoProxyCreator#findEligibleAdvisors
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
//從緩存取出所有切面信息
List<Advisor> candidateAdvisors = findCandidateAdvisors();
//根據(jù)advisor信息中的表達(dá)式進(jìn)行方法對(duì)class的匹配
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
此時(shí)如果是第一次執(zhí)行適配方法findAdvisorsThatCanApply的話,candidateAdvisors中的攔截表達(dá)式還是空的,需要進(jìn)行表達(dá)式獲取,也就是@Pointcut的value。spring的操作的在第一次執(zhí)行findAdvisorsThatCanApply時(shí)解析獲取攔截表達(dá)式的值,獲得攔截表達(dá)式值之后就跟當(dāng)前class的方法進(jìn)行匹配看是否需要進(jìn)行代理。
繼續(xù)往下跟蹤代碼
AopUtils#canApply(org.springframework.aop.Advisor, java.lang.Class<?>, boolean)
AopUtils#canApply(org.springframework.aop.Pointcut, java.lang.Class<?>, boolean)
AspectJExpressionPointcut#getClassFilter
AspectJExpressionPointcut#checkReadyToMatch
private void checkReadyToMatch() {
if (getExpression() == null) {
throw new IllegalStateException("Must set property 'expression' before attempting to match");
}
if (this.pointcutExpression == null) {
this.pointcutClassLoader = (this.beanFactory instanceof ConfigurableBeanFactory ?
((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader() :
ClassUtils.getDefaultClassLoader());
//解析得到攔截表達(dá)式,例如根據(jù)@Before的value來關(guān)聯(lián)查詢出對(duì)應(yīng)的表達(dá)式
this.pointcutExpression = buildPointcutExpression(this.pointcutClassLoader);
}
}
最終解析完之后,advisor中的表達(dá)式信息結(jié)構(gòu)如下圖。包含在pointcut屬性中,匹配時(shí)就根據(jù)pointcutExpression循環(huán)進(jìn)行匹配class的方法。有興趣的可以繼續(xù)調(diào)試看看是如何實(shí)現(xiàn)匹配表達(dá)式的。

## 創(chuàng)建代理對(duì)象
如果在上面的匹配切面過程中,發(fā)現(xiàn)適配的切面,那就需要進(jìn)行代理對(duì)象的創(chuàng)建了。
我們回到上面的AbstractAutoProxyCreator#wrapIfNecessary,主要看代碼如下。
// Create proxy if we have advice.
//查找匹配切面
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//創(chuàng)建代理對(duì)象
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
所以,繼續(xù)看
AbstractAutoProxyCreator#createProxy
的創(chuàng)建代理對(duì)象方法。設(shè)置ProxyFactory創(chuàng)建Proxy需要的一切信息。
protected Object createProxy(
Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
//新建代理對(duì)象工廠
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
//設(shè)置工廠代理類
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
//設(shè)置攔截切面
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
for (Advisor advisor : advisors) {
proxyFactory.addAdvisor(advisor);
}
//設(shè)置被代理對(duì)象
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
//創(chuàng)建代理對(duì)象
return proxyFactory.getProxy(getProxyClassLoader());
}
下面看ProxyFactory是如何創(chuàng)建代理對(duì)象,繼續(xù)跟蹤proxyFactory.getProxy(getProxyClassLoader());
public Object getProxy(ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
createAopProxy()作用是根據(jù)class的種類判斷采用的代理方式,看如下實(shí)現(xiàn)
DefaultAopProxyFactory#createAopProxy
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
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.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
//采用jdk動(dòng)態(tài)代理必須基于接口
return new JdkDynamicAopProxy(config);
}
//基于cglib實(shí)現(xiàn)代理不需要接口
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
所以在當(dāng)前調(diào)試的例子中,使用cglib代理。所以執(zhí)行如下代理。
@Override
public Object getProxy(ClassLoader classLoader) {
//。。。。。。
// Configure CGLIB Enhancer...
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
enhancer.setSuperclass(proxySuperClass);
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
//獲取攔截回調(diào)函數(shù)
Callback[] 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 above
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
// Generate the proxy class and create a proxy instance.
//返回一個(gè)cglib代理對(duì)象
return createProxyClassAndInstance(enhancer, callbacks);
}
catch (CodeGenerationException ex) {
//、、、、、、
}
}
getCallbacks(rootClass);在這個(gè)獲取回調(diào)函數(shù)的方法中,普通的aop采用的回調(diào)函數(shù)是如下的方式。
// Choose an "aop" interceptor (used for AOP calls). Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
cglib 的aop回調(diào)函數(shù)如下。
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Class<?> targetClass = null;
Object target = null;
try {
//這里注入的advised就是之前創(chuàng)建的ProxyFactory對(duì)象
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 = getTarget();
if (target != null) {
targetClass = target.getClass();
}
//根據(jù)切面信息創(chuàng)建切面內(nèi)容調(diào)用鏈
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.
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...
//創(chuàng)建一個(gè)方法調(diào)用對(duì)象,具體調(diào)用實(shí)現(xiàn)沒分析,Before邏輯大概是先調(diào)用切面,在反射調(diào)用目標(biāo)方法
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
finally {
if (target != null) {
releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
基于SpringMVC中的路徑參數(shù)和URL參數(shù)實(shí)例
這篇文章主要介紹了基于SpringMVC中的路徑參數(shù)和URL參數(shù)實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-02-02
使用jaxp進(jìn)行dom解析_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要介紹了使用jaxp進(jìn)行dom解析的相關(guān)資料,需要的朋友可以參考下2017-08-08
java文件下載設(shè)置中文名稱的實(shí)例(response.addHeader)
下面小編就為大家分享一篇java文件下載設(shè)置中文名稱的實(shí)例(response.addHeader),具有很好的參考價(jià)值,希望對(duì)大家有所幫助2017-12-12
Java設(shè)計(jì)模式之組合模式(Composite模式)介紹
這篇文章主要介紹了Java設(shè)計(jì)模式之組合模式(Composite模式)介紹,Composite定義:將對(duì)象以樹形結(jié)構(gòu)組織起來,以達(dá)成“部分-整體” 的層次結(jié)構(gòu),使得客戶端對(duì)單個(gè)對(duì)象和組合對(duì)象的使用具有一致性,需要的朋友可以參考下2015-03-03
又又叕出BUG啦!理智分析Java NIO的ByteBuffer到底有多難用
網(wǎng)絡(luò)數(shù)據(jù)的基本單位永遠(yuǎn)是byte,Java NIO提供ByteBuffer作為字節(jié)的容器,但該類過于復(fù)雜,有點(diǎn)難用.本篇文章就帶大家簡(jiǎn)單了解一下 ,需要的朋友可以參考下2021-06-06
Spring實(shí)戰(zhàn)之Bean銷毀之前的行為操作示例
這篇文章主要介紹了Spring實(shí)戰(zhàn)之Bean銷毀之前的行為操作,結(jié)合實(shí)例形式分析了spring在bean銷毀之前的行為相關(guān)設(shè)置與使用技巧,需要的朋友可以參考下2019-11-11
淺談javaSE 面向?qū)ο?Object類toString)
下面小編就為大家?guī)硪黄獪\談javaSE 面向?qū)ο?Object類toString)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-06-06
springboot 設(shè)置局域網(wǎng)訪問的實(shí)現(xiàn)步驟
Spring Boot是一個(gè)開源Java-based框架,用于創(chuàng)建獨(dú)立的、生產(chǎn)級(jí)別的Spring應(yīng)用,它旨在簡(jiǎn)化Spring應(yīng)用的初始搭建及開發(fā)過程,通過提供各種自動(dòng)配置的starter包,Spring Boot使得項(xiàng)目配置變得簡(jiǎn)單快速,感興趣的朋友一起看看吧2024-02-02
SpringCloud項(xiàng)目的log4j2漏洞解決方案詳解流程
很多小伙伴因?yàn)長(zhǎng)og4j2的驚爆0Day漏洞一時(shí)束手無策,這里提供最終解決方案可以進(jìn)行一個(gè)版本號(hào)的升級(jí),感興趣的朋友來看看吧2022-04-04

