spring系列之AOP

springaop:是 Aspect Oriented Programming 的缩写,意思是面向切面编程。可以通过预 编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。追求的是调用者和被调用者之间的解耦。

用途: 日志、事务、安全等都会写在业务代码中(也即是说,这些非业务类横切 于业务类),但这些代码往往是重复,复制——粘贴式的代码会给程序的维护带来不便,AOP 就实现了 把这些业务需求与系统需求分开来做。这种解决的方式也称代理机制。

使用方法:

1、开启自动扫描并激活自动代理

< context :component-scan base-package ="com.gupaoedu" />
< context :annotation-config />

 

2、定义切面

// 声明这是一个组件
@Component
// 声明这是一个切面 Bean
@Aspect
 
// 配置切入点 , 该方法无方法体 , 主要为方便同类中其他方法使用此处配置的切入点
@Pointcut ( "execution(* com.gupaoedu.vip.pattern.spring.aop.service..*(..))" )
public void aspect (){ }
/*
* 配置前置通知 , 使用在方法 aspect() 上注册的切入点
* 同时接受 JoinPoint 切入点对象 , 可以没有该参数
*/
@Before ( "aspect()" )
public void before (JoinPoint joinPoint){
log .info( "before 通知 " + joinPoint) ;
}
// 配置后置通知 , 使用在方法 aspect() 上注册的切入点
@After ( "aspect()" )
public void after (JoinPoint joinPoint){
log .info( "after 通知 " + joinPoint) ;
}
// 配置环绕通知 , 使用在方法 aspect() 上注册的切入点
@Around ( "aspect()" )
public void around (JoinPoint joinPoint){
long start = System. currentTimeMillis () ;
try {
((ProceedingJoinPoint) joinPoint).proceed() ;
long end = System. currentTimeMillis () ;
} catch (Throwable e) {
long end = System. currentTimeMillis () ;
log .info( "around 通知 " + joinPoint + " \t Use time : " + (end - start) + " ms with exception :
" + e.getMessage()) ;
}
}
// 配置后置返回通知 , 使用在方法 aspect() 上注册的切入点
@AfterReturning ( "aspect()" )
public void afterReturn (JoinPoint joinPoint){
log .info( "afterReturn 通知 " + joinPoint) ;
}
// 配置抛出异常后通知 , 使用在方法 aspect() 上注册的切入点
@AfterThrowing ( pointcut = "aspect()" , throwing = "ex" )
public void afterThrow (JoinPoint joinPoint , Exception ex){
log .info( "afterThrow 通知 " + joinPoint + " \t " + ex.getMessage()) ;
}
}
 
 

AOP原理分析:

入口:AOP是从此接口的后置处理器方法开始的
 

另:自定义此接口的实现可以控制bean加载前后做一些业务处理。

public interface BeanPostProcessor {

	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

}

在类AbstractAutowireCapableBeanFactory的doCreateBean方法中的初始化bean的时候initializeBean方法里会做三件事儿:

		//前置处理器
		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}
		//配置bean的init-method方法
		try {
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}
		//后指处理器
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

然后通过DefaultAopProxyFactory类的createAopProxy方法去创建代理

	@Override
	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);
		}
	}

以JDK动态代理为例:JdkDynamicAopProxy实现了InvocationHandler类,那么必定有一个invoke方法

final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable 

invoke方法主要做了一下几件事儿:

1、获取可以应用到此方法上的 Interceptor 列表(获取调用链)即方法getInterceptorsAndDynamicInterceptionAdvice(),其中在获取调用链的时候AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();会调用

AdvisorAdapterRegistry类的实现类DefaultAdvisorAdapterRegistry来完成各种通知的适配和注册
@SuppressWarnings("serial")

