终于到AOP了,前面没看懂的一定跟着代码多看,不然本篇文章容易迷路!
话不多说,万变不离其宗,先上图。
AOP时序图
源码分析
1.初始化阶段 -> 匹配切点的方法
- 回到上篇文章中的
AbstractAutowireCapableBeanFactory.doCreateBean
主要看依赖注入后面的代码
//找到这里
//依赖注入
populateBean(beanName, mbd, instanceWrapper);
//初始化bean里面的初始方法 AOP切面入口 本文主要看这个
exposedObject = initializeBean(beanName, exposedObject, mbd);
//初始容器时创建的Bean对象,为其添加BeanPostProcessor后置处理器
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
//调用所有实现BeanNameAware、BeanClassLoaderAware、BeanFactoryAware接口方法回调
//为Bean实例对象包装相关属性,如名称,类加载器,所属容器等信息
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//调用回调方法,为Bean实例初始化前做一些处理
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//文件中通过init-method属性指定的 或者 @PostConstruct
//还有一些实现InitializingBean 会调用后置通知 afterPropertiesSet
//MVC mapping在这里回调触发 下一篇MVC时讲解
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()) {
//调用回调方法,为Bean实例初始化之后做一些处理 AOP代理主要走这个
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
//返回对象
return wrappedBean;
}
//调用BeanPostProcessor后置处理器实例对象初始化之后的处理方法
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
//遍历容器为所创建的Bean回调所有实现了BeanPostProcessor接口后置处理器
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
//为Bean实例对象在初始化之后做一些自定义的处理操作 接下来走这个
Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
- 接下来就到了spring-aop包下的
AbstractAutoProxyCreator#postProcessAfterInitialization
->wrapIfNecessary
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && 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;
}
// Create proxy if we have advice.
//如果存在advice 就创建代理类 先看获取advices链,再看创建代理对象
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
//如果这个数组不等于null
//protected static final Object[] DO_NOT_PROXY = null;
if (specificInterceptors != DO_NOT_PROXY) {
//标识这个bean被有advice
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;
}
- 接下来看获取拦截器链advices的逻辑,往下到
AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable 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) {
//加载当前已配置的AOP列表
List<Advisor> candidateAdvisors = findCandidateAdvisors();
//根据beanName去匹配 下面简单分析一下这个
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
//排序
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
//返回执行责任链
return eligibleAdvisors;
}
findAdvisorsThatCanApply
一直往下到AopUtils.canApply
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
MethodMatcher methodMatcher = pc.getMethodMatcher();
if (methodMatcher == MethodMatcher.TRUE) {
// No need to iterate the methods if we're matching any method anyway...
return true;
}
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}
Set<Class<?>> classes = new LinkedHashSet<>();
if (!Proxy.isProxyClass(targetClass)) {
classes.add(ClassUtils.getUserClass(targetClass));
}
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
for (Class<?> clazz : classes) {
//获取所有的方法
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
//断点调试走introductionAwareMethodMatcher.matches 接下来看这里
if (introductionAwareMethodMatcher != null ?
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
introductionAwareMethodMatcher.matches -> AspectJExpressionPointcut.getShadowMatch
//找到这行 通过AOP规则验证这个方法是否满足切点
shadowMatch = obtainPointcutExpression().matchesMethodExecution(methodToMatch);
如果满足当前配置的切点,则在AbstractAutoProxyCreator#wrapIfNecessary
创建代理对象并返回,初始化阶段到这里就完成了,接下来继续分析创建代理源码,也就是代码织入阶段
2.代码织入阶段 ->创建动态代理
- 回到
AbstractAutoProxyCreator.wrapIfNecessary
//找到这一段
//获取拦截器链
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;
}
//创建代理对象
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable 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);
proxyFactory.addAdvisors(advisors);
//原始class对象的信息 封装了一层SingletonTargetSource
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
//创建代理-> 这里有两种创建代理的方法 CGLIB 和JDK 我们这里挑 JdkDynamicAopProxy看
return proxyFactory.getProxy(getProxyClassLoader());
}
- 接下来到
ProxyFactory#getProxy
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
//createAopProxy -> ProxyCreatorSupport#createAopProxy
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
//传的是this
return getAopProxyFactory().createAopProxy(this);
}
//得到jdk或者Cglib对象
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (!NativeDetector.inNativeImage() &&
(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)) {
//通过构造方法保存advice信息AdvisedSupport
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
//已jdk代理为例
public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
Assert.notNull(config, "AdvisedSupport must not be null");
if (config.getAdvisorCount() == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
throw new AopConfigException("No advisors and no TargetSource specified");
}
this.advised = config;
//获取原始类的接口 JKD动态代理必须是有接口的
this.proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(this.proxiedInterfaces);
}
- 接下来分析
getProxy -> JdkDynamicAopProxy.getProxy
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
//很熟悉的创建代理方式 如果不理解先移步看动态代理
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
至此代理对象就创建好了,返回到IOC容器中的就是代理对象了。
3.运行阶段 -> 动态代理的反射调用
- 调用某个方法是拿到的是代理对象,贴下
JdkDynamicAopProxy
代理类
//上面看到这个,执行回调方法为 this ,那么就说明代理对象调用会走当前类的invoke方法
Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
//接下来看invoker方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
//获取原始类封装SingletonTargetSource
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
//一系列的判断删掉
......
//获取到原始类
target = targetSource.getTarget();
//类信息
Class<?> targetClass = (target != null ? target.getClass() : null);
//chain 链/管道的意思 获取拦截器管道
//一直往下跟 实际上就是包装了一下 同时存了缓存 interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
//interceptor 就是registry.getInterceptors(advisor);通过构造方法初始化前置 后置 异常
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
if (chain.isEmpty()) {
//管道为空
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
//直接通过反射调用原始类
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// We need to create a method invocation...
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
//开始调用管道 我们接下来走这里
retVal = invocation.proceed();
}
//后面就是返回指定额处理了,先去掉
。。。
}
finally {
if (target != null && !targetSource.isStatic()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
- 接下来
invocation.proceed() ->ReflectiveMethodInvocation.proceed()
//成员变量
//执行的管道调用链 上面通过构造方法赋值
protected final List<?> interceptorsAndDynamicMethodMatchers;
private int currentInterceptorIndex = -1;
//开始责任链调用
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
//如果当前执行的下标等于执行的size-1 说明是到最后一个执行了 则执行原生调用方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
//这里面跟进去就是这个 return method.invoke(target, args);
return invokeJoinpoint();
}
//下标+1 就是从0开始 默认值是-1
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
//如果要动态匹配joinPoint
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
//动态匹配:运行时参数是否满足匹配条件
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
//主要看前置后置和异常 传入的参数是this
//例如前置切面执行完会再次调用到该方法
return dm.interceptor.invoke(this);
}
else {
//继续递归
return proceed();
}
}
else {
//如果不是 直接调用MethodInterceptor
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
dm.interceptor.invoke(this) -> AspectJAfterAdvice.invoke
调用通知的方法,挑一个看吧
//调用之后 其他的可以自己了解
public Object invoke(MethodInvocation mi) throws Throwable {
try {
//反射调用原始类
return mi.proceed();
}
finally {
//调用返回后的切面方法
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
总结
在容器初始化bean之后,回调到后置通知方法,aop正好实现后置通知方法,经过判断如果满足当前的配置切点则生成代理类并返回到IOC容器中。
创建代理类时会把原始类、调用链路等信息通过构造方法保存下来,在创建动态代理时newInstance
时传入的回调handler
类也是this
,那么在调用该代理类时会到handler
类的invoke
方法
在invoke方法中通过递归以及增加下标的方法使调用链路执行反射调用,如果不能正常匹配到对应的Advice类,则在到最后一个时直接反射调用原始类并返回
如果能正常匹配到,例如上面的AspectJAfterAdvice则是先反射调用原始类,然后再调用后置切面方法,整个流程结束
至此整个AOP切面的源码就分析完了,看完这些代码,再手写一般简单的应没啥问题了吧!
下一节MVC源码篇,都是基于IOC容器来,思想和AOP差不多。
以上就是本章的全部内容了。
上一篇:Spring源码分析第二弹 - DI 依赖注入分析
下一篇:Spring源码分析第四弹 - MVC分析
莫等闲,白了少年头,空悲切