Spring系列之-Spring AOP设计原理(二)
2017-12-24 00:00
459 查看
Spring系列之-Spring AOP设计原理(一)中讲述了Spring AOP初始化过程。Spring AOP是基于代理模式实现的,而为对象建立代理的这种过程是在Spring 调用getBaen()方法第一次获取Bean的过程。我们在上一文中分析到,在解析<aop:config>中Spring注册了一个AspectJAwareAdvisorAutoProxyCreator到容器中,这个类是Spring AOP代理建立过程中的核心类,其继承体系如下:
可以看到在AspectJAwareAdvisorAutoProxyCreator的继承体系过程中AspectJAwareAdvisorAutoProxyCreator间接实现了InstantiationAwareBeanPostProcessor接口,二InstantiationAwareBeanPostProcessor继承于BeanPostProcessor。
BeanPostProcessor这个接口再熟悉不过了,在Spring第一次调用getBean()方法时会对Bean进行实例化并依赖注入,只要实现BeanPostProcessor接口的类会在初始化Bean过程中调用BeanPostProcessor接口的方法。
真正实现BeanPostProcessor系列接口的是AspectJAwareAdvisorAutoProxyCreator的父类AbstractAutoProxyCreator,具体方法如下:
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);这句代码判断具体哪些bean需要创建代理。该方法是一个抽象方法其实现在AbstractAdvisorAutoProxyCreator中
这系列代码就是获取到当前bean所对应的通知,目前是判断当前Bean是否需要创建代理,暂时不详细研究知道这里。
回到上面如果当前bean需要创建代理则调用createProxy方法为当前bean创建代理并返回代理对象。
createProxy方法实现如下:
proxyFactory.isProxyTargetClass()这句代码判断是否是使用jdk代理还是使用cglib进行代理,<aop:config>中proxy-target-class这个属性值用于决定是否使用类的代理还是基于接口代理,缺省情况下proxy-target-class=false,如果为ture说明是基于类的代理需要cglib库,否则使用JDK动态代理,前提是有接口。
向代理工厂设置完相关参数后就会调用工厂方法中的 return proxyFactory.getProxy(getProxyClassLoader());创建代理对象。
代码非常简单创建AOP代理实现类并且调用getProxy方法获取代理对象。
DefaultAopProxyFactory实现了AopProxyFactory,createAopProxy实现方法如下:
这段代码主要决定使用何种代理方式
1.如果使用平台优化(config.isOptimize())或者 是直接代理类(config.isProxyTargetClass())或者没有实现任何接口进入if判断
2.如果代理类是接口或者被判断是一个动态代理类即proxy-target-class="false"或者没有设置proxy-target-class属性
满足上述1,2使用JDK动态代理,否则使用Cglib创建代理对象。
如果不满足1则直接使用JDK动态代理。
下面我们看JDK动态代理是如何创建代理对象
如果使用Jdk动态代理将会调用下面方法获取代理对象;
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this)
这句代理就能看见JDK动态代理的影子了。
熟悉JDK原生代理的人都知道,要使用JDK代理必须创建一个类实现InvocationHandler,这里JdkDynamicAopProxy本身就实现了InvocationHandler,故Proxy.newProxyInstance(classLoader, proxiedInterfaces, this)传入的是this。
JdkDynamicAopProxy必须要实现InvocationHandler中的invoke方法,我们看下invoke方法是如何实现:
可以看到在AspectJAwareAdvisorAutoProxyCreator的继承体系过程中AspectJAwareAdvisorAutoProxyCreator间接实现了InstantiationAwareBeanPostProcessor接口,二InstantiationAwareBeanPostProcessor继承于BeanPostProcessor。
BeanPostProcessor这个接口再熟悉不过了,在Spring第一次调用getBean()方法时会对Bean进行实例化并依赖注入,只要实现BeanPostProcessor接口的类会在初始化Bean过程中调用BeanPostProcessor接口的方法。
真正实现BeanPostProcessor系列接口的是AspectJAwareAdvisorAutoProxyCreator的父类AbstractAutoProxyCreator,具体方法如下:
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (!this.earlyProxyReferences.contains(cacheKey)) { return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; } 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; } // 如果当前bean存在通知,则创建代理 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); if (specificInterceptors != DO_NOT_PROXY) { this.advisedBeans.put(cacheKey, Boolean.TRUE); 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; }
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);这句代码判断具体哪些bean需要创建代理。该方法是一个抽象方法其实现在AbstractAdvisorAutoProxyCreator中
@Override protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) { List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName); if (advisors.isEmpty()) { return DO_NOT_PROXY; } return advisors.toArray(); } protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { //获取所有定义的通知,直接从Spring BeanFactory中获取,这里会获取到befor和after所对应的通知bean List<Advisor> candidateAdvisors = findCandidateAdvisors(); List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); extendAdvisors(eligibleAdvisors); if (!eligibleAdvisors.isEmpty()) { eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; } protected List<Advisor> findAdvisorsThatCanApply( List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) { ProxyCreationContext.setCurrentProxiedBeanName(beanName); try { return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass); } finally { ProxyCreationContext.setCurrentProxiedBeanName(null); } }
这系列代码就是获取到当前bean所对应的通知,目前是判断当前Bean是否需要创建代理,暂时不详细研究知道这里。
回到上面如果当前bean需要创建代理则调用createProxy方法为当前bean创建代理并返回代理对象。
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); if (specificInterceptors != DO_NOT_PROXY) { this.advisedBeans.put(cacheKey, Boolean.TRUE); Object proxy = createProxy( bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; }
createProxy方法实现如下:
protected Object createProxy( Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) { if (this.beanFactory instanceof ConfigurableListableBeanFactory) { AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass); } //实例化一个代理工厂 ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.copyFrom(this); //判断是否直接代理当前类或使用接口代理, if (!proxyFactory.isProxyTargetClass()) { if (shouldProxyTargetClass(beanClass, beanName)) { proxyFactory.setProxyTargetClass(true); } else { evaluateProxyInterfaces(beanClass, proxyFactory); } } Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); for (Advisor advisor : advisors) { proxyFactory.addAdvisor(advisor); } proxyFactory.setTargetSource(targetSource); customizeProxyFactory(proxyFactory); proxyFactory.setFrozen(this.freezeProxy); if (advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } return proxyFactory.getProxy(getProxyClassLoader()); }
proxyFactory.isProxyTargetClass()这句代码判断是否是使用jdk代理还是使用cglib进行代理,<aop:config>中proxy-target-class这个属性值用于决定是否使用类的代理还是基于接口代理,缺省情况下proxy-target-class=false,如果为ture说明是基于类的代理需要cglib库,否则使用JDK动态代理,前提是有接口。
向代理工厂设置完相关参数后就会调用工厂方法中的 return proxyFactory.getProxy(getProxyClassLoader());创建代理对象。
public Object getProxy(ClassLoader classLoader) { return createAopProxy().getProxy(classLoader); }
代码非常简单创建AOP代理实现类并且调用getProxy方法获取代理对象。
DefaultAopProxyFactory实现了AopProxyFactory,createAopProxy实现方法如下:
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)) { return new JdkDynamicAopProxy(config); } return new ObjenesisCglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); } }
这段代码主要决定使用何种代理方式
1.如果使用平台优化(config.isOptimize())或者 是直接代理类(config.isProxyTargetClass())或者没有实现任何接口进入if判断
2.如果代理类是接口或者被判断是一个动态代理类即proxy-target-class="false"或者没有设置proxy-target-class属性
满足上述1,2使用JDK动态代理,否则使用Cglib创建代理对象。
如果不满足1则直接使用JDK动态代理。
下面我们看JDK动态代理是如何创建代理对象
如果使用Jdk动态代理将会调用下面方法获取代理对象;
public Object getProxy(ClassLoader classLoader) { if (logger.isDebugEnabled()) { logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource()); } Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true); findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); }
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this)
这句代理就能看见JDK动态代理的影子了。
熟悉JDK原生代理的人都知道,要使用JDK代理必须创建一个类实现InvocationHandler,这里JdkDynamicAopProxy本身就实现了InvocationHandler,故Proxy.newProxyInstance(classLoader, proxiedInterfaces, this)传入的是this。
JdkDynamicAopProxy必须要实现InvocationHandler中的invoke方法,我们看下invoke方法是如何实现:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { MethodInvocation invocation; Object oldProxy = null; boolean setProxyContext = false; TargetSource targetSource = this.advised.targetSource; Class<?> targetClass = null; Object target = null; try { if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { // The target does not implement the equals(Object) method itself. return equals(args[0]); } else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { // The target does not implement the hashCode() method itself. return hashCode(); } else if (method.getDeclaringClass() == DecoratingProxy.class) { // There is only getDecoratedClass() declared -> dispatch to proxy config. return AopProxyUtils.ultimateTargetClass(this.advised); } else if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) { // Service invocations on ProxyConfig with the proxy config... return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); } Object retVal; 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 = targetSource.getTarget(); if (target != null) { targetClass = target.getClass(); } // Get the interception chain for this method. List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); // Check whether we have any advice. If we don't, we can fallback on direct // reflective invocation of the target, and avoid creating a MethodInvocation. if (chain.isEmpty()) { // 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 = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); } else { // We need to create a method invocation... invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); // Proceed to the joinpoint through the interceptor chain. retVal = invocation.proceed(); } // Massage return value if necessary. Class<?> returnType = method.getReturnType(); if (retVal != null && retVal == target && returnType != Object.class && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { // Special case: it returned "this" and the return type of the method // is type-compatible. Note that we can't help if the target sets // a reference to itself in another returned object. retVal = proxy; } else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) { throw new AopInvocationException( "Null return value from advice does not match primitive return type for: " + method); } return retVal; } finally { if (target != null && !targetSource.isStatic()) { // Must have come from TargetSource. targetSource.releaseTarget(target); } if (setProxyContext) { // Restore old proxy. AopContext.setCurrentProxy(oldProxy); } } }
相关文章推荐
- Spring系列之-Spring AOP设计原理(一)
- spring系列(三)——springAOP原理探究(CGLIB代理机制)
- 深入解析Spring架构与设计原理(二)AOP原理
- Spring技术内幕——深入解析Spring架构与设计原理(二)AOP
- Spring 系列:AOP原理
- 死磕Spring AOP系列5:设计模式在AOP中的使用
- 深入解析Spring架构与设计原理-AOP
- Spring技术内幕——深入解析Spring架构与设计原理(二)AOP
- Spring系列之 (八):AOP实现原理
- Spring技术内幕——深入解析Spring架构与设计原理(二)AOP
- Spring技术内幕——深入解析Spring架构与设计原理(二)AOP
- AOP的概念和实现原理—Spring系列介绍
- Spring基于注解形式的 AOP的原理流程及源码解析(四)
- 反射实现AOP动态代理模式(SpringAOP的实现原理)
- Spring系列之AOP
- 《Spring技术内幕——深入解析Spring架构与设计原理》连载1
- 深入解析Spring架构与设计原理3
- spring5——Aop的实现原理(动态代理)
- 《Spring技术内幕——深入解析Spring架构与设计原理》连载2
- Spring AOP 实现原理