设计理念
将分散在程序各处的横切关注点剥离出来,并已集中的方式进行表达 AOP和继承有些类似,前者重点考虑程序横切逻辑,后者重点考虑纵向职责分派
AOP核心概念
Advice(通知) -定义在连接点处的行为,围绕方法调用而进行注入
-Pointcut(切点) -确定在哪些连接点处应用通知
Advisor()通知器 -组合Advice与Pointcut
AOP 代理
未使用代理如下
已使用代理如下
如图所示
AOP代理可以 执行目标对象之前后都可以先执行指定好的通知器(切点和通知)
SpringAOP目标代理对象创建如下
JDK动态代理 (代理接口)CGLIB(代理实现类)AOP代理源码分析
public class ProxyFactoryBean extends ProxyCreatorSupport implements FactoryBean, BeanClassLoaderAware, BeanFactoryAware public Object getObject() throws BeansException { //步骤1 initializeAdvisorChain(); //步骤2 if (isSingleton()) return getSingletonInstance(); if (targetName == null) logger.warn("Using non-singleton proxies with singleton targets is often undesirable. Enable prototype proxies by setting the 'targetName' property."); return newPrototypeInstance(); } }ProxyFactoryBean是springAop底层实现源头,构建其AOP代理 如上 步骤1 配置通知事件会调用getObject()方法,initializeAdvisorChain()会把配置的Adviser通知器方法加载到集合中,以便后续目标方法执行前后去集合中匹配,根据每个Adviser的pointcut去执行 步骤2 根据配置的 scope属性,默认是single
紧接着分析 getSingletonInstance()方法获取代理对象
private synchronized Object getSingletonInstance() { if (singletonInstance == null) { targetSource = freshTargetSource(); if (autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) { Class targetClass = getTargetClass(); if (targetClass == null) throw new FactoryBeanNotInitializedException( "Cannot determine target class for proxy"); //1 setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, proxyClassLoader)); } super.setFrozen(freezeProxy); //2 singletonInstance = getProxy(createAopProxy()); } return singletonInstance; } public interface AopProxy { public abstract Object getProxy(); public abstract Object getProxy(ClassLoader classloader); }如上 //1 表示创建出来代理对象要实现代理接口 //2 通过工厂代理创建AopProxy接口,调用其getProxy,生成代理实例
AOP选择动态代理和CGLIB 源码如下
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable { 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); else return CglibProxyFactory.createCglibProxy(config); } else { return new JdkDynamicAopProxy(config); } } |源码分析
如果目标对象实现了接口,那么Spring就会通过动态代理为目标对象生成代理对象,否则通过CGLIB代理 代理模式作用是:为其它对象提供一种代理以控制对这个对象的访问
接着分析JDK动态代理源码如下
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable { public Object getProxy(ClassLoader classLoader) { if (logger.isDebugEnabled()) logger.debug((new StringBuilder()) .append("Creating JDK dynamic proxy: target source is ") .append(advised.getTargetSource()).toString()); Class proxiedInterfaces[] = AopProxyUtils .completeProxiedInterfaces(advised); findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); //rs Proxy return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); } } public interface InvocationHandler extends Callback { public abstract Object invoke(Object obj, Method method, Object aobj[]) throws Throwable; }通过其源码发现 如上rs Proxy真正使用JDK动态代理获得代理实例,代理类需要继承InvocationHandler接口, InvocationHandler内部只有一个抽象方法invoke(参数1指代理类,参数2指代理方法,参数3指方法参数值) Proxy.newProxyInstance(参数1 类加载器,参数2 动态代理对象实现了接口,参数3 指InvocationHandler 实例通过反射生成对象的实例) 由此可得 JDK动态代理 实现步骤 1.创建一个实现接口InvocationHandler的类吗,它必须实现invoke方法 2.创建被代理类以及接口 3.通过proxy的静态方法创建代理 4.通过代理调用方法
CGLIB 源码如下
final class CglibAopProxy implements AopProxy, Serializable { public Object getProxy(ClassLoader classLoader) { if (logger.isDebugEnabled()) logger.debug((new StringBuilder()) .append("Creating CGLIB proxy: target source is ") .append(advised.getTargetSource()).toString()); try { Class rootClass = advised.getTargetClass(); Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy"); Class proxySuperClass = rootClass; if (ClassUtils.isCglibProxyClass(rootClass)) { proxySuperClass = rootClass.getSuperclass(); Class additionalInterfaces[] = rootClass.getInterfaces(); Class arr$[] = additionalInterfaces; int len$ = arr$.length; for (int i$ = 0; i$ < len$; i$++) { Class additionalInterface = arr$[i$]; advised.addInterface(additionalInterface); } } validateClassIfNecessary(proxySuperClass); 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(java / lang / reflect / UndeclaredThrowableException)); enhancer.setInterfaces(AopProxyUtils .completeProxiedInterfaces(advised)); enhancer.setInterceptDuringConstruction(false); Callback callbacks[] = getCallbacks(rootClass); enhancer.setCallbacks(callbacks); enhancer.setCallbackFilter(new ProxyCallbackFilter(advised .getConfigurationOnlyCopy(), fixedInterceptorMap, fixedInterceptorOffset)); Class types[] = new Class[callbacks.length]; for (int x = 0; x < types.length; x++) types[x] = callbacks[x].getClass(); enhancer.setCallbackTypes(types); Object proxy; //结果 if (constructorArgs != null) proxy = enhancer.create(constructorArgTypes, constructorArgs); else proxy = enhancer.create(); return proxy; } catch (CodeGenerationException ex) { throw new AopConfigException( (new StringBuilder()) .append("Could not generate CGLIB subclass of class [") .append(advised.getTargetClass()) .append("]: ") .append("Common causes of this problem include using a final class or a non-visible class") .toString(), ex); } catch (IllegalArgumentException ex) { throw new AopConfigException( (new StringBuilder()) .append("Could not generate CGLIB subclass of class [") .append(advised.getTargetClass()) .append("]: ") .append("Common causes of this problem include using a final class or a non-visible class") .toString(), ex); } catch (Exception ex) { throw new AopConfigException("Unexpected AOP exception", ex); } } }如上结果 通过 Enhancer.create生成代理实例,其通过Enhancer 字节码类构建类的接口、类型、类回调等参数 最终会的代理实例对象
总结:
本篇文章主要阐述 AOP拦截触发器执行过程、AOP代理实现的两种方式
作者简介:张程 技术研究
更多文章请关注微信公众号:zachary分解狮 (frankly0423)