前面咱已经知道,最终 bean 的初始化会被 BeanPostProcessor
的 postProcessAfterInitialization
处理,进入到 AnnotationAwareAspectJAutoProxyCreator
的 postProcessAfterInitialization
方法中,它又要调用 wrapIfNecessary
方法来尝试创建代理,咱深入方法内部来研究。
1. wrapIfNecessary
复制 protected Object wrapIfNecessary( Object bean , String beanName , Object cacheKey) {
// 判断决定是否是不会被增强的 bean
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 );
// 创建代理对象的动作
// 注意此处它创建了一个SingletonTargetSource,将bean包装起来了
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;
}
这里前面的筛选过滤懂还是蛮简单的,咱就不关注了,重点是关注一下中间的获取增强器,以及下面的创建代理对象,两个动作。
1.1 getAdvicesAndAdvisorsForBean
这个方法很明显是根据当前正在初始化的 bean ,去匹配获取能切入的增强器,它的源码看上去不复杂:
复制 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 ();
}
毫无疑问,核心逻辑是 findEligibleAdvisors
方法咯,继续往里走:
复制 protected List< Advisor > findEligibleAdvisors( Class<?> beanClass , String beanName) {
// 获取所有增强器
List < Advisor > candidateAdvisors = findCandidateAdvisors() ;
// 筛选出可以切入当前bean的增强器
List < Advisor > eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors , beanClass , beanName) ;
// 添加额外的增强器
extendAdvisors(eligibleAdvisors) ;
if ( ! eligibleAdvisors . isEmpty ()) {
// 增强器排序
eligibleAdvisors = sortAdvisors(eligibleAdvisors) ;
}
return eligibleAdvisors;
}
这个方法就很复杂了,尽管只有几行,但都是封装好的方法,咱一个一个的展开来看。
1.1.1 findCandidateAdvisors
又回到 AnnotationAwareAspectJAutoProxyCreator
了:
复制 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;
}
可以发现,这个方法只是把 SpringFramework 原生的 AOP 增强器,以及 AspectJ 形式封装的增强器都拿出来,仅此而已。
1.1.2 findAdvisorsThatCanApply
所有的增强器获取到之后,下面要去匹配可以切入到当前 bean 的增强器了,咱进入到 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 );
}
}
这个方法又交给 AopUtils
执行了,咱继续往里看:
复制 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;
}
可以发现,整体逻辑分为两个部分,前面是针对引介通知的增强器作筛选,后面是普通的方法通知封装的增强器。
上面的引介增强器的匹配咱就不多研究了,本来平时就用得少,咱主要还是来看对于方法的增强器,它是如何去做匹配的。进入到下面的 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.
// SpringFramework也不知道咋搞了,于是就直接让它可以匹配
return true ;
}
}
从这个逻辑中就可以看出,底层针对不同种的增强器,分别会有不同的判断逻辑。对于方法增强器的判断,它又调用了下面的重载方法:
复制 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 ) {
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) {
// 逐个判断每个方法是否能被当前切入点表达式切入,切入则立即返回true
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 ;
}
整体思路还是很清晰的吧,我们要理解的核心部分,是下面的这个双重循环,以此就能判断出来切入点表达式是否能对当前 bean 进行增强了。
Debug 下来,最终发现可以给 OrderService
匹配到的增强器一共有 2 个:( FinanceService
就不看了,因为咱一开始学习的时候,就是拿它举的例子,所有的通知方法都切入它了)
1.1.3 extendAdvisors
这个方法看上去蛮不起眼的,不过小伙伴们有自己 Debug 的话,过了这个方法会发现 eligibleAdvisors
集合中多了一个增强器:
诶?它自己还有偷偷添加增强器啊,那咱看看它干了些啥:
1.1.3.1 extendAdvisors方法的小动作
复制 protected void extendAdvisors( List< Advisor > candidateAdvisors) {
AspectJProxyUtils . makeAdvisorChainAspectJCapableIfNecessary (candidateAdvisors);
}
// AspectJProxyUtils
public static boolean makeAdvisorChainAspectJCapableIfNecessary( List< Advisor > advisors) {
// Don't add advisors to an empty list; may indicate that proxying is just not required
if ( ! advisors . isEmpty ()) {
boolean foundAspectJAdvice = false ;
for ( Advisor advisor : advisors) {
// Be careful not to get the Advice without a guard, as this might eagerly
// instantiate a non-singleton AspectJ aspect...
if ( isAspectJAdvice(advisor) ) {
foundAspectJAdvice = true ;
break ;
}
}
// 发现有AspectJ包装的增强器,则添加一个ExposeInvocationInterceptor
if (foundAspectJAdvice && ! advisors . contains ( ExposeInvocationInterceptor . ADVISOR )) {
advisors . add ( 0 , ExposeInvocationInterceptor . ADVISOR );
return true ;
}
}
return false ;
}
逻辑不算复杂,它这个方法的关键是,判断当前可用的增强器中有没有 AspectJ 类型的,如果有的话,那就在整个增强器的列表的最前面,添加一个 ExposeInvocationInterceptor.ADVISOR
。
1.1.3.2 ADVISOR是个啥?
那这个 ADVISOR
又是个啥子?咱继续往里走:
复制 public static final ExposeInvocationInterceptor INSTANCE = new ExposeInvocationInterceptor() ;
public static final Advisor ADVISOR = new DefaultPointcutAdvisor(INSTANCE) {
@ Override
public String toString () {
return ExposeInvocationInterceptor . class . getName () + ".ADVISOR" ;
}
};
哦?合着它是个对所有 bean 都生效的增强器呗?传入的这个 INSTANCE
很明显是单例的设计,那到头来核心还是这个 ExposeInvocationInterceptor
本身。
1.1.3.3 ExposeInvocationInterceptor又是个啥?
那新的问题就来了:ExposeInvocationInterceptor
这玩意的作用是什么呢?
翻开源码的核心 invoke 方法,发现它在向当前线程的 ThreadLocal
中放入了当前正在执行的代理对象的方法执行包装:
复制 private static final ThreadLocal < MethodInvocation > invocation =
new NamedThreadLocal <>( "Current AOP method invocation" );
public Object invoke( MethodInvocation mi) throws Throwable {
MethodInvocation oldInvocation = invocation . get ();
invocation . set (mi);
try {
return mi . proceed ();
}
finally {
invocation . set (oldInvocation);
}
}
每次都在增强器链的第一个执行,并且放入 ThreadLocal
变量中,那这意图就很明显了:它可以让后面的增强器都拿到当前正在执行的 MethodInvocation
。至于哪里会用到 MethodInvocation
,咱目前还没有遇到,后面如果遇到了咱再留意。
或许会有小伙伴产生一个小小的疑惑:那你放就放呗, MethodInvocation oldInvocation = invocation.get();
这个操作是啥意思?原本就没有,你 get
个什么劲呢???
哎?真的没有吗?如果是一个 AOP 代理对象,调用了另外一个 AOP 代理对象的话,这个过程是在一个线程中执行的呀,那第二个代理对象的方法被调用时,是不是也会经过 ExposeInvocationInterceptor
呢?那是不是从 ThreadLocal
中就可以取出 MethodInvocation
了呢?所以小伙伴们一定要多想一层呀,多实践多思考才会更进步 ~
1.2 createProxy
上面结束之后,所有的增强器也就都准备好了,接下来就是创建代理对象的部分了,咱进入 createProxy
中:
复制 protected Object createProxy( Class<?> beanClass , @ Nullable String beanName ,
@ Nullable Object [] specificInterceptors , TargetSource targetSource) {
// 记录被代理bean的原始类型
if ( this . beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils . exposeTargetClass ((ConfigurableListableBeanFactory) this . beanFactory , beanName , beanClass);
}
// 代理工厂的初始化
ProxyFactory proxyFactory = new ProxyFactory() ;
proxyFactory . copyFrom ( this );
// 根据AOP的设计,决定是否强制使用Cglib
if ( ! proxyFactory . isProxyTargetClass ()) {
if ( shouldProxyTargetClass(beanClass , beanName) ) {
// Cglib动态代理直接记录被代理bean的所属类即可
proxyFactory . setProxyTargetClass ( true );
}
else {
// 解析被代理bean所属类的所有实现的接口
evaluateProxyInterfaces(beanClass , proxyFactory) ;
}
}
// 1.2.1 构造整合所有增强器
Advisor [] advisors = buildAdvisors(beanName , specificInterceptors) ;
proxyFactory . addAdvisors (advisors);
proxyFactory . setTargetSource (targetSource);
customizeProxyFactory(proxyFactory) ;
proxyFactory . setFrozen ( this . freezeProxy );
if ( advisorsPreFiltered() ) {
proxyFactory . setPreFiltered ( true );
}
// 1.2.2 创建代理对象
return proxyFactory . getProxy ( getProxyClassLoader() );
}
到了这里,咱就可以发现,这里面的逻辑已经基本上处理的差不多了,核心的动作就两个:收集整理要织入到目标对象的通知增强器 ,以及创建代理对象 。前面的那些小细节小伙伴们可以自行研究,相对都是蛮简单的,小册带小伙伴们关注的是这两部分的核心逻辑。
1.2.1 buildAdvisors
源码不算长,里面有一段日志的部分,小册在这里删掉了,咱只关心核心逻辑:
复制 protected Advisor [] buildAdvisors(@ Nullable String beanName , @ Nullable Object [] specificInterceptors) {
// Handle prototypes correctly...
// 这个地方是适配Spring原生AOP的MethodInterceptor,感兴趣的小伙伴可自行研究
Advisor [] commonInterceptors = resolveInterceptorNames() ;
List < Object > allInterceptors = new ArrayList <>();
if (specificInterceptors != null ) {
allInterceptors . addAll ( Arrays . asList (specificInterceptors));
// 组合原生的方法拦截器,共同作为AOP的通知织入
if ( commonInterceptors . length > 0 ) {
if ( this . applyCommonInterceptorsFirst ) {
allInterceptors . addAll ( 0 , Arrays . asList (commonInterceptors));
}
else {
allInterceptors . addAll ( Arrays . asList (commonInterceptors));
}
}
}
// logger ......
Advisor [] advisors = new Advisor [ allInterceptors . size ()];
for ( int i = 0 ; i < allInterceptors . size (); i ++ ) {
// 此处有一个原生AOP的适配动作
advisors[i] = this . advisorAdapterRegistry . wrap ( allInterceptors . get (i));
}
return advisors;
}
上面整合 SpringFramework 原生 AOP 的内容咱小册就不提及了,毕竟是很久之前用的东西了,咱现在都是 AspectJ 的。在最下面,它有一个 advisorAdapterRegistry.wrap
的方法调用,它是干嘛的呢?咱可以去瞅一眼:
复制 public Advisor wrap( Object adviceObject) throws UnknownAdviceTypeException {
// Advisor增强器可以直接返回
if (adviceObject instanceof Advisor) {
return (Advisor) adviceObject;
}
// 不支持非Advice的类型
if ( ! (adviceObject instanceof Advice)) {
throw new UnknownAdviceTypeException(adviceObject) ;
}
Advice advice = (Advice) adviceObject;
// MethodInterceptor的支持
if (advice instanceof MethodInterceptor) {
// So well-known it doesn't even need an adapter.
return new DefaultPointcutAdvisor(advice) ;
}
// AdvisorAdapter的支持
for ( AdvisorAdapter adapter : this . adapters ) {
// Check that it is supported.
if ( adapter . supportsAdvice (advice)) {
return new DefaultPointcutAdvisor(advice) ;
}
}
throw new UnknownAdviceTypeException(advice) ;
}
注意这个方法的参数和返回值:它可以是任意类型的入参,但返回的一定是 Advisor
,这也就呼应了 wrap
方法的含义:将可以支持转换 / 包装为 **Advisor**
类型的对象适配成 **Advisor**
。至于它可以适配的类型,内置的只有 MethodInterceptor
和几种原生的 Advice
(前面 Spring 原生 AOP 中提到的),不过它提供了一个 AdvisorAdapter
的接口,供我们扩展使用,以此来支持自定义的 Advice
类型。不过我们几乎都没有这么做的,所以这部分小伙伴们知道一下就可以了,没必要深究。
1.2.2 proxyFactory.getProxy
下面就是真正创建代理对象的逻辑了,这个方法又分为两个部分:
复制 public Object getProxy(@ Nullable ClassLoader classLoader) {
return createAopProxy() . getProxy (classLoader);
}
咱一一来看。
1.2.2.1 createAopProxy
复制 protected final synchronized AopProxy createAopProxy() {
if ( ! this . active ) {
activate() ;
}
return getAopProxyFactory() . createAopProxy ( this );
}
private void activate() {
this . active = true ;
for ( AdvisedSupportListener listener : this . listeners ) {
listener . activated ( this );
}
}
上面有一个监听器的通知动作,由于这个动作涉及到的监听器 AdvisedSupportListener
只在 ProxyCreatorSupport
这个类中使用,咱们开发也基本不会碰这些东西,所以这个咱可以跳过了,关键的还是下面 getAopProxyFactory().createAopProxy(this);
的执行。
getAopProxyFactory
方法返回的是当前 ProxyCreatorSupport
的成员 aopProxyFactory
,借助 Debug 可以发现它的类型是 DefaultAopProxyFactory
。
进入到它的 createAopProxy
方法中,终于发现了咱熟悉的 jdk 、Cglib 动态代理的字眼了:
复制 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动态代理了的代理对象
// 则使用jdk动态代理
if ( targetClass . isInterface () || Proxy . isProxyClass (targetClass)) {
return new JdkDynamicAopProxy(config) ;
}
// 否则使用Cglib动态代理
return new ObjenesisCglibAopProxy(config) ;
}
else {
return new JdkDynamicAopProxy(config) ;
}
}
至此,咱就知道,使用 jdk 动态代理,还是 Cglib 动态代理,底层的选择是在这里决定的。
1.2.2.2 AopProxy#getProxy
创建完 AopProxy
后,下面就是创建代理对象的动作了,咱以 JdkDynamicAopProxy
为例进去看一下:
复制 public Object getProxy(@ Nullable ClassLoader classLoader) {
// logger ......
Class < ? >[] proxiedInterfaces = AopProxyUtils . completeProxiedInterfaces ( this . advised , true );
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces) ;
// jdk动态代理的API
return Proxy . newProxyInstance (classLoader , proxiedInterfaces , this );
}
看,最底下,咱最最熟悉的 Proxy.newProxyInstance
方法出现了!!!所以由此咱就可以体会到,代理对象的底层创建还是依赖 jdk 动态代理,或者 Cglib 动态代理的核心 API 呀!
至于 Cglib 动态代理的创建,咱就不特别深入了,咱注意一下中间的核心部分即可:
复制 // ......
// 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 ClassLoaderAwareGeneratorStrategy(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) ;
// ......
可以看到,这也是对 Cglib 中的 Enhancer
进行操作,核心的思路是不变的,只是框架比咱考虑的更多罢了。
OK ,到此为止,代理对象也就成功创建了,整个 AOP 通知织入的流程也就结束了。