//它用来完成各种通知的适配和注册过程
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {

	private final List<AdvisorAdapter> adapters = new ArrayList<>(3);

	/**
	 * Create a new DefaultAdvisorAdapterRegistry, registering well-known adapters.
	 */
	public DefaultAdvisorAdapterRegistry() {
		registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
		registerAdvisorAdapter(new AfterReturningAdviceAdapter());
		registerAdvisorAdapter(new ThrowsAdviceAdapter());
	}


	@Override
	public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
		if (adviceObject instanceof Advisor) {
			return (Advisor) adviceObject;
		}
		if (!(adviceObject instanceof Advice)) {
			throw new UnknownAdviceTypeException(adviceObject);
		}
		Advice advice = (Advice) adviceObject;
		if (advice instanceof MethodInterceptor) {
			// So well-known it doesn't even need an adapter.
			return new DefaultPointcutAdvisor(advice);
		}
		for (AdvisorAdapter adapter : this.adapters) {
			// Check that it is supported.
			if (adapter.supportsAdvice(advice)) {
				return new DefaultPointcutAdvisor(advice);
			}
		}
		throw new UnknownAdviceTypeException(advice);
	}

	@Override
	public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
		List<MethodInterceptor> interceptors = new ArrayList<>(3);
		Advice advice = advisor.getAdvice();
		if (advice instanceof MethodInterceptor) {
			interceptors.add((MethodInterceptor) advice);
		}
		for (AdvisorAdapter adapter : this.adapters) {
			if (adapter.supportsAdvice(advice)) {
				interceptors.add(adapter.getInterceptor(advisor));
			}
		}
		if (interceptors.isEmpty()) {
			throw new UnknownAdviceTypeException(advisor.getAdvice());
		}
		return interceptors.toArray(new MethodInterceptor[interceptors.size()]);
	}

	@Override
	public void registerAdvisorAdapter(AdvisorAdapter adapter) {
		this.adapters.add(adapter);
	}

}
public DefaultAdvisorAdapterRegistry() {
   registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
   registerAdvisorAdapter(new AfterReturningAdviceAdapter());
   registerAdvisorAdapter(new ThrowsAdviceAdapter());
}      
springAOP设计了特定的拦截器MethodBeforeAdviceAdapter;AfterReturningAdviceAdapter;ThrowsAdviceAdapter对这些功能进行了封装,可以查看具体的拦截器中的invoke方法是先调用了advice的before/after方法,还是先调用MethodInvocation的proceed()方法。

2、如果获取的调用链为空,则直接反射调用目标方法,否则创建 MethodInvocation,调用其 proceed()方法,触发拦截器链的执行。

/**
	 * 主要实现思路可以简述为:首先获取应用到此方法上的通知链(Interceptor Chain)。
	 * 如果有通知,则 应用通知,并执行 JoinPoint;如果没有通知,则直接反射执行 JoinPoint。
	 * 而这里的关键是通知链是如 何获取的以及它又是如何执行的呢?
	 */

	//springAOP是在此处织入的
	@Override
	@Nullable
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		MethodInvocation invocation;
		Object oldProxy = null;
		boolean setProxyContext = false;

		TargetSource targetSource = this.advised.targetSource;
		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);
			}

			//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;
			}

			// Get as late as possible to minimize the time we "own" the target,
			// in case it comes from a pool.

			//获得目标对象的类
			target = targetSource.getTarget();
			Class<?> targetClass = (target != null ? target.getClass() : null);

			//获取可以应用到此方法上的 Interceptor 列表(获取调用链)
			// 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.
			//如果没有可以应用到此方法的通知(Interceptor),此直接反射调用 Method.invoke(target, args)
			//如 果 得 到 的 拦 截 器 链 chain 为 空 , 则 直 接 反 射 调 用 目 标 方 法 ,
			// 否 则 创 建 MethodInvocation,调用其 proceed()方法,触发拦截器链的执行,
			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...
				//创建 MethodInvocation
				//如 果 得 到 的 拦 截 器 链 chain 为 空 , 则 直 接 反 射 调 用 目 标 方 法 ,
				// 否 则 创 建 MethodInvocation,调用其 proceed()方法,触发拦截器链的执行,
				invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
				// Proceed to the joinpoint through the interceptor chain.
				retVal = invocation.proceed();//ReflectiveMethodInvocation.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);
			}
		}
	}
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值