AOP源码分析
上一篇分析过spring 通过ProxyFactory来创建代理对象。下面来分析下ProxyFactory的原理
ProxyFactory源码分析
上一篇aop的介绍中有提到这两行代码
ProxyFactory proxyFactory = new ProxyFactory();
BookInterface bookInterface = (BookInterface)proxyFactory.getProxy();
关键是getProxy方法。
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
// 默认为DefaultAopProxyFactory
return getAopProxyFactory().createAopProxy(this);
}
//最终调到这个方法 通过该方法判断是通过cglib代理还是jdk代理
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// 如果ProxyFactory的isOptimize为true,
// 或者isProxyTargetClass为true,
// 或者被代理对象没有实现接口,
// 或者只实现了SpringProxy这个接口
// 那么则利用Cglib进行动态代理,但如果被代理类是接口,或者被代理类已经是进行过JDK动态代理而生成的代理类了则只能进行JDK动态代理
// 其他情况都会进行JDK动态代理,比如被代理类实现了除SpringProxy接口之外的其他接口
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)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
决定好通过那个方式进行代理后,真正调getProxy()方法由下面两个实现类
这里通过jdk的动态代理为例子
spring中jdk动态代理源码分析
JdkDynamicAopProxy这个类就是jdk动态代理源码。
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
// this实现了InvocationHandler
return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
}
这个方法就是放回一个代理对象,不做过多分析。jdk动态代理中,执行代理逻辑和目标方法是通过invoke方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
// 拿到被代理对象
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
// 如果接口中没有定义equals()方法,那么则直接调用,不走代理
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// 得到代理对象的类型,而不是所实现的接口
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// 也是直接调用Advised接口中的方法,不走代理逻辑
// 其实就是利用代理对象获取ProxyFactory中的信息
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
// 如果ProxyFactory的exposeProxy为true,则将代理对象设置到currentProxy这个ThreadLocal中去
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// 被代理对象和代理类
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
//获取被代理对象和执行的方法对应的代理逻辑链路
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
if (chain.isEmpty()) {
// 如果没有代理逻辑,则直接调用对应方法
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
//把代理逻辑链路 和代理对象 执行的方法 入参 等封装成MethodInvocation对象
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
retVal = invocation.proceed();
}
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
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()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
AopContext.setCurrentProxy(oldProxy);
}
}
}
整个方法的大致流程是:过滤掉equal()、hashcode()这两个方法,这两个方法执行不触发代理逻辑。判断代理类型,执行对应代码。各种判断通过后,List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);方法拿到所有的代理逻辑链路。没有代理逻辑执行目标方法。有代理逻辑,把每个代理逻辑加上代理对象,入参等封装成MethodInvocation对象执行invocation.proceed();方法。
这个过程中核心部分有两个getInterceptorsAndDynamicInterceptionAdvice方法拿到所有代理逻辑。proceed()真正去执行代理逻辑。那么接下来分析如何获取所有代理逻辑和如何去执行
如何获取所有代理逻辑
getInterceptorsAndDynamicInterceptionAdvice这个方法最终调到DefaultAdvisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice方法
@Override
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class<?> targetClass) {
// This is somewhat tricky... We have to process introductions first,
// but we need to preserve order in the ultimate list.
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
// 从ProxyFactory中拿到所设置的Advice(添加时被封装成了DefaultPointcutAdvisor)
// 添加的时候会控制顺序
Advisor[] advisors = config.getAdvisors();
List<Object> interceptorList = new ArrayList<>(advisors.length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
Boolean hasIntroductions = null;
for (Advisor advisor : advisors) {
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
// 先匹配类
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
// 再匹配方法
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
boolean match;
if (mm instanceof IntroductionAwareMethodMatcher) {
if (hasIntroductions == null) {
hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
}
match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
}
else {
match = mm.matches(method, actualClass);
}
// 如果匹配则将Advisor封装成为Interceptor
if (match) {
//该方法使用了适配器模式,根据配置的切面逻辑类型 BeforeAdvice 、AroundAdvice等等 封装成Interceptor
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
if (mm.isRuntime()) {
// Creating a new object instance in the getInterceptors() method
// isn't a problem as we normally cache created chains.
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
else {
// 将Advisor封装成为Interceptor
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
这个过程大致是:从ProxyFactory 拿到所有代理逻辑,不管在ProxyFactory 中配置的是addAdvice()还是addAdvisor()都会封装成Advisor。遍历所有代理逻辑,判断该代理逻辑是满足切点(源码中先判断 是否满足被代理的类 ,再判断是否满足被代理的方法)。匹配通过会把所有通过的代理逻辑封装成Interceptor。
如何调用
找到那些代理逻辑需要被调用后。通过invocation.proceed();进行调用
public Object proceed() throws Throwable {
// currentInterceptorIndex初始值为-1,每调用一个interceptor就会加1
// 当调用完了最后一个interceptor后就会执行被代理方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
//都拿到对应的代理逻辑
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
// 当前interceptor是InterceptorAndDynamicMethodMatcher,则先进行匹配,匹配成功后再调用该interceptor
// 如果没有匹配则递归调用proceed()方法,调用下一个interceptor
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
if (dm.methodMatcher.matches(this.method, 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 {
// 直接调用MethodInterceptor,传入this,在内部会再次调用proceed()方法进行递归
// 比如MethodBeforeAdviceInterceptor
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
整个流程大概是:判断当前执行完的代理逻辑是不是最后一个,如果是执行代理方法。如果不是执行代理逻辑,执行代理逻辑之前会进行类型判断。类型判断未通过递归执行invoke方法,接着判断下一个代理逻辑。判断通过后还有进行方法入参的判断。判断通过执行对应的代理逻辑。
上面这些过程都是ProxyFactory的过程。那么在spring中的Aop流程是怎么使用这个ProxyFactory的呢
springAOP流程源码分析
下面通过spring源码分析上一篇中使用到AOP代码。
@EnableAspectJAutoProxy
@Configuration
public class AopConfig {}
@Component
@Aspect
public class MyAspect {
@Before("execution(public void aop.BookService.book())")
public void myBefore(JoinPoint joinPoint) {
System.out.println("myBefore --- BookService init");
}
}
其中@EnableAspectJAutoProxy的代码
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({AspectJAutoProxyRegistrar.class})
public @interface EnableAspectJAutoProxy {
boolean proxyTargetClass() default false;
boolean exposeProxy() default false;
}
主要是引入了AspectJAutoProxyRegistrar.class。这个类呢主要就给spring容器中注册AnnotationAwareAspectJAutoProxyCreator这个类。并且根据@EnableAspectJAutoProxy的属性值给这个类对应的属性赋值。
根据类关系图可以看出AnnotationAwareAspectJAutoProxyCreator实际上是一个BeanPostProcessor。注册这个AnnotationAwareAspectJAutoProxyCreator实际上就是注册了一个BeanPostProcessor。在spring生命周期中分析过 。BeanPostProcessor在初始化后执行会执行postProcessAfterInitialization方法。在这里执行的是AbstractAutoProxyCreator.postProcessAfterInitialization方法。
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
//核心方法 基于当前bean创建代理对象
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
//这个bean已经是代理类 直接返回
return bean;
}
//advisedBeans表示已经判断过的bean 和下面一个if有关
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
//已经判断过的bean 不需要代理 直接返回
return bean;
}
//isInfrastructureClass(bean.getClass()) 符合这些(Pointcut.class 、Advisor.class 、Advisor.class等)类型的bean不需要aop
// 当前正在创建的Bean不用进行AOP,比如切面Bean
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
// 判断当前bean是否存在匹配的advice,如果存在则要生成一个代理对象
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
// advisedBeans记录了某个Bean已经进行过AOP了
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;
}
wrapIfNecessary这个过程就是:通过一些条件判断哪些类需要AOP,哪些类不需要AOP。如果需要AOP,核心部分有两个
- Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);获取所有匹配的切面‘’
- Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));创建代理对象
先来看创建代理对象
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()) {
// Explicit handling of JDK proxy targets (for introduction advice scenarios)
if (Proxy.isProxyClass(beanClass)) {
// Must allow for introductions; can't just set interfaces to the proxy's interfaces only.
for (Class<?> ifc : beanClass.getInterfaces()) {
proxyFactory.addInterface(ifc);
}
}
}
else {
// No proxyTargetClass flag enforced, let's apply our default checks...
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
// 如果使用了@DeclareParents,那么在添加advisor时,会把对应的接口添加到ProxyFactory中
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// Use original ClassLoader if bean class not locally loaded in overriding class loader
ClassLoader classLoader = getProxyClassLoader();
if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {
classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();
}
return proxyFactory.getProxy(classLoader);
}
底层就是通过ProxyFactory来创建代理对象。这也是为什么有先铺垫ProxyFactory的原因。这里就不在分析了。
接下来看如何获取切面
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
// 寻找匹配的Advisor
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 找到所有的Advisor
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 进行筛选
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
//子类扩展 可以忽略
extendAdvisors(eligibleAdvisors);
// 对Advisor进行排序,按Ordered接口、@Order注解进行排序
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
从上面源码来看 如何获取切面 大致分为三个步骤,
- 第一步 找到所有的切面 findCandidateAdvisors();
- 第二步进行筛选 indAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
- 第三步排序 sortAdvisors(eligibleAdvisors);
findCandidateAdvisors()
@Override
protected List<Advisor> findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
// 先找到所有Advisor类型的Bean对象
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
// 再从所有切面中解析得到Advisor对象 就是解析@Aspect注解的类下面的@Before等注解
if (this.aspectJAdvisorsBuilder != null) {
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
这一个步流程就是从spring容器中找出所有的bean判断哪些bean是Advisor类型。通过判断哪些Advisor类型的bean有@Aspect注解,解析@Aspect注解的bean里面的@Before等注解
indAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
该方法底层核心筛选代码就是canApply,通过该方法返回boolean值判断符不符合要求
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
// 判断targetClass是不是和当前Pointcut匹配
// 先判断类
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) {
if (introductionAwareMethodMatcher != null ?
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
// 在判断方法是否匹配
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
主要也是从类 和方法这两方面进行判断。不在深入分析。
最后进行切面的排序,根据@order注解进行排序也不深入分析。到此SpringAOP流程就结束了
Spring中AOP原理流程图:https://www.processon.com/view/link/5faa4ccce0b34d7a1aa2a9a5
下面来总结一下
总结
- 当使用@Aspect进行切面配置的时候需要添加@EnableAspectJAutoProxy表示启动@Aspect的切面配置。原理就是引入了AspectJAutoProxyRegistrar.class
- AspectJAutoProxyRegistrar.class向Spring容器中注册了AnnotationAwareAspectJAutoProxyCreator。其父类是BeanPostProcessor类型。在bean的生命周期中的初始化后阶段会执行postProcessAfterInitialization方法。对应上的实现就是AbstractAutoProxyCreator.postProcessAfterInitialization方法。
- AbstractAutoProxyCreator.postProcessAfterInitialization方法作用就是判断当前类需要不需要AOP,如果需要返回代理对象,如果不需要返回原始bean对象。其核心方法是wrapIfNecessary
- wrapIfNecessary核心步骤有两个 一个找出所有匹配这个bean的切面,另一个是生成代理对象
- 找出所有匹配这个bean的切面分为三个步骤 1:找出所有的切面 2:筛选切面 3:切面排序
- 当找到匹配的切面后,通过ProxyFactory创建代理对象。到此bean的代理对象就创建完毕