Spring源码分析 AOP设计实现过程

Spring源码分析 AOP设计实现过程

设计理念

将分散在程序各处的横切关注点剥离出来,并已集中的方式进行表达
AOP和继承有些类似,前者重点考虑程序横切逻辑,后者重点考虑纵向职责分派

AOP核心概念

Advice(通知)
-定义在连接点处的行为,围绕方法调用而进行注入

-Pointcut(切点)
-确定在哪些连接点处应用通知

Advisor()通知器
-组合Advice与Pointcut

AOP 代理

未使用代理如下
通篇1

已使用代理如下

aop
如图所示

AOP代理可以 执行目标对象之前后都可以先执行指定好的通知器(切点和通知)

SpringAOP目标代理对象创建如下

  • JDK动态代理 (代理接口)
  • CGLIB(代理实现类)

001
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)

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值