日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

spring aop源码实现分析

發布時間:2025/4/5 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 spring aop源码实现分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1. 先分析Advice

before執行Cglib2AopProxy的intercept方法:

/*** General purpose AOP callback. Used when the target is dynamic or when the* proxy is not frozen.*/private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {private AdvisedSupport advised;public DynamicAdvisedInterceptor(AdvisedSupport advised) {this.advised = advised;}public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {MethodInvocation invocation = null;Object oldProxy = null;boolean setProxyContext = false;Class targetClass = null;Object target = null;try {Object retVal = null;if (this.advised.exposeProxy) {// Make invocation available if necessary.oldProxy = AopContext.setCurrentProxy(proxy);setProxyContext = true;}// May be <code>null</code>. 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();}List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);// 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.retVal = methodProxy.invoke(target, args);}else {// We need to create a method invocation...invocation = new CglibMethodInvocation(proxy, target, method, args,targetClass, chain, methodProxy);// If we get here, we need to create a MethodInvocation.retVal = invocation.proceed();}retVal = massageReturnTypeIfNecessary(proxy, target, method, retVal);return retVal;}finally {if (target != null) {releaseTarget(target);}if (setProxyContext) {// Restore old proxy. AopContext.setCurrentProxy(oldProxy);}}}

第一步:獲取target ?

target.getClass();

第二步:獲取攔截器和advice,返回定義好的org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor示例

/*** Determine a list of {@link org.aopalliance.intercept.MethodInterceptor} objects* for the given method, based on this configuration.* @param method the proxied method* @param targetClass the target class* @return List of MethodInterceptors (may also include InterceptorAndDynamicMethodMatchers)*/public List getInterceptorsAndDynamicInterceptionAdvice(Method method, Class targetClass) {MethodCacheKey cacheKey = new MethodCacheKey(method);List cached = (List) this.methodCache.get(cacheKey);if (cached == null) {cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(this, method, targetClass);this.methodCache.put(cacheKey, cached);}return cached;}

第三步創建一個方法的invocation

// We need to create a method invocation...invocation = new CglibMethodInvocation(proxy, target, method, args,targetClass, chain, methodProxy);

第四步 執行aop的before方法

public void before(Method method, Object[] args, Object target)throws Throwable {System.out.println(" Before method!");}

第五步 觸發MethodBeforeAdviceInterceptor的invoke方法

public Object invoke(MethodInvocation mi) throws Throwable {this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );return mi.proceed();}

第六步:觸發ReflectiveMethodInvocation的process方法

public Object proceed() throws Throwable {// We start with an index of -1 and increment early.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 {// Dynamic matching failed.// Skip this interceptor and invoke the next in the chain.return proceed();}}else {// It's an interceptor, so we just invoke it: The pointcut will have// been evaluated statically before this object was constructed.return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);}}

第七步,包裝返回值Cglib2AopProxy

/*** Wrap a return of this if necessary to be the proxy*/private static Object massageReturnTypeIfNecessary(Object proxy, Object target, Method method, Object retVal) {// Massage return value if necessaryif (retVal != null && retVal == target &&!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {// Special case: it returned "this".// Note that we can't help if the target sets a reference// to itself in another returned object.retVal = proxy;}return retVal;}

最后執行finanly方法

finally {if (target != null) {releaseTarget(target);}if (setProxyContext) {// Restore old proxy. AopContext.setCurrentProxy(oldProxy);}

before,after,around,throw基本相似,不一一贅述

2.PointCut和Advisor為例

?2.1 創建代理的過程

首先是ProxyFactoryBean獲取對象代理

/*** Return a proxy. Invoked when clients obtain beans from this factory bean.* Create an instance of the AOP proxy to be returned by this factory.* The instance will be cached for a singleton, and create on each call to* <code>getObject()</code> for a proxy.* @return a fresh AOP proxy reflecting the current state of this factory*/public Object getObject() throws BeansException {initializeAdvisorChain();if (isSingleton()) {return getSingletonInstance();}else {if (this.targetName == null) {logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +"Enable prototype proxies by setting the 'targetName' property.");}return newPrototypeInstance();}}

獲取過程如下:

/*** Return the singleton instance of this class's proxy object,* lazily creating it if it hasn't been created already.* @return the shared singleton proxy*/private synchronized Object getSingletonInstance() {if (this.singletonInstance == null) {this.targetSource = freshTargetSource();if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {// Rely on AOP infrastructure to tell us what interfaces to proxy.Class targetClass = getTargetClass();if (targetClass == null) {throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");}setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));}// Initialize the shared singleton instance.super.setFrozen(this.freezeProxy);this.singletonInstance = getProxy(createAopProxy());}return this.singletonInstance;}

父類創建代理的過程

/*** Subclasses should call this to get a new AOP proxy. They should <b>not</b>* create an AOP proxy with <code>this</code> as an argument.*/protected final synchronized AopProxy createAopProxy() {if (!this.active) {activate();}return getAopProxyFactory().createAopProxy(this);}

調用代理工廠創建代理的過程

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()) {return new JdkDynamicAopProxy(config);}if (!cglibAvailable) {throw new AopConfigException("Cannot proxy target class because CGLIB2 is not available. " +"Add CGLIB to the class path or specify proxy interfaces.");}return CglibProxyFactory.createCglibProxy(config);}else {return new JdkDynamicAopProxy(config);}}

可以看出,代理的實現主要是jdk本身自帶的動態代理和cglib提供的代理。

2.2 獲取代理的過程

this.singletonInstance = getProxy(createAopProxy());

Cglib2AopProxy類的Object getProxy(ClassLoader classLoader)

public Object getProxy(ClassLoader classLoader) {if (logger.isDebugEnabled()) {logger.debug("Creating CGLIB2 proxy: target source is " + this.advised.getTargetSource());}try {Class rootClass = this.advised.getTargetClass();Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");Class proxySuperClass = rootClass;if (AopUtils.isCglibProxyClass(rootClass)) {proxySuperClass = rootClass.getSuperclass();Class[] additionalInterfaces = rootClass.getInterfaces();for (int i = 0; i < additionalInterfaces.length; i++) {Class additionalInterface = additionalInterfaces[i];this.advised.addInterface(additionalInterface);}}// Validate the class, writing log messages as necessary. validateClassIfNecessary(proxySuperClass);// 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.setStrategy(new UndeclaredThrowableStrategy(UndeclaredThrowableException.class));enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));enhancer.setInterceptDuringConstruction(false); Callback[] callbacks = getCallbacks(rootClass);enhancer.setCallbacks(callbacks);enhancer.setCallbackFilter(new ProxyCallbackFilter(this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));Class[] types = new Class[callbacks.length];for (int x = 0; x < types.length; x++) {types[x] = callbacks[x].getClass();}enhancer.setCallbackTypes(types);// Generate the proxy class and create a proxy instance. Object proxy;if (this.constructorArgs != null) {proxy = enhancer.create(this.constructorArgTypes, this.constructorArgs);}else {proxy = enhancer.create();}return proxy;}catch (CodeGenerationException ex) {throw new AopConfigException("Could not generate CGLIB subclass of class [" +this.advised.getTargetClass() + "]: " +"Common causes of this problem include using a final class or a non-visible class",ex);}catch (IllegalArgumentException ex) {throw new AopConfigException("Could not generate CGLIB subclass of class [" +this.advised.getTargetClass() + "]: " +"Common causes of this problem include using a final class or a non-visible class",ex);}catch (Exception ex) {// TargetSource.getTarget() failedthrow new AopConfigException("Unexpected AOP exception", ex);}}

獲取回調方法

private Callback[] getCallbacks(Class rootClass) throws Exception {// Parameters used for optimisation choices...boolean exposeProxy = this.advised.isExposeProxy();boolean isFrozen = this.advised.isFrozen();boolean isStatic = this.advised.getTargetSource().isStatic();// Choose an "aop" interceptor (used for AOP calls).Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);// Choose a "straight to target" interceptor. (used for calls that are// unadvised but can return this). May be required to expose the proxy.Callback targetInterceptor = null;if (exposeProxy) {targetInterceptor = isStatic ?(Callback) new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :(Callback) new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource());}else {targetInterceptor = isStatic ?(Callback) new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :(Callback) new DynamicUnadvisedInterceptor(this.advised.getTargetSource());}// Choose a "direct to target" dispatcher (used for// unadvised calls to static targets that cannot return this).Callback targetDispatcher = isStatic ?(Callback) new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp();Callback[] mainCallbacks = new Callback[]{aopInterceptor, // for normal advicetargetInterceptor, // invoke target without considering advice, if optimizednew SerializableNoOp(), // no override for methods mapped to thistargetDispatcher, this.advisedDispatcher,new EqualsInterceptor(this.advised),new HashCodeInterceptor(this.advised)};Callback[] callbacks;// If the target is a static one and the advice chain is frozen,// then we can make some optimisations by sending the AOP calls// direct to the target using the fixed chain for that method.if (isStatic && isFrozen) {Method[] methods = rootClass.getMethods();Callback[] fixedCallbacks = new Callback[methods.length];this.fixedInterceptorMap = new HashMap(methods.length);// TODO: small memory optimisation here (can skip creation for// methods with no advice)for (int x = 0; x < methods.length; x++) {List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass);fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());this.fixedInterceptorMap.put(methods[x].toString(), new Integer(x));}// Now copy both the callbacks from mainCallbacks// and fixedCallbacks into the callbacks array.callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];for (int x = 0; x < mainCallbacks.length; x++) {callbacks[x] = mainCallbacks[x];}for (int x = 0; x < fixedCallbacks.length; x++) {callbacks[x + mainCallbacks.length] = fixedCallbacks[x];}this.fixedInterceptorOffset = mainCallbacks.length;}else {callbacks = mainCallbacks;}return callbacks;}

獲取攔截器和動態攔截器Advice

/*** Determine a list of {@link org.aopalliance.intercept.MethodInterceptor} objects* for the given method, based on this configuration.* @param method the proxied method* @param targetClass the target class* @return List of MethodInterceptors (may also include InterceptorAndDynamicMethodMatchers)*/public List getInterceptorsAndDynamicInterceptionAdvice(Method method, Class targetClass) {MethodCacheKey cacheKey = new MethodCacheKey(method);List cached = (List) this.methodCache.get(cacheKey);if (cached == null) {cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(this, method, targetClass);this.methodCache.put(cacheKey, cached);}return cached;}

繼續調用DefaultAdvisorChainFactory:

?

public List getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, Class targetClass) {// This is somewhat tricky... we have to process introductions first,// but we need to preserve order in the ultimate list.List interceptorList = new ArrayList(config.getAdvisors().length);boolean hasIntroductions = hasMatchingIntroductions(config, targetClass);AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();Advisor[] advisors = config.getAdvisors();for (int i = 0; i < advisors.length; i++) {Advisor advisor = advisors[i];if (advisor instanceof PointcutAdvisor) {// Add it conditionally.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 (int j = 0; j < interceptors.length; j++) {interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptors[j], 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;}

NameMatchMethodPointcut

public boolean matches(Method method, Class targetClass) {for (int i = 0; i < this.mappedNames.size(); i++) {String mappedName = (String) this.mappedNames.get(i);if (mappedName.equals(method.getName()) || isMatch(method.getName(), mappedName)) {return true;}}return false;}

?

轉載于:https://www.cnblogs.com/davidwang456/p/5534090.html

總結

以上是生活随笔為你收集整理的spring aop源码实现分析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。