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 necessary
- if (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() failed
- throw 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 advice
- targetInterceptor, // invoke target without considering advice, if optimized
- new SerializableNoOp(), // no override for methods mapped to this
- targetDispatcher, 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;
- }
spring aop源码实现分析的更多相关文章
- spring AOP源码分析(三)
在上一篇文章 spring AOP源码分析(二)中,我们已经知道如何生成一个代理对象了,那么当代理对象调用代理方法时,增强行为也就是拦截器是如何发挥作用的呢?接下来我们将介绍JDK动态代理和cglib ...
- Spring AOP 源码分析 - 拦截器链的执行过程
1.简介 本篇文章是 AOP 源码分析系列文章的最后一篇文章,在前面的两篇文章中,我分别介绍了 Spring AOP 是如何为目标 bean 筛选合适的通知器,以及如何创建代理对象的过程.现在我们的得 ...
- Spring AOP 源码分析 - 创建代理对象
1.简介 在上一篇文章中,我分析了 Spring 是如何为目标 bean 筛选合适的通知器的.现在通知器选好了,接下来就要通过代理的方式将通知器(Advisor)所持有的通知(Advice)织入到 b ...
- Spring AOP 源码分析 - 筛选合适的通知器
1.简介 从本篇文章开始,我将会对 Spring AOP 部分的源码进行分析.本文是 Spring AOP 源码分析系列文章的第二篇,本文主要分析 Spring AOP 是如何为目标 bean 筛选出 ...
- Spring AOP 源码分析系列文章导读
1. 简介 前一段时间,我学习了 Spring IOC 容器方面的源码,并写了数篇文章对此进行讲解.在写完 Spring IOC 容器源码分析系列文章中的最后一篇后,没敢懈怠,趁热打铁,花了3天时间阅 ...
- Spring AOP源码分析(三):基于JDK动态代理和CGLIB创建代理对象的实现原理
AOP代理对象的创建 AOP相关的代理对象的创建主要在applyBeanPostProcessorsBeforeInstantiation方法实现: protected Object applyBea ...
- 最简 Spring AOP 源码分析!
前言 最近在研究 Spring 源码,Spring 最核心的功能就是 IOC 容器和 AOP.本文定位是以最简的方式,分析 Spring AOP 源码. 基本概念 上面的思维导图能够概括了 Sprin ...
- 5.2 Spring5源码--Spring AOP源码分析二
目标: 1. 什么是AOP, 什么是AspectJ 2. 什么是Spring AOP 3. Spring AOP注解版实现原理 4. Spring AOP切面原理解析 一. 认识AOP及其使用 详见博 ...
- 5.2 spring5源码--spring AOP源码分析二--切面的配置方式
目标: 1. 什么是AOP, 什么是AspectJ 2. 什么是Spring AOP 3. Spring AOP注解版实现原理 4. Spring AOP切面原理解析 一. 认识AOP及其使用 详见博 ...
随机推荐
- MSSQL数据库中Text类型字段在PHP中被截断之解 (转)
在PHP中使用了MSSQL数据库,恰巧数据库中又使用了Text类型字段,于是问题产生了.每次从数据库中查询得到的数据总是被莫名的截断,一开始是以为我使用的PHP框架中对字符串的长度有所限制,后来发现这 ...
- iPhone的Push(推送通知)功能原理浅析
第一部分:Push原理(以下绝大多数内容参考自.图片来自iPhone OS Reference Library)机制简介Push 的工作机制可以简单的概括为下图图中,Provider是指某个iPhon ...
- wordpress搬家换域名
很多朋友开始接触wordpress都是在本地安装调试好了,再上传到服务器正常运营,我也是一样当我在本地测试好了准备将网站上线,在搬家到服务器的时候遇到过的一些问题,记录分享一下我是如何为wordpre ...
- 分享:写了一个 java 调用 C语言 开发的动态库的范例
分享:写了一个 java 调用 C语言 开发的动态库的范例 cfunction.h 代码#pragma once#ifdef __cplusplusextern "C" {#e ...
- 嗅探、中间人sql注入、反编译--例说桌面软件安全性问题
嗅探.中间人sql注入.反编译--例说桌面软件安全性问题 今天这篇文章不准备讲太多理论,讲我最近遇到的一个案例.从技术上讲,这个例子没什么高深的,还有一点狗屎运的成分,但是它又足够典型,典型到我可以讲 ...
- 冲刺阶段 day12
项目进展 周二我们将专业管理部分又继续做了完善,之前漏掉的几项功能也都在熟能生巧中编写的越来越顺畅,但还差最后一点数据库部分没能实现,我们会尽快完成. 存在问题 还是与数据库的连接上出现问题,部分不能 ...
- json-smart 使用示例(推荐fastjson)
关于json库,请使用fastjson,这是我用过的最好用的json库! 地址:https://github.com/alibaba/fastjson ======================== ...
- Ping!
我知道我很久没有更新这个博客了,所以特意来更新一下,骚扰一下各位订户.我有几年没有写过很具体跟技术相关的文章了,而跟职业发展相关的文章也半年没更新了,所以最近准备开始写写技术文章.在此之前,我要先完结 ...
- Unity3D核心类型一览
Unity3D核心类型一览 本文记录了Unity3D的最基本的核心类型.包括Object.GameObject.Component.Transform.Behaviour.Renderer.Colli ...
- Spring MVC 1
============================== 摘抄至<跟我学SpringMVC.pdf> =========================== 1.首先用户发送请求— ...