浅析Spring系列
1. AOP概念与Spring AOP
1.1 AOP的概念
来自AOP官方文档:docs.spring.io/spring-fram…
英文水平有限,有些直接用英文比较准确。
Aspect:A modularization of a concern that cuts across multiple classes。例如:事务管理是一个好的横切关注点。
Join point:A point during the execution of a program。比如方法的执行,异常的处理。在Spring中,一般代表方法的执行。Spring AOP仅支持方法执行的join point
Advice:Action taken by an aspect at a particular join point。包括"around", "before", and "after" 三种advice。Spring中将advice类似拦截器,并且join point中维护了一系列的拦截器。
Pointcut:A predicate that matches join points.
Introduction: Declaring additional methods or fields on behalf of a type.
Target object: An object being advised by one or more aspects
AOP proxy: An object created by the AOP framework in order to implement the aspect contracts。在Spring中,AOP proxy是JDK动态代理或者CGLIB代理。
Weaving: linking aspects with other application types or objects to create an advised object. 可以在编译时(如AspcetJ编译器)、加载时以及运用时,Spring AOP的Weaving就是在运行时。
1.2 Spring AOP的目标
不是为了提供完整的AOP实现(比如仅支持方法的join point),而是旨在和Spring IOC结合解决通用问题。
1.3 Spring AOP和AspectJ关系
Spring解释和AspectJ相同的注解,使用AspectJ提供的库进行切入点解析和匹配。在AOP运行时,仍然是纯Spring AOP,不会依赖AspectJ的编译器或者织入器。
2. 动态代理例子
Spring AOP底层的核心还是使用JDK动态代理或者CGLIB代理,所以理解这两种代理的使用,有助于我们理解源码。Spring也只是在此基础上增加了IOC和AspectJ的整合而已。
public interface IEchoService {
void echo(String str);
}
public class MyEchoService implements IEchoService {
@Override
public void echo(String str) {
System.out.println(str);
}
}
2.1 JDK动态代理
JDK动态代理的核心是通过Proxy.newProxyInstance方法,拦截逻辑在InvocationHandler
public class JdkDynamicProxyDemo {
public static void main(String[] args) {
MyEchoService echoServiceImpl = new MyEchoService();
IEchoService echoService = (IEchoService)Proxy.newProxyInstance(echoServiceImpl.getClass().getClassLoader(),
echoServiceImpl.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object object, Method method, Object[] args) throws Throwable {
System.out.println("jdk proxy");
method.invoke(echoServiceImpl,args);
return null;
}
});
echoService.echo("hello");
//output:
//jdk proxy
//hello
}
}
2.2 CGLIB代理
CGLIB的核心是通过api,设置一些参数,然后创建代理对象。拦截函数在Callback接口,一般会使用子接口MethodInterceptor。
public class CglibProxyDemo {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
//设置目标类
enhancer.setSuperclass(MyEchoService.class);
//设置拦截函数
enhancer.setCallback(new MethodInterceptor() {
/**
*
* @param o 表示被代理的类
* @param method 拦截的方法
* @param objects 参数列表
* @param methodProxy 拦截方法的代理,invokeSuper方法表示对被代理对象的方法的调用
* @return 执行结果
* @throws Throwable
*/
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("cglib proxy");
//不能用invoke,会进入死循环;method.invoke执行的是子类的方法(也就是CGLIB生成的子类的方法k)
methodProxy.invokeSuper(o, objects);
return "";
}
});
//创建代理类
MyEchoService echoService = (MyEchoService) enhancer.create();
echoService.echo("hello");
//output:
//cglib proxy
//hello
}
}
2.3 Spring使用AspectJ代理
在Spring AOP中,常用的是AspectJ的方式,以下是使用的例子。后续的源码分析中,也是基于此基础进行分析,其中拦截主要分析BeforeAdvice。
@Configuration
@EnableAspectJAutoProxy
public class AopDemo {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(AopDemo.class);
context.refresh();
IEchoService echoService = context.getBean(IEchoService.class);
echoService.echo("hello");
//output:
//before AspectJ
//hello
context.close();
}
@Bean
public MyEchoService myEchoService(){
return new MyEchoService();
}
@Bean
public AspectConfig aspectConfig(){
return new AspectConfig();
}
}
@Aspect
public class AspectConfig {
@Pointcut("execution(* com.spring.demo.MyEchoService.echo(..))")
public void pointCut(){
}
@Before("pointCut()")
public void before(){
System.out.println("before AspectJ");
}
public void emptyMethod(){
}
}
3. Spring AOP流程分析
源码分析主要分析Spring AOP对于AspectJ的整合,以及IOC的整合。主要分析流程,建议可以代码debug跟踪一下,比较容易理解。本章节会从@EnableAspectJAutoProxy注解作为入口,然后分析如何代理bean,再分析如何拦截Bean。
3.1 @EnableAspectJAutoProxy
从注解上发现会有@Import注解,AspectJAutoProxyRegistrar类实现了ImportBeanDefinitionRegistrar接口,会在IOC容器启动的过程中调用registerBeanDefinitions方法。而调用ImportBeanDefinitionRegistrar接口,在Spring启动阶段中的处理BeanFactoryPostProcessor阶段。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
/**
* Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
* to standard Java interface-based proxies. The default is {@code false}.
*/
boolean proxyTargetClass() default false;
/**
* Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal}
* for retrieval via the {@link org.springframework.aop.framework.AopContext} class.
* Off by default, i.e. no guarantees that {@code AopContext} access will work.
* @since 4.3.1
*/
boolean exposeProxy() default false;
}
AspectJAutoProxyRegistrar的registerBeanDefinitions方法会注入AOP相关的Bean(BeanPostProssor)注入到IOC容器中,并且会把@EnableAspectJAutoProxy注解的值给运用起来。
//AspectJAutoProxyRegistrar#registerBeanDefinitions
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//注册AnnotationAwareAspectJAutoProxyCreator到IOC容器
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);
}
}
}
AopConfigUtils里会注册AnnotationAwareAspectJAutoProxyCreator,这个类实现了BeanPostProcessor接口。bean创建的过程中会调用BeanPostProcessor接口的方法。
//AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
这里会把AnnotationAwareAspectJAutoProxyCreator封装成BeanDefinition。等到Spring启动阶段中的BeanPostProcessor处理阶段时,会被实例化和初始化。
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
3.2 代理Bean
AnnotationAwareAspectJAutoProxyCreator实现了BeanPostProcessor接口,所以Bean在创建的过程中会调用,把Bean给代理了。主要入口在初始化完成后操作。
//AbstractAutoProxyCreator#postProcessAfterInitialization
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
wrapIfNecessary的逻辑如下,首先会判断,Bean是否需要代理,如果不用代理直接返回。然后回查找符合这个Bean的Advisor,如果找到了则进对这个Bean进行代理。主要逻辑有两大部分:查找符合的Advisor;对Bean进行创建代理。
//AbstractAutoProxyCreator#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.
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;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
3.2.1 查找Advisor
getAdvicesAndAdvisorsForBean是父类的抽象方法,子类AbstractAdvisorAutoProxyCreator会调用findEligibleAdvisors方法,逻辑如下
//AbstractAdvisorAutoProxyCreator#findEligibleAdvisors
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
List<Advisor> candidateAdvisors = findCandidateAdvisors();
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
//会根据@Order等注解进行排序
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
而findCandidateAdvisors方法,在AnnotationAwareAspectJAutoProxyCreator会进行重写,内部实际会调用BeanFactoryAspectJAdvisorsBuilder的buildAspectJAdvisors方法
//AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors
protected List<Advisor> findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
if (this.aspectJAdvisorsBuilder != null) {
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
在buildAspectJAdvisors方法中,主要会判断是否有@Aspect注解,然后调用advisorFactory的getAdvisors方法获取整个Advisor,并且会把结果缓存起来。advisorFactory的实现类实际就ReflectiveAspectJAdvisorFactory
//BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors
public List<Advisor> buildAspectJAdvisors() {
//...
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
for (String beanName : beanNames) {
if (!isEligibleBean(beanName)) {
continue;
}
// We must be careful not to instantiate beans eagerly as in this case they
// would be cached by the Spring container but would not have been weaved.
Class<?> beanType = this.beanFactory.getType(beanName);
if (beanType == null) {
continue;
}
//判断是否有Aspect注解,并且不是Ajc编译的(字段前缀不是ajc$)
if (this.advisorFactory.isAspect(beanType)) {
aspectNames.add(beanName);
AspectMetadata amd = new AspectMetadata(beanType, beanName);
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
if (this.beanFactory.isSingleton(beanName)) {
this.advisorsCache.put(beanName, classAdvisors);
} else {
this.aspectFactoryCache.put(beanName, factory);
}
advisors.addAll(classAdvisors);
}
}
}
//...
}
在getAdvisors方法中,首先会找AdvisorMethod,然后再获取Advisor
//ReflectiveAspectJAdvisorFactory#getAdvisors
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
//...
// We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
// so that it will only instantiate once.
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
List<Advisor> advisors = new ArrayList<>();
for (Method method : getAdvisorMethods(aspectClass)) {
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
//...
return advisors;
}
在getAdvisorMethods方法中,会返回除了@Pointcut标记的方法。
//ReflectiveAspectJAdvisorFactory#getAdvisorMethods
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
final List<Method> methods = new ArrayList<>();
ReflectionUtils.doWithMethods(aspectClass, method -> {
// Exclude pointcuts
if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
methods.add(method);
}
}, ReflectionUtils.USER_DECLARED_METHODS);
if (methods.size() > 1) {
methods.sort(METHOD_COMPARATOR);
}
return methods;
}
在getAdvisor方法中,会先获取PointCut,然后封装成一个Advisor。
//ReflectiveAspectJAdvisorFactory#getAdvisor
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName) {
validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
AspectJExpressionPointcut expressionPointcut = getPointcut(
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
if (expressionPointcut == null) {
return null;
}
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
在获取PpintCut方法中,首先会查找AspectJ注解,也就是@Before、@Around等注解,内部实现通过for循环查找,有找到就返回,然后创建AspectJExpressionPointcut对象,设置expression,此时如果我们直接引用了pointcut方法,这里还没有解析。例如:@Before("pointCut()"),此处的expression="pointCut()"。
//ReflectiveAspectJAdvisorFactory#getPointcut
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
AspectJExpressionPointcut ajexp =
new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
if (this.beanFactory != null) {
ajexp.setBeanFactory(this.beanFactory);
}
return ajexp;
}
获取的AspectJExpressionPointcut最后会封装成Advisor,实现类就是InstantiationModelAwarePointcutAdvisorImpl,该类也实现了PointcutAdvisor。Advisor接口有个方法是获取Advice,该接口是切面的逻辑,看下如何返回不同类型的Advce,也就是对应不同的注解,如@Before,@Around。
内部实际会调用aspectJAdvisorFactory获取Advice,而aspectJAdvisorFactory就是ReflectiveAspectJAdvisorFactory。
//InstantiationModelAwarePointcutAdvisorImpl#getAdvice
public synchronized Advice getAdvice() {
if (this.instantiatedAdvice == null) {
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}
return this.instantiatedAdvice;
}
//InstantiationModelAwarePointcutAdvisorImpl#instantiateAdvice
private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
return (advice != null ? advice : EMPTY_ADVICE);
}
在获取Advice逻辑中,可以发现是根据注解来,例如:Before注解,则返回AspectJMethodBeforeAdvice。
//ReflectiveAspectJAdvisorFactory#getAdvice
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
//...
AbstractAspectJAdvice springAdvice;
switch (aspectJAnnotation.getAnnotationType()) {
case AtPointcut:
if (logger.isDebugEnabled()) {
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
}
return null;
case AtAround:
springAdvice = new AspectJAroundAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtBefore:
springAdvice = new AspectJMethodBeforeAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfter:
springAdvice = new AspectJAfterAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfterReturning:
springAdvice = new AspectJAfterReturningAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
springAdvice.setReturningName(afterReturningAnnotation.returning());
}
break;
case AtAfterThrowing:
springAdvice = new AspectJAfterThrowingAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
}
break;
default:
throw new UnsupportedOperationException(
"Unsupported advice type on method: " + candidateAdviceMethod);
}
//...
return springAdvice;
}
3.2.2 过滤Advisor
前面已经找出来所有的Advisor,现在要看下哪些Advisor适合当前的Bean。
//AbstractAdvisorAutoProxyCreator#findAdvisorsThatCanApply
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
在findAdvisorsThatCanApply方法中,核心逻辑还是canApply方法中
//AopUtils#findAdvisorsThatCanApply
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new ArrayList<>();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {
// already processed
continue;
}
//核心判断逻辑
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
内部实际上会在判断Advisor的类型,我们知道的Advisor是PointcutAdvisor,而且由前面得知,PointcutAdvisor的实现类是AspectJExpressionPointcut。
//AopUtils#canApply
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
if (advisor instanceof IntroductionAdvisor) {
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
else if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
// It doesn't have a pointcut so we assume it applies.
return true;
}
}
在canApply内部,实际上会获取PointCut的MethodMatcher,获取Bean的所有方法(包括父类接口方法),然后遍历进行匹配,如果能匹配上就认为是符合的。
AspectJExpressionPointcut内部实际上也自己实现了ClassFilter和MethodMatcher接口,所以matches逻辑,都在AspectJExpressionPointcut内部实现。而内部则会通过获取PointcutExpression,然后进行判断方法是否符合@Pointcut注解。PointcutExpression实际上是由AspectJ框架提供的,这也应征了Spring AOP所描述的"Spring interprets the same annotations as AspectJ 5, using a library supplied by AspectJ for pointcut parsing and matching. The AOP runtime is still pure Spring AOP, though, and there is no dependency on the AspectJ compiler or weaver."
//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) {
if (introductionAwareMethodMatcher != null ?
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
3.2.3 创建代理对象
假设已经找到了合适的Advisor,现在是时候创建代理对象了。先会构建Advisor,因为我们从参数列表可以发现,虽然前面获取到了Advisor对象,但是参数实际上是Object的,可能是Spring为了更通用。所以对于不是Advisor的对象,会在封装成Advisor,最后会利用ProxyFactory创建代理对象
//AbstractAutoProxyCreator#createProxy
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
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(getProxyClassLoader());
}
getProxy内部会调用createAopProxy方法获取AopProxyFactory,然后调用getProxy代理对象,而返回的实际就是DefaultAopProxyFactory。
//ProxyFactory#getProxy
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
//ProxyFactory#createAopProxy
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
//ProxyFactory#getAopProxyFactory
public AopProxyFactory getAopProxyFactory() {
return this.aopProxyFactory;
}
//ProxyFactory
public ProxyCreatorSupport() {
this.aopProxyFactory = new DefaultAopProxyFactory();
}
在获取AopProxy对象的内部逻辑中,会判断是使用JDK动态代理,还是CGLIB代理,逻辑如下代码所示。现在简单做个总结:
- 如果目标对象实现了接口,默认会采用JDK动态代理实现AOP。
- 如果目标对象实现了接口, 可以强制使用CGLIB实现AOP。@EnableAspectJAutoProxy注解的proxyTargetClass设置为true或者xml配置的proxy-target-class设置为true。
- 如果目标对象没有实现接口,必须采用CGLIB实现AOP。
JDK动态代理和CGLIB字节码生成的区别如下:
- JDK动态代理只能对实现了接口的类生成代理(底层逻辑有判断必须是接口才能代理),而不能针对类。
- CGLIB是针对类实现代理,底层逻辑是继承,对指定类生成一个子类,覆盖其中的方法,所以要代理的方法不要声明为final或private。
//DefaultAopProxyFactory#createAopProxy
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.");
}
//代理对象是个接口 || 或者已经是JDK动态代理
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
先看下JdkDynamicAopProxy获取代理对象的逻辑,核心就是调用Proxy.newProxyInstance方法,并且JdkDynamicAopProxy有实现InvocationHandler接口,也就是拦截逻辑就在JdkDynamicAopProxy中。
//JdkDynamicAopProxy#getProxy
public Object getProxy() {
return getProxy(ClassUtils.getDefaultClassLoader());
}
//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);
}
再看下ObjenesisCglibAopProxy,继承了CglibAopProxy,getProxy实际就是在CglibAopProxy里。逻辑上也是调用CGLIB的api,然后创建代理对象。CGLIB拦截的逻辑就在Callback接口上,在Spring AOP上,具体拦截逻辑就在DynamicAdvisedInterceptor上。
//CglibAopProxy#getProxy
public Object getProxy(@Nullable ClassLoader classLoader) {
//...
// Configure CGLIB Enhancer...
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
enhancer.setSuperclass(proxySuperClass);
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
// fixedInterceptorMap only populated at this point, after getCallbacks call above
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
// Generate the proxy class and create a proxy instance.
return createProxyClassAndInstance(enhancer, callbacks);
// ...
}
3.3 拦截Bean
3.3.1 JdkDynamicAopProxy
拦截的核心,在于创建执行链,然后通过封装成MethodInvocation进行调用。获取拦截链的方法实际上会通过AdvisorChainFactory接口的getInterceptorsAndDynamicInterceptionAdvice方法获取,AdvisorChainFactory的默认实现类为DefaultAdvisorChainFactory
//JdkDynamicAopProxy#invoke
// Get the interception chain for this method.
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// We need to create a method invocation...
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
retVal = invocation.proceed();
在DefaultAdvisorChainFactory的getInterceptorsAndDynamicInterceptionAdvice方法中,核心逻辑如下:从前面得知我们的Advisor实际上PointcutAdvisor,会走一下逻辑,通过AdvisorAdapterRegistry获取MethodInterceptor接口。AdvisorAdapterRegistry的默认实现为DefaultAdvisorAdapterRegistry。
//DefaultAdvisorChainFactory#getInterceptorsAndDynamicInterceptionAdvice
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
boolean match = mm.matches(method, actualClass);
//...
if (match) {
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
}
获取拦截器的逻辑为:从AdvisorAdapter列表中便利,如果支持的Advise就进行转换,默认的AdvisorAdapter有MethodBeforeAdviceAdapter、AfterReturningAdviceAdapter和ThrowsAdviceAdapter。
//DefaultAdvisorAdapterRegistry#getInterceptors
for (AdvisorAdapter adapter : this.adapters) {
if (adapter.supportsAdvice(advice)) {
interceptors.add(adapter.getInterceptor(advisor));
}
}
//DefaultAdvisorAdapterRegistry
public DefaultAdvisorAdapterRegistry() {
registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
registerAdvisorAdapter(new AfterReturningAdviceAdapter());
registerAdvisorAdapter(new ThrowsAdviceAdapter());
}
可以看下MethodBeforeAdviceAdapter 的逻辑,就是MethodBeforeAdvice时,封装成MethodBeforeAdviceInterceptor(实现了MethodInterceptor接口)进行返回。后续会有接口进行调用MethodInterceptor接口的方法。
//MethodBeforeAdviceAdapter
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {
@Override
public boolean supportsAdvice(Advice advice) {
return (advice instanceof MethodBeforeAdvice);
}
@Override
public MethodInterceptor getInterceptor(Advisor advisor) {
MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
return new MethodBeforeAdviceInterceptor(advice);
}
}
在proceed中就是通过递归调用的方式进行MethodInterceptor的拦截,当MethodInterceptor执行完后,最后会执行invokeJoinpoint方法,也就是会调用真正要调用的方法。我们从前面得知MethodInterceptor实际就是MethodBeforeAdviceInterceptor,这里的invoke参数为this(ReflectiveMethodInvocation实现了MethodInvocation接口,MethodInvocation接口继承了Joinpoint接口,Joinpoint提供了proceed方法)
//ReflectiveMethodInvocation#proceed
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
// 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);
}
在MethodBeforeAdviceInterceptor的逻辑中,会先调用advice的before接口,然后调用MethodInvocation的proceed,其实就是会回到ReflectiveMethodInvocation的proceed方法中
//MethodBeforeAdviceInterceptor#invoke
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
return mi.proceed();
}
这里的advice其实就是AspectJMethodBeforeAdvice,内部实际上调用父类的方法。会通过反射进行调用拦截的方法。aspectJAdviceMethod就是拦截的方法,this.aspectInstanceFactory.getAspectInstance()就是定义拦截方法的类。到此处我们了解到了拦截方法的执行。
//AbstractAspectJAdvice#invokeAdviceMethodWithGivenArgs
protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
try {
ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
// TODO AopUtils.invokeJoinpointUsingReflection
return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
}
}
回到ReflectiveMethodInvocation的invokeJoinpoint,其实就是调用真正要调用的方法,内部会通过AopUtils工具类提供的方法执行。逻辑其实也很简单,就是通过反射进行方法调用。
public static Object invokeJoinpointUsingReflection(@Nullable Object target, Method method, Object[] args)
throws Throwable {
// Use reflection to invoke the method.
try {
ReflectionUtils.makeAccessible(method);
return method.invoke(target, args);
}
//...
}
3.3.2 DynamicAdvisedInterceptor
DynamicAdvisedInterceptor的逻辑和JdkDynamicAopProxy的逻辑类似,这里就不重复说明。
4. 参考资料
- Spring 源码分支5.1.x
- 《Spring 源码解析》