MethodOverrides方法的覆盖源码分析
如下xml配置:
<bean id="getBeanTest" class="springSourseAnalyes.GetBeanTest"
lazy-init="true"> <lookup-method name="getBean" bean="stu" /> </bean> <bean
id="stu" class="springSourseAnalyes.Student" lazy-init="true"/> <bean
id="teacher" class="springSourseAnalyes.Teacher" /> <bean id="testChangeMethod"
class="springSourseAnalyes.TestChangeMethod"> <replaced-method name="chanageMe"
replacer="replacer" /> </bean> <bean id="replacer"
class="springSourseAnalyes.TestMethodReplcer"/>
抽象类GetBeanTest代码:
package springSourseAnalyes; public abstract class GetBeanTest { public void
showMe(){ getBean().showMe(); } abstract User getBean(); }
User类和Teacher类代码:
package springSourseAnalyes; public class User { void showMe(){
System.out.println("i am user"); } } package springSourseAnalyes; public class
Teacher extends User{ @Override void showMe() { // TODO Auto-generated method
stub System.out.println("i am Teacher"); } }
其实MethodOverrides的作用就是在spring配置中存在lookup-mehtod和rreplace-method的,而这两个配置在加载xml的时候就会统一存放在BeanDefinition中的methodOverrides属性里。
查看源码AbstractAutowireCapableBeanFactory的创建bean的方法create:
这时候GetBeanTest类已经是class类,开始调用准备方法的覆盖,继续进入方法prepareMethosOverrides()。
查看源码AbstractBeanDefinition
遍历MethodOverrides,对于一个方法的匹配来j讲,如果一个l类中存在若干个重载方法,那么,在函数调用以及增强的时候还需要根据参数类型进行匹配,来最终确认当前调用的到底是哪个函数,但是,spring将一部分匹配工作在这里完成了,如果当前类中的方法只有一个,那么就设置重载该方法没有被重载,这样在后续调用的时候便可以直接使用找到的方法,而不需要j进行方法的参数匹配了,而且还可以提前对方法存在性进行验证。
进入帮助类ClassUtils
使用递归方式来遍历当前类的方法,是否与methodName匹配,如果匹配则count计数器自增,然后对当前类的接口进行遍历匹配操作,然后在对当前类的超类进行遍历匹配。返回计数器。
递归先后遍历:1、当前类方法遍历。2、当前类接口的方法遍历。3、当前类超类的方法遍历。
最终返回的是一个对当前类的代理类。通过CGLIB生成不同的代理类。
其中owner 是BeanFactory 接口、beanDefinition为RootBeanDefinition类
当调用方法时,就会被拦截调用intercept方法,获取到该方法的替换者bean类,然后在通过owner.getBean来获取bean类,然后真正调用被替换的方法。