我们先来java类
xml实现
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="testChangeMethod" class="com.spring_1_100.test_41_50.test42.TestChangeMethod"> <replaced-method name="changeMe" replacer="replacer"> </bean> <bean id="replacer" class="com.spring_1_100.test_41_50.test42.TestMethodReplacer"> </beans>【结果输出】 我替换了原有的方法
在这一篇博客中【https://blog.csdn.net/quyixiao/article/details/108368581】,我们分析了lookup-method标签的源码实现,而replaced-method的实现,大同小异,这里我们挑选一些关键部分源码分析一下 首先是代码解析部分:
/* 我们可以看到,无论是look-up还是replace-method都是构造了一个MethodOverride,并最终记录在了AbstractBeanDefinition中的methodOverrides属性中 * ,而这个属性如何使用以完成它所提供的功能呢,这个要在后续的章节中进行详细的介绍 */ public void parseReplacedMethodSubElements(Element beanEle, MethodOverrides overrides) { NodeList nl = beanEle.getChildNodes(); for (int i = 0; i < nl.getLength(); i++) { Node node = nl.item(i); // 仅当在Spring默认的bean的子元素下且为 replace-method时有效 if (isCandidateElement(node) && nodeNameEquals(node, REPLACED_METHOD_ELEMENT)) { Element replacedMethodEle = (Element) node; // 提取要替换的旧的方法 String name = replacedMethodEle.getAttribute("name"); // 提取对应的新的替换方法 String callback = replacedMethodEle.getAttribute("replacer"); ReplaceOverride replaceOverride = new ReplaceOverride(name, callback); // Look for arg-type match elements. List<Element> argTypeEles = DomUtils.getChildElementsByTagName(replacedMethodEle, "arg-type"); for (Element argTypeEle : argTypeEles) { // 记录参数 String match = argTypeEle.getAttribute("match"); match = (StringUtils.hasText(match) ? match : DomUtils.getTextValue(argTypeEle)); if (StringUtils.hasText(match)) { replaceOverride.addTypeIdentifier(match); } } replaceOverride.setSource(extractSource(replacedMethodEle)); overrides.addOverride(replaceOverride); } } }在这个ReplaceOverride类的实例化过程中,将xml解析出来的name存储到methodName属性中,将xml中的replacer存储到了methodReplacerBeanName属性中。这个属性后面在cglib代理的时候会用到。
在replaced-method分析中,对于TestChangeMethod这个实例的创建过程,同样的是使用了cglib代理, 从图中我们看到,对于changeMe()方法,最后accept()方法返回的是2,2对应的是
private static final Class<?>[] CALLBACK_TYPES = new Class<?>[] {NoOp.class, LookupOverrideMethodInterceptor.class, ReplaceOverrideMethodInterceptor.class};ReplaceOverrideMethodInterceptor这个拦截器类,因此,根据cglib 特性 ,在调用TestChangeMethod 的 changeMe() 方法时,会被ReplaceOverrideMethodInterceptor的intercept方法拦截到,因此我们来看看ReplaceOverrideMethodInterceptor类
通过上面的cglib拦截,就调用到了我们实现了MethodReplacer接口的reimplement方法了。
@Override public Object reimplement(Object obj, Method method, Object[] args) throws Throwable { System.out.println("我替换了原有的方法"); return null; }本文github地址是 https://github.com/quyixiao/spring_tiny/blob/master/src/main/java/com/spring_1_100/test_41_50/test42
