public class MathCalculator {
public int div(int i, int j) {
System.out.println("目标方法执行,结果:" + (i / j));
return i / j;
}
}
@Aspect
public class LogAspects {
//抽取公共的切入点表达式
@Pointcut("execution(public int cn.example.aop.MathCalculator.*(..))")
public void pointCut(){};
//@Before在目标方法之前切入
@Before("pointCut()")
public void logStart(JoinPoint joinPoint){
Object[] args = joinPoint.getArgs();
System.out.println(""+joinPoint.getSignature().getName()+"执行。@Before:参数列表是:{"+ Arrays.asList(args)+"}");
}
//@After在目标方法之后切入
@After("pointCut()")
public void logEnd(JoinPoint joinPoint){
System.out.println(""+joinPoint.getSignature().getName()+"执行。@After:");
}
//@AfterReturning在目标方法正常返回的时候切入
// JoinPoint一定要出现在参数表的第一位
@AfterReturning(value="pointCut()",returning="result")
public void logReturn(JoinPoint joinPoint,Object result){
System.out.println(""+joinPoint.getSignature().getName()+"执行。@AfterReturning:运行结果:{"+result+"}");
}
//@AfterThrowing在目标方法出现异常的时候切入
@AfterThrowing(value="pointCut()",throwing="exception")
public void logException(JoinPoint joinPoint,Exception exception){
System.out.println(""+joinPoint.getSignature().getName()+"执行。@AfterThrowing异常信息:{"+exception+"}");
}
}
@EnableAspectJAutoProxy
@Configuration
public class MainConfigOfAOP {
@Bean
public MathCalculator calculator() {
return new MathCalculator();
}
@Bean
public LogAspects logAspects() {
return new LogAspects();
}
}
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext ioc = new AnnotationConfigApplicationContext(MainConfigOfAOP.class);
MathCalculator calculator = ioc.getBean("calculator", MathCalculator.class);
calculator.div(1, 1);
}
}
@EnableAspectJAutoProxy注解用于开启AOP的支持,源码:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
//...省略
}
主要是@Import(AspectJAutoProxyRegistrar.class)
,AspectJAutoProxyRegistrar实现了ImportBeanDefinitionRegistrar 接口,给系统注册组件AspectJAnnotationAutoProxyCreator,这个组件的最终有一个父接口是BeanPostProcessor,说明这个组件是个后置处理器,看源码可以发现它是InstantiationAwareBeanPostProcessor类型的后置处理器,后置处理器的功能就能在其他Bean创建之前进行拦截。AspectJAutoProxyRegistrar 源码:
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
/**
* Register, escalate, and configure the AspectJ auto proxy creator based on the value
* of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
* {@code @Configuration} class.
*/
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}
第一步从容器的refresh()开始
AnnotationConfigApplicationContext ioc = new AnnotationConfigApplicationContext(MainConfigOfAOP.class);
会进入到容器的refresh()方法开始:
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
this();
register(annotatedClasses);
refresh();
}
refresh()方法的具体步骤在《Spring源码——容器创建》写过
@Override
public void refresh() throws BeansException, IllegalStateException {
//...忽略很多源码片段...
// 一、
//Instantiate all remaining (non-lazy-init) singletons.
// 开始实例化所有剩下的单实例Bean(不包含懒加载的Bean)
// MathCalculator的Bean对象创建就是从这里开始的(虽然它是个需要增强的Bean,但是最开始的流程和普通的Bean没有区别,到最后后置处理器工作的时候才会看到它的不同)
finishBeanFactoryInitialization(beanFactory);
}
进入finishBeanFactoryInitialization()
方法之后的一些函数调用链也在《Spring源码——容器创建》写过,所以这里直接跳到AbstractAutowireCapableBeanFactory的initializeBean()
方法中:
/**
* Initialize the given bean instance, applying factory callbacks
* as well as init methods and bean post processors.
* 初始化Bean的实例,应用工厂的回调方法、自定义的初始化方法
* 和BeanPostProcessor后置处理器
*/
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
/**
* 二、
* 调用:
* BeanNameAware
* BeanClassLoaderAware
* BeanFactory
* 的方法
*/
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
/**
* 三、
* 执行后置处理器的before方法
*/
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
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()) {
/**
* 五、
* 执行后置处理器的after方法
*/
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
/**
* 六、
* 返回包装过的Bean对象(对于我们的MathCalculator,返回的就是代理对象)
*/
return wrappedBean;
}
applyBeanPostProcessorsAfterInitialization()
方法中获取到所有的后置处理器,执行它们的after()
方法,applyBeanPostProcessorsAfterInitialization()
源码:
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
/**
* 5.1
* 遍历所有的后置处理器,依次执行after方法
*/
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
调用getBeanPostProcessors()
获取的所有后置处理器,第3号位置就是AspectJAnnotationAutoProxyCreator
的后置处理器:
当遍历到AspectJAnnotationAutoProxyCreator
的后置处理器时,进入postProcessAfterInitialization()
方法
/**
* Create a proxy with the configured interceptors if the bean is
* identified as one to proxy by the subclass.
* @see #getAdvicesAndAdvisorsForBean
*/
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
/**
* 5.2
* 创建代理对象
*/
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
wrapIfNecessary()
方法:
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
/**
* 5.2.1
* 如果当前Bean已经在advisedBeans中(保存了所有增强过的Bean),就直接返回
* 当前MathCalculator还没有被增强,继续下面的流程
*/
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
/**
* 5.2.2
* isInfrastructureClass:
* 判断当前Bean是不是切面类(实现了Advisor等接口或者有@Aspect注解)
* shouldSkip:
* 获取所有的候选增强器(切面里的通知方法包装过的东西,
* 对应我们的例子就是logStart()、logEnd()、logReturn()、logException()保证后的东西)
* 然后判断增强器是不是AspectJPointcutAdvisor类型的(我们的增强器是
* InstantiationModelAwarePointcutAdvisor类型的)
*
* 所以这判断使false,继续下面的流程
*/
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
/**
*
* 5.2.3
* 现在,真正的开始创建代理对象
* 5.2.3.1.
* getAdvicesAndAdvisorsForBean()方法会去遍历所有的通知方法,
* 使用通知方法的类型和切入点表示式等计算,
* 得到当前Bean可用的增强器(包装过的通知方法),然后进行排序(见下面当前Bean可用的通知方法截图)
* 返回当前Benn可用的增强器
*/
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
/**
* 5.2.3.2.
* 将当前Bean保存到advisedBeans中,value设置为true,表示织入了通知方法
*/
this.advisedBeans.put(cacheKey, Boolean.TRUE);
/**
* 5.2.3.3.
* 创建代理(见下面的创建代理createProxy()方法)
*/
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
/**
* 5.2.3.4.
* 返回代理对象
*/
return proxy;
}
/*
* 如果当前Bean没有增强器:
* 把当前Bean放入advisedBeans,value设置为false,表示当前Bean没有通知方法
*/
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
当前Bean可用的通知方法:
创建代理createProxy()
方法:
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
//...忽略部分源码
/**
* 5.2.3.3--1 先拿到增强器(就是上面截图的那5个,第一个是固有的)
*/
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
// 设置代理工厂
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
/**
* 5.2.3.3--2 用代理工厂创建代理对象
*/
return proxyFactory.getProxy(getProxyClassLoader());
}
getProxy()
方法:
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
createAopProxy()
方法:
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
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.");
}
/**
* 5.2.3.3--3 如果目标类实现了接口(任意接口),就使用JDK动态代理,否则使用Cglib代理
* 我们的MathCalculator走的是Cglib代理
*/
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
现在,MathCalculator的代理对象已经放到容器中了,以后从容器中取的就是这个代理对象,可以看到四个通知方法和一个默认方法:
断点调试执行到div()方法,这个方法的执行会被CgligAopProxy静态内部类的intercept()方法拦截,进入:
class CglibAopProxy implements AopProxy, Serializable {
//....省略部分源码
// 一个静态内部类
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
//....省略部分源码
@Override
@Nullable
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Object target = null;
TargetSource targetSource = this.advised.getTargetSource();
try {
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);
/**
* 核心在这里
* 1. 通过advised(ProxyFactory)对象获取将要执行的目标方法(div())的拦截器链
* 连接器链就是封装过的通知方法(MethodInterceptor类型)
* 看下面的拦截器链chain截图
*/
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
// 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.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = methodProxy.invoke(target, argsToUse);
}
else {
// We need to create a method invocation...
/**
* 2. 有拦截器链,调用CglibMethodInvocation.proceed()方法执行
* proceed()就是拦截器链的执行过程
* 看下面的 CglibMethodInvocation.proceed()执行拦截器链
*/
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
//....省略部分源码
public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable {
//....省略部分源码
private int currentInterceptorIndex = -1;
@Override
@Nullable
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
/**
* 2.1 如果拦截器索引(currentInterceptorIndex)大小等于拦截器数组大小减1,
* ,直接进入invokeJoinpoint()执行目标方法
*/
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
/**
* 2.2 遍历拦截器数组,获取拦截器,拦截器索引加1,调用对应的invoke()方法
*/
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);
}
}
//....省略部分源码
拦截器链的执行过程有点像递归:
ExposeInvocationInterceptor
,currentInterceptorIndex =0,执行((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
invoke()方法,这个拦截器的invoke()方法中又会调回到ReflectiveMethodInvocation.proceed()
方法AspectJAfterThrowingAdvice
,currentInterceptorIndex =1,执行((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
invoke()方法,这个拦截器的invoke()方法中又会调回到ReflectiveMethodInvocation.proceed()
方法AfterRunningAdviceInterceptor
,currentInterceptorIndex =2,执行((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
invoke()方法,这个拦截器的invoke()方法中又会调回到ReflectiveMethodInvocation.proceed()
方法AspectJAfterAdvice
,currentInterceptorIndex =3,执行((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
invoke()方法,,这个拦截器的invoke()方法中又会调回到ReflectiveMethodInvocation.proceed()
方法((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
invoke()方法,这个拦截器的invoke()方法中会先执行前置通知,再调回到ReflectiveMethodInvocation.proceed()
方法invokeJoinpoint()
方法执行目标方法