博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
spring aop源码实现分析
阅读量:6680 次
发布时间:2019-06-25

本文共 20832 字,大约阅读时间需要 69 分钟。

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 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(); } 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     * getObject() 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 not     * create an AOP proxy with this 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;    }

 

转载地址:http://vziao.baihongyu.com/

你可能感兴趣的文章
[摘录]第3章 终局谈判策略
查看>>
react-router中的路由钩子使用
查看>>
C#编程之“串口通讯多次接收”
查看>>
【python 文件操作】python 文件操作
查看>>
线程相关
查看>>
linux下svn服务器配置问题
查看>>
《自我介绍》
查看>>
【C语言】20-static和extern关键字2-对变量的作用
查看>>
使用mpvue开发github小程序总结
查看>>
用表格给表单定位
查看>>
Redis
查看>>
Intent-filter的介绍
查看>>
开博说明
查看>>
Scala方法定义,方法和函数的区别,将方法转换成函数
查看>>
Hbase 读写 原理
查看>>
详解JDBC驱动的四种类型
查看>>
第十一次作业
查看>>
关于Android 2.2设置短信本机号码和头像的解决办法
查看>>
JZ-C-47
查看>>
【算法随记三】小半径中值模糊的急速实现(16MB图7.5ms实现) + Photoshop中蒙尘和划痕算法解读。...
查看>>