1.replaced-method 子元素
方法替换: 可以在运行时用新的方法替换现有的方法,与之前的 look-up不同的是replace-method 不但可以动态地替换返回的实体bean,而且可以动态的更改原有方法的逻辑,
1.1.1使用实例:
首先创建一个Bean完成某项业务
1 public class Person { 2 3 public void show() { 4 System.out.println("I am Person .."); 5 } 6 }
在运营一段时间后需要改变原有的逻辑
1 import java.lang.reflect.Method; 2 3 import org.springframework.beans.factory.support.MethodReplacer; 4 5 public class ReplacedClass implements MethodReplacer { 6 7 @Override 8 public Object reimplement(Object obj, Method method, Object[] args) throws Throwable { 9 System.out.println(obj); 10 System.out.println(method.getName()); 11 System.out.println("I am replacer..."); 12 return null; 13 } 14 15 }
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-2.5.xsd"> <bean id="person" class="test.replaced.Person"> <replaced-method name="show" replacer="replace"></replaced-method> </bean> <bean id="replace" class="test.replaced.ReplacedClass"> </bean> </beans>
测试类
1 public class Main { 2 3 public static String XML_PATH = "test\replaced\applicationContxt.xml"; 4 5 public static void main(String[] args) { 6 try { 7 Resource resource = new ClassPathResource(XML_PATH); 8 XmlBeanFactory beanFactory = new XmlBeanFactory(resource); 9 Person bean = (Person) beanFactory.getBean("person"); 10 System.out.println(bean); 11 bean.show(); 12 } 13 catch (Exception e) { 14 e.printStackTrace(); 15 } 16 } 17 }
好了,运行测试就可以看到我们预期的结果了,控制台成功打印出
test.replaced.Person$$EnhancerBySpringCGLIB$$7f7813f2@1a69b07
test.replaced.Person$$EnhancerBySpringCGLIB$$7f7813f2@1a69b07
show
I am replacer...
知道了这个子元素的用法,我们再来看看Spring是怎么对这个元素进行提取的.
BeanDefinitionParserDelegate.java
1 /** 2 * Parse replaced-method sub-elements of the given bean element. 3 */ 4 public void parseReplacedMethodSubElements(Element beanEle, MethodOverrides overrides) { 5 NodeList nl = beanEle.getChildNodes(); 6 for (int i = 0; i < nl.getLength(); i++) { 7 Node node = nl.item(i); 8 //仅当在Spring默认Bean的子元素下, 9 //且为<lookup-method 时有效 10 if (isCandidateElement(node) && nodeNameEquals(node, REPLACED_METHOD_ELEMENT)) { 11 Element replacedMethodEle = (Element) node; 12 // 提取要替换的旧的方法 13 String name = replacedMethodEle.getAttribute(NAME_ATTRIBUTE); 14 // 提取对应的新的替换的方法 15 String callback = replacedMethodEle.getAttribute(REPLACER_ATTRIBUTE); 16 ReplaceOverride replaceOverride = new ReplaceOverride(name, callback); 17 // Look for arg-type match elements. 18 List<Element> argTypeEles = DomUtils.getChildElementsByTagName( 19 replacedMethodEle, ARG_TYPE_ELEMENT); 20 for (Element argTypeEle : argTypeEles) { 21 String match = argTypeEle.getAttribute(ARG_TYPE_MATCH_ATTRIBUTE); 22 // 记录参数 23 match = (StringUtils.hasText(match) ? match 24 : DomUtils.getTextValue(argTypeEle)); 25 if (StringUtils.hasText(match)) { 26 replaceOverride.addTypeIdentifier(match); 27 } 28 } 29 replaceOverride.setSource(extractSource(replacedMethodEle)); 30 overrides.addOverride(replaceOverride); 31 } 32 } 33 }
我们可以看到,无论是lookup-method 还是 replace-method 都是构造了一个methodOverride ,并且最终记录在AbstractBeanDefinition 中的 methodOerrides 属性当中.
而这个属性如何使用,我们后续再继续研究.