Spring MethodOverride

  • Author: HuiFer
  • 源码阅读仓库: SourceHot-spring

  • org.springframework.beans.factory.support.MethodOverride

    • org.springframework.beans.factory.support.LookupOverride
    • org.springframework.beans.factory.support.ReplaceOverride
  • org.springframework.beans.factory.support.MethodOverrides

MethodOverride

  • MethodOverride 方法重载类

MethodOverride定义了下面三个属性

  1. 方法名称
  2. 是否重载
  1. public abstract class MethodOverride implements BeanMetadataElement {
  2. /**
  3. * 方法名称
  4. */
  5. private final String methodName;
  6. /**
  7. * 是否重载
  8. */
  9. private boolean overloaded = true;
  10. /**
  11. * 源
  12. */
  13. @Nullable
  14. private Object source;
  15. }
  • 定义了一个抽象方法, 交由子类实现
  1. public abstract boolean matches(Method method);

类图

MethodOverride

  • 在 Spring 中有两种可以重写的机制(XML)

    1. lookup-method 标签

      1. <lookup-method name="" bean=""/>
    2. replaced-method 标签

      1. <replaced-method name="" replacer=""/>

相对应的两个类如类图所示

LookupOverride

  • org.springframework.beans.factory.support.LookupOverride
  • lookup-method 标签对应的实体对象

属性列表

  1. beanName
  2. method
  1. @Nullable
  2. private final String beanName;
  3. @Nullable
  4. private Method method;

matches

比较方法

  1. method 是否直接相等
  2. method 名称是否相同
  3. 是否需要重载
  4. 是不是 ABSTRACT 方法
  5. 参数列表长度是否等于 0
  1. @Override
  2. public boolean matches(Method method) {
  3. if (this.method != null) {
  4. // 通过 equals 判断
  5. return method.equals(this.method);
  6. }
  7. else {
  8. // 1. method 名称是否相同
  9. // 2. 是否需要重载
  10. // 3. 是不是 ABSTRACT 方法
  11. // 4. 参数列表长度是否等于0
  12. return (method.getName().equals(getMethodName()) && (!isOverloaded() ||
  13. Modifier.isAbstract(method.getModifiers()) || method.getParameterCount() == 0));
  14. }
  15. }

ReplaceOverride

  • org.springframework.beans.factory.support.ReplaceOverride
  1. /**
  2. * 实现 MethodReplacer 接口的bean name
  3. * @see MethodReplacer
  4. */
  5. private final String methodReplacerBeanName;
  6. /**
  7. * 标签 arg-type 数据
  8. */
  9. private final List<String> typeIdentifiers = new LinkedList<>();
  • 一个例子
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xmlns="http://www.springframework.org/schema/beans"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
  5. <bean id="apple" class="org.source.hot.spring.overview.ioc.bean.lookup.Apple">
  6. <replaced-method replacer="methodReplacerApple" name="hello" >
  7. <arg-type>String</arg-type>
  8. </replaced-method>
  9. </bean>
  10. <bean id="methodReplacerApple" class="org.source.hot.spring.overview.ioc.bean.lookup.MethodReplacerApple">
  11. </bean>
  12. </beans>

methodReplacerBeanName 对应org.springframework.beans.factory.support.MethodReplacer 的实现类

typeIdentifiers 对应标签 arg-type 的属性值

构造方法

  1. public ReplaceOverride(String methodName, String methodReplacerBeanName) {
  2. super(methodName);
  3. Assert.notNull(methodName, "Method replacer bean name must not be null");
  4. this.methodReplacerBeanName = methodReplacerBeanName;
  5. }

methodName 通过父类进行设置

matches

  1. @Override
  2. public boolean matches(Method method) {
  3. // 方法名称是否相同
  4. if (!method.getName().equals(getMethodName())) {
  5. return false;
  6. }
  7. // 是否重载
  8. if (!isOverloaded()) {
  9. // Not overloaded: don't worry about arg type matching...
  10. return true;
  11. }
  12. // If we get here, we need to insist on precise argument matching...
  13. // 类型标识数量是否和参数列表是否不相同
  14. if (this.typeIdentifiers.size() != method.getParameterCount()) {
  15. return false;
  16. }
  17. // 获取参数类型列表
  18. Class<?>[] parameterTypes = method.getParameterTypes();
  19. for (int i = 0; i < this.typeIdentifiers.size(); i++) {
  20. String identifier = this.typeIdentifiers.get(i);
  21. // 判断 方法参数的类型是否在类型标识列表中
  22. if (!parameterTypes[i].getName().contains(identifier)) {
  23. return false;
  24. }
  25. }
  26. return true;
  27. }

MethodOverrides

  • org.springframework.beans.factory.support.MethodOverrides

  • 重载方法对象

  • 存储所有重载的方法列表(set 结构)

  1. private final Set<MethodOverride> overrides = new CopyOnWriteArraySet<>();

几个方法

  1. 添加 MethodOverride

    1. public void addOverride(MethodOverride override) {
    2. this.overrides.add(override);
    3. }
    4. public void addOverrides(@Nullable MethodOverrides other) {
    5. if (other != null) {
    6. this.overrides.addAll(other.overrides);
    7. }
    8. }
  2. 获取 MethodOverride

    1. @Nullable
    2. public MethodOverride getOverride(Method method) {
    3. MethodOverride match = null;
    4. for (MethodOverride candidate : this.overrides) {
    5. if (candidate.matches(method)) {
    6. match = candidate;
    7. }
    8. }
    9. return match;
    10. }