本方法我们需要关注对Enhancer实例的配置,有如下关注点:
- 通过它增强的每个类都实现了EnhancedConfiguration接口,并且它还是BeanFactoryAware的子接口
- 统一实现接口,这和Spring AOP创建代理是不是如出一辙?想一想
- 实现了BeanFactoryAware接口,这样Spring在创建代理类实例的时候会给注入BeanFactory
- 使用SpringNamingPolicy策略来生成类名称。这就是解释了为何代理类的名你都能看到BySpringCGLIB字样
- 对于代理最为重要的当属过滤器/拦截器org.springframework.cglib.proxy.Callback,它们是实现功能的核心。配置此增强器时设置了CALLBACK_FILTER共三个拦截器
关于CALLBACK_FILTER,我们发现在类ConfigurationClassEnhancer最开始处就申明了三个拦截器放进去了:
ConfigurationClassEnhancer: private static final Callback[] CALLBACKS = new Callback[] { new BeanMethodInterceptor(), new BeanFactoryAwareMethodInterceptor(), NoOp.INSTANCE };
如果说前面都是做准备工作,那么拦截器才是运行期真正干活的“人”了。它能够解答我们今天的疑问~
拦截器分析
什么是动态代理?用通俗的话理解就是:代理的核心逻辑就是依赖于拦截器实现的,可见拦截器(也叫增强)之于代理类是何等重要。
上面的三个拦截器中,NoOp.INSTANCE代表什么都没做,因此我们只需要关注前两个。他俩均是MethodInterceptor接口的实现类,均实现了intercept()方法来做具体的拦截操作(他俩均是私有静态内部类哟)。
说明:本文的两个case用第一个拦截器即可解释,鉴于第二个拦截器非常的复杂,所以我把它放在下篇文章详解(已写得差不多了,因为太复杂,篇幅比本文还长)
BeanFactoryAwareMethodInterceptor
顾名思义,它表示的是BeanFactoryAware方法的拦截器,所以靠猜应该能猜到它拦截的是setBeanFactory(beanFactory)方法。
说明:Spring所有的拦截器实现的拦截都是方法级别的。虽然也支持构造器的拦截,但并没有内置实现,需要使用者自行扩展(比较复杂,一般并无使用场景)
相较于下文要讲的第二个拦截器,这个拦截器比较简单。但是它实现的功能可不简约哦,因为它能够解释文首提出的两个case,让你谈薪更有底气。
既然是拦截器,就应该按如下两步去了解它:执行时机 + 做了何事。
执行时机
执行时机决定了增强逻辑何时执行,毕竟一般来说都不可能是增强所有的嘛。
BeanFactoryAwareMethodInterceptor: // 当执行到setBeanFactory(xxx)方法时匹配成功 @Override public boolean isMatch(Method candidateMethod) { return isSetBeanFactory(candidateMethod); } // 此方法标记为public static 是因为下面这个拦截器也会用到 public static boolean isSetBeanFactory(Method candidateMethod) { return (candidateMethod.getName().equals("setBeanFactory") && candidateMethod.getParameterCount() == 1 && BeanFactory.class == candidateMethod.getParameterTypes()[0] && BeanFactoryAware.class.isAssignableFrom(candidateMethod.getDeclaringClass())); }
我们知道setBeanFactory()方法是由Spring容器在初始化Bean时回调调用的,而代理类实现了EnhancedConfiguration接口(间接实现了BeanFactoryAware接口),所以该拦截器的执行时机为:在Spring初始化代理类实例时执行拦截。
说明:isSetBeanFactory()判断方法做这么“复杂”主要是为了容错,“担心”你自己定义了一个名为setBeanFactory的方法而“搞错了”。
做了何事
作为一个拦截器,增强逻辑才是它的核心。
BeanFactoryAwareMethodInterceptor: @Override @Nullable public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { // 找到本类(代理类)里名为`$$beanFactory`的字段 // 若没找到直接报错。若找到了此字段,就给此字段赋值 Field field = ReflectionUtils.findField(obj.getClass(), BEAN_FACTORY_FIELD); Assert.state(field != null, "Unable to find generated BeanFactory field"); field.set(obj, args[0]); // 如果用户类(也就是你自己定义的类)自己实现了该接口,那么别担心,也会给你赋值上 if (BeanFactoryAware.class.isAssignableFrom(ClassUtils.getUserClass(obj.getClass().getSuperclass()))) { return proxy.invokeSuper(obj, args); } return null; }
从执行时机知道了,它拦截的是setBeanFactory()
方法的执行。所以这里的Method就代表的是setBeanFactory()
方法,Object[] args
的值是当前容器的BeanFactory工厂(注意理解这句话)实例。
此拦截器增强完成后,结果截图如下:
好了,介绍到这里本文就先告一段落。如果你是认真的看完了本文的分析,那么现在你再“回到顶部”理解那两个case的结果,你就豁然开朗了。
建议一定弄懂,我觉得已经很明朗了,所以就不再废话。若有不清楚,可以下方扫码加我微信私聊我吧(或者文末留言)
总结
又是一篇关于Spring配置类的长文,只希望对你有帮助才有意义。最为核心的两个增强/拦截器,迫于篇幅和读者的脑力(毕竟理解起来还是比较费劲的),今天只讲一个。我把另外一个更为重要、更为复杂、更为多金的部分放在了下文专文阐述,你可关注我公众号保持“收看”。