Spring源码之:方法重写机制

611 阅读11分钟

1. 提出问题

假设有如下实体类:

public class SupplierBean {
    public Object getObject() {
        return "hello";
    }
}

spring.xml文件中配置该Bean:

<?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="supplierBean" class="com.xxx.SupplierBean"/>

</beans>

创建一个BeanFactory并获取该Bean,并打印其getObject()方法的结果:

public class Demo {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml");
        SupplierBean supplierBean = ctx.getBean("supplierBean", SupplierBean.class);
        
        // 显然,这里打印"hello"
        System.out.println(supplierBean.getObject());
    }
}

假设我们想要修改SupplierBean类的getObject()方法的返回值
最容易想到的做法是写一个SupplierBean的子类,并重写getObject()方法;但这种方式不是我们要讨论的
实际上,Spring提供了方法重写(即MethodOverride)机制,允许我们通过配置的方式来重写Bean的方法
Spring提供了LookupMethodReplacedMethod两种重写方式

需要注意的是,对于那些通过@Bean注解注册的Bean,方法重写机制是不会生效的
这是因为方法重写的信息需要存到BeanDefinition中,而Spring在将@Bean方法转成BeanDefinition时,忽略了方法重写机制

2. LookupMethod

这种方式只能修改方法的返回值,且只能返回Spring容器管理的Bean(可以是多例的,这种情况下,方法的返回值会不断变化)
因此,被LookupMethod方式重写的方法就等价于BeanFactorygetBean()方法
如果希望方法的返回值固定从容器中获取,则可以使用这种方式

2.1. 配置文件方式

修改配置文件,如下:

<?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,作为supplierBean的getObject()方法的返回值 -->
    <bean id="lookupBean" class="java.lang.String" factory-method="valueOf">
        <constructor-arg type="java.lang.Object" value="world" />
    </bean>

    <!-- 添加lookup-method标签,表示将该Bean的getObject()方法的返回值修改成lookupBean -->
    <bean id="supplierBean" class="com.xxx.SupplierBean" >
        <lookup-method name="getObject" bean="lookupBean" />
    </bean>

</beans>

在测试程序中打印获取到的Bean:

public class Demo {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml");
        SupplierBean supplierBean = ctx.getBean("supplierBean", SupplierBean.class);
        
        // 这里的supplierBean是个代理对象:com.xxx.SupplierBean$$EnhancerBySpringCGLIB$$ba7bf0f2@6ac13091
        System.out.println(supplierBean);
        
        // 打印"world"
        System.out.println(supplierBean.getObject());
    }
}

2.2. 注解方式

@Component
public class SupplierBean {

    /**
     * 注册一个lookupBean
     */
    @Bean
    public Object lookupBean() {
        return "world";
    }

    /**
     * 使用@Lookup注解,将当前方法的返回值改为lookupBean
     */
    @Lookup("lookupBean")
    public Object getObject() {
        return "hello";
    }
}
public class Demo {
    public static void main(String[] args) {
        ApplicationContext ctx = new AnnotationConfigApplicationContext(SupplierBean.class);
        SupplierBean supplierBean = ctx.getBean("supplierBean", SupplierBean.class);
        System.out.println(supplierBean);
        System.out.println(supplierBean.getObject());
    }
}

3. ReplacedMethod

这种方式的功能比LookupMethod方式更强大,且优先级更高;可以看作是JDK动态代理和Spring的结合
一方面,这种方式的增强逻辑和JDK动态代理类似
另一方面,这种方式的方法处理器会被配置成Bean,因此可以通过实现Aware接口等方式来获取更多信息

3.1. MethodReplacer

ReplacedMethod方式需要先自定义一个MethodReplacer组件,用于封装重写方法的实现逻辑:

public class MyMethodReplacer implements MethodReplacer {

    /**
     * 重写目标方法;本方法和JDK动态代理的InvocationHandler.invoke()方法类似
     *
     * @param obj    代理对象
     * @param method 被重写的方法
     * @param args   方法的参数
     */
    @Override
    public Object reimplement(Object obj, Method method, Object[] args) throws Throwable {
        
        // 打印代理对象,并返回自定义的数据
        System.out.println(obj);
        return "world";
    }
}

3.2. 配置文件方式

<?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">

    <!-- 将自定义的MethodReplacer注册为一个Bean -->
    <bean id="myMethodReplacer" class="com.xxx.MyMethodReplacer" />

    <!-- 添加replaced-method标签,表示重写该Bean的getObject()方法;重写逻辑放在myMethodReplacer中 -->
    <bean id="supplierBean" class="com.xxx.SupplierBean" >
        <replaced-method name="getObject" replacer="myMethodReplacer">
            <!-- 此外,replaced-method标签内还可以配置arg-type标签 -->
            <!-- 当有多个重载方法时,可以通过该标签来指定方法的参数类型,从而确定要重写哪个方法 -->
            <!-- <arg-type match="com.xxx.XxxClass" /> -->
            <!-- <arg-type>java.lang.String</arg-type> -->
        </replaced-method>
    </bean>

</beans>

测试程序及打印结果如下:

public class Demo {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml");
        SupplierBean supplierBean = ctx.getBean("supplierBean", SupplierBean.class);
        System.out.println(supplierBean);
        System.out.println(supplierBean.getObject());
    }
}
com.xxx.SupplierBean$$EnhancerBySpringCGLIB$$ba7bf0f2@16e7dcfd
com.xxx.SupplierBean$$EnhancerBySpringCGLIB$$ba7bf0f2@16e7dcfd
world

4. 源码解析:基本组件

4.1. InstantiationStrategy

AbstractAutowireCapableBeanFactory实现了createBean()方法,该方法负责创建Bean
创建Bean的过程主要包括:实例化Bean依赖注入调用init方法
其中,实例化Bean这一步是通过InstantiationStrategy组件来实现的
InstantiationStrategy组件在实例化Bean时,会判断该Bean是否有方法重写,如果有,则会创建该Bean的代理对象

注意,在实例化Bean时,可以通过无参构造器或有参构造器来创建;这里我们以无参构造器为例来讲解

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
        implements AutowireCapableBeanFactory {

    /** 
     * Bean的实例化策略
     */
    private InstantiationStrategy instantiationStrategy;

    /**
     * 通过无参构造器实例化Bean
     */
    protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
        try {
            Object beanInstance;
            
            // 调用instantiationStrategy的instantiate()方法实例化Bean
            // 这一步中,会判断该Bean是否有MethodOverride,如果有,则创建该Bean的代理对象
            beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this); // @Privileged
            
            BeanWrapper bw = new BeanWrapperImpl(beanInstance);
            initBeanWrapper(bw);
            return bw;
        } catch (Throwable ex) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
        }
    }
}

4.2. SimpleInstantiationStrategy

本类实现了InstantiationStrategy接口,主要负责直接实例化Bean:

public class SimpleInstantiationStrategy implements InstantiationStrategy {

    /**
     * 根据无参构造器来创建Bean实例
     */
    @Override
    public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
        
        // 如果该Bean没有MethodOverride,则直接通过无参构造器实例化该Bean
        if (!bd.hasMethodOverrides()) {
            
            // 下面这块代码是在获取该Bean的无参构造器
            Constructor<?> constructorToUse;
            synchronized (bd.constructorArgumentLock) {
                constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
                if (constructorToUse == null) {
                    final Class<?> clazz = bd.getBeanClass();
                    if (clazz.isInterface()) {
                        throw new BeanInstantiationException(clazz, "Specified class is an interface");
                    }
                    try {
                        constructorToUse = clazz.getDeclaredConstructor(); // @Privileged
                        bd.resolvedConstructorOrFactoryMethod = constructorToUse;
                    } catch (Throwable ex) {
                        throw new BeanInstantiationException(clazz, "No default constructor found", ex);
                    }
                }
            }
            
            // 根据构造器实例化Bean
            return BeanUtils.instantiateClass(constructorToUse);
        
        // 如果有MethodOverride,则需要创建Bean的代理对象
        } else {
            
            // instantiateWithMethodInjection()方法默认抛出UnsupportedOperationException异常,需要子类重写
            return instantiateWithMethodInjection(bd, beanName, owner);
        }
    }
}

4.3. CglibSubclassingInstantiationStrategy

本类继承自SimpleInstantiationStrategy,重写了instantiateWithMethodInjection()方法:

public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationStrategy {

    /**
     * 根据无参构造器创建Bean的代理对象
     */
    @Override
    protected Object instantiateWithMethodInjection(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner){
        return instantiateWithMethodInjection(bd, beanName, owner, null);
    }

    /**
     * 根据指定构造器创建Bean的代理对象;如果不指定构造器,则采用无参构造器
     */
    @Override
    protected Object instantiateWithMethodInjection(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
                                                    @Nullable Constructor<?> ctor, Object... args) {

        // 通过内部组件CglibSubclassCreator来创建Cglib代理对象;这个组件稍后再解析
        return new CglibSubclassCreator(bd, owner).instantiate(ctor, args);
    }

    /**
     * 本类主要作为其它内部组件(如方法过滤器和方法拦截器)的父类
     * 本类重写了equals()和hashcode()方法,确保同一个Bean的同一种类型的内部组件是等价的
     */
    private static class CglibIdentitySupport {
        private final RootBeanDefinition beanDefinition;

        public CglibIdentitySupport(RootBeanDefinition beanDefinition) {
            this.beanDefinition = beanDefinition;
        }

        public RootBeanDefinition getBeanDefinition() {
            return this.beanDefinition;
        }

        @Override
        public boolean equals(@Nullable Object other) {
            return (other != null && getClass() == other.getClass() &&
                    this.beanDefinition.equals(((CglibIdentitySupport) other).beanDefinition));
        }

        @Override
        public int hashCode() {
            return this.beanDefinition.hashCode();
        }
    }
}

4.4. MethodOverrideCallbackFilter

先来看MethodOverrideCallbackFilter组件;该组件主要负责判断哪些方法需要增强

public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationStrategy {

    /**
     * 常量0代表方法不需要进行增强
     */
    private static final int PASSTHROUGH = 0;

    /**
     * 常量1代表方法需要进行LookupMethod增强
     */
    private static final int LOOKUP_OVERRIDE = 1;

    /**
     * 常量2代表方法需要进行ReplacedMethod增强
     */
    private static final int METHOD_REPLACER = 2;

    /**
     * 方法过滤器,用于判断Bean的指定方法是否需要重写、采用什么方式的重写机制
     */
    private static class MethodOverrideCallbackFilter extends CglibIdentitySupport implements CallbackFilter {

        /**
         * 构造方法,需指定目标BeanDefinition
         */
        public MethodOverrideCallbackFilter(RootBeanDefinition beanDefinition) {
            super(beanDefinition);
        }

        /**
         * 判断目标Bean的指定方法是否需要增强
         */
        @Override
        public int accept(Method method) {
            
            // 获取该方法对应的MethodOverride(相当于xml文件中的lookup-method/replaced-method标签)
            MethodOverride methodOverride = getBeanDefinition().getMethodOverrides().getOverride(method);
            
            // 如果该方法没有对应的MethodOverride,则直接放行
            if (methodOverride == null) {
                return PASSTHROUGH;
            
            // 否则,根据MethodOverride的类型返回相应的数值
            } else if (methodOverride instanceof LookupOverride) {
                return LOOKUP_OVERRIDE;
            } else if (methodOverride instanceof ReplaceOverride) {
                return METHOD_REPLACER;
            }
            throw new UnsupportedOperationException("Unexpected MethodOverride subclass: " +
                    methodOverride.getClass().getName());
        }
    }
}

4.5. CglibSubclassCreator

public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationStrategy {

    /**
     * 本类负责为有方法重写机制的Bean创建代理对象
     */
    private static class CglibSubclassCreator {

        /**
         * 回调(拦截器/增强逻辑)的类型
         * 注意,拦截器的下标和MethodOverrideCallbackFilter的accept()方法的返回值是对应的
         * 比如,方法过滤器的accept()方法返回1(LOOKUP_OVERRIDE),就代表要执行LookupOverrideMethodInterceptor的增强
         */
        private static final Class<?>[] CALLBACK_TYPES = new Class<?>[]
                {NoOp.class, LookupOverrideMethodInterceptor.class, ReplaceOverrideMethodInterceptor.class};

        /**
         * 要给哪个Bean创建代理对象
         */
        private final RootBeanDefinition beanDefinition;

        /**
         * 所属BeanFactory
         */
        private final BeanFactory owner;

        /**
         * 全参构造器
         */
        CglibSubclassCreator(RootBeanDefinition beanDefinition, BeanFactory owner) {
            this.beanDefinition = beanDefinition;
            this.owner = owner;
        }

        /**
         * 创建Bean类的子类(代理对象的类型)
         */
        private Class<?> createEnhancedSubclass(RootBeanDefinition beanDefinition) {
            Enhancer enhancer = new Enhancer();

            // 设置父类
            enhancer.setSuperclass(beanDefinition.getBeanClass());

            enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
            if (this.owner instanceof ConfigurableBeanFactory) {
                ClassLoader cl = ((ConfigurableBeanFactory) this.owner).getBeanClassLoader();
                enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(cl));
            }

            // 设置方法过滤器
            enhancer.setCallbackFilter(new MethodOverrideCallbackFilter(beanDefinition));

            // 设置拦截器类型;注意,这里设置的是拦截器类型,而不是具体的拦截器实例
            // 拦截器实例会在子类对象实例化完成后才创建(这么做是为了避免内存泄漏)
            enhancer.setCallbackTypes(CALLBACK_TYPES);

            // 创建子类
            return enhancer.createClass();
        }

        /**
         * 根据指定构造方法创建Bean的代理对象
         */
        public Object instantiate(@Nullable Constructor<?> ctor, Object... args) {

            // 创建Bean类的子类
            Class<?> subclass = createEnhancedSubclass(this.beanDefinition);

            // 实例化子类对象
            Object instance;
            if (ctor == null) {
                instance = BeanUtils.instantiateClass(subclass);
            } else {
                try {
                    Constructor<?> enhancedSubclassConstructor = subclass.getConstructor(ctor.getParameterTypes());
                    instance = enhancedSubclassConstructor.newInstance(args);
                } catch (Exception ex) {
                    throw new BeanInstantiationException(this.beanDefinition.getBeanClass(),
                            "Failed to invoke constructor for CGLIB enhanced subclass [" + subclass.getName() + "]", ex);
                }
            }

            // 给子类对象设置回调,将增强逻辑应用到子类对象之中;这里设置的callbacks要和CALLBACK_TYPES相对应
            Factory factory = (Factory) instance;
            factory.setCallbacks(new Callback[]{NoOp.INSTANCE,
                    new LookupOverrideMethodInterceptor(this.beanDefinition, this.owner),
                    new ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)});
            return instance;
        }
    }
}

4.6. XxxOverrideMethodInterceptor

public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationStrategy {
    
    /**
     * 与LookupOverride相关的方法拦截器
     */
    private static class LookupOverrideMethodInterceptor extends CglibIdentitySupport implements MethodInterceptor {
        private final BeanFactory owner;

        public LookupOverrideMethodInterceptor(RootBeanDefinition beanDefinition, BeanFactory owner) {
            super(beanDefinition);
            this.owner = owner;
        }

        /**
         * 对指定方法进行LookupMethod增强
         */
        @Override
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable {
            
            // 获取到该方法的LookupOverride配置
            // 这里可以直接将MethodOverride强转为LookupOverride,并且它一定不为null
            // 这是因为在方法过滤器中,我们已经对MethodOverride的类型进行过判断了
            LookupOverride lo = (LookupOverride) getBeanDefinition().getMethodOverrides().getOverride(method);
            Assert.state(lo != null, "LookupOverride not found");
            
            // 将该方法的传参作为获取Bean时使用的参数
            Object[] argsToUse = (args.length > 0 ? args : null);
            
            // 如果指定了Lookup的Bean名称,则根据Bean名称和相应的参数来获取Bean,并将该Bean作为方法的返回值返回
            if (StringUtils.hasText(lo.getBeanName())) {
                Object bean = (argsToUse != null ? this.owner.getBean(lo.getBeanName(), argsToUse) :
                        this.owner.getBean(lo.getBeanName()));
                // Detect package-protected NullBean instance through equals(null) check
                return (bean.equals(null) ? null : bean);
            
            // 否则,根据方法的返回值类型(可能涉及到泛型)获取相应类型的Bean并返回
            } else {
                ResolvableType genericReturnType = ResolvableType.forMethodReturnType(method);
                return (argsToUse != null ? this.owner.getBeanProvider(genericReturnType).getObject(argsToUse) :
                        this.owner.getBeanProvider(genericReturnType).getObject());
            }
        }
    }

    /**
     * 与ReplaceOverride相关的方法拦截器
     */
    private static class ReplaceOverrideMethodInterceptor extends CglibIdentitySupport implements MethodInterceptor {
        private final BeanFactory owner;

        public ReplaceOverrideMethodInterceptor(RootBeanDefinition beanDefinition, BeanFactory owner) {
            super(beanDefinition);
            this.owner = owner;
        }

        /**
         * 对指定方法进行ReplacedMethod增强
         */
        @Override
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable {

            // 获取到该方法的ReplaceOverride配置
            ReplaceOverride ro = (ReplaceOverride) getBeanDefinition().getMethodOverrides().getOverride(method);
            Assert.state(ro != null, "ReplaceOverride not found");
            
            // 获取到对应的MethodReplacer组件并调用其reimplement()方法
            // TODO could cache if a singleton for minor performance optimization
            MethodReplacer mr = this.owner.getBean(ro.getMethodReplacerBeanName(), MethodReplacer.class);
            return mr.reimplement(obj, method, args);
        }
    }
}

5. 源码解析:重写机制

5.1. MethodOverride

/**
 * 本类代表Bean的方法重写信息;一个Bean可以对应多个MethodOverride
 * 注意,方法重写机制不能作为插入横切的通用方式(也就是说,方法重写机制不能代替AOP)
 */
public abstract class MethodOverride implements BeanMetadataElement {

    /**
     * 被重写的方法的名称
     */
    private final String methodName;

    /**
     * 该方法是否有重载方法
     * 如果为false,说明类中只有一个名称为methodName的方法
     * 如果为true,说明类中有多个名称为methodName的方法,或者未解析类中的方法(即未知)
     */
    private boolean overloaded = true;

    /**
     * 该MethodOverride的配置源
     * 该字段的作用我不太清楚,而且该字段的用处较少,因此可以先忽略
     */
    @Nullable
    private Object source;

    /**
     * 构造器,需指定方法名称
     */
    protected MethodOverride(String methodName) {
        Assert.notNull(methodName, "Method name must not be null");
        this.methodName = methodName;
    }
    
    // 这里省略了以上3个字段的set/get方法,以及equals()/hashcode()方法

    /**
     * 抽象方法;判断本MethodOverride配置是否要应用到目标方法中(即目标方法是否需要重写)
     */
    public abstract boolean matches(Method method);
}
/**
 * 本类代表Bean的LookupMethod增强信息
 * 被重写的方法可以有形参;当从容器中获取目标Bean时,方法的参数将会被传到容器的getBean()方法中
 */
public class LookupOverride extends MethodOverride {

    /**
     * 要返回的Bean的名称
     */
    @Nullable
    private final String beanName;

    /**
     * 被重写的方法
     */
    @Nullable
    private Method method;

    /**
     * 构造器1:需指定被重写的方法的名称和目标Bean名称
     * 如果是xml文件配置,则使用该构造器来创建LookupOverride对象
     */
    public LookupOverride(String methodName, @Nullable String beanName) {
        super(methodName);
        this.beanName = beanName;
    }

    /**
     * 构造器2:需指定被重写的方法和目标Bean名称
     * 如果是通过@Lookup注解来配置的,则使用该构造器来创建LookupOverride对象
     */
    public LookupOverride(Method method, @Nullable String beanName) {
        super(method.getName());
        this.method = method;
        this.beanName = beanName;
    }

    /**
     * 获取要返回的Bean的名称
     */
    @Nullable
    public String getBeanName() {
        return this.beanName;
    }

    /**
     * 判断目标方法是否需要进行Lookup增强
     */
    @Override
    public boolean matches(Method method) {
        
        // 如果是通过@Lookup注解配置的,则直接判断this.method是否和目标方法相同
        if (this.method != null) {
            return method.equals(this.method);
        
        // 否则,如果同时满足以下两个条件,则目标方法需要被重写:
        // 1. 目标方法的名称和本类要重写的方法的名称相同
        // 2. Bean类中只有一个该名称的方法,或者目标方法是抽象的,或者目标方法是无参的(即默认重写无参方法)
        } else {
            return (method.getName().equals(getMethodName()) && (!isOverloaded() ||
                    Modifier.isAbstract(method.getModifiers()) || method.getParameterCount() == 0));
        }
    }
    
    // 这里省略了equals()/hashcode()/toString()方法
}
/**
 * 本类代表Bean的ReplacedMethod增强信息
 */
public class ReplaceOverride extends MethodOverride {

    /**
     * 目标MethodReplacer组件的Bean名称
     */
    private final String methodReplacerBeanName;

    /**
     * 目标方法的参数类型(即arg-type标签的内容)
     */
    private final List<String> typeIdentifiers = new ArrayList<>();

    /**
     * 构造器,需指定目标方法名称和目标MethodReplacer组件的Bean名称
     */
    public ReplaceOverride(String methodName, String methodReplacerBeanName) {
        super(methodName);
        Assert.notNull(methodReplacerBeanName, "Method replacer bean name must not be null");
        this.methodReplacerBeanName = methodReplacerBeanName;
    }

    /**
     * 获取MethodReplacer组件的Bean名称
     */
    public String getMethodReplacerBeanName() {
        return this.methodReplacerBeanName;
    }

    /**
     * 添加方法参数类型;每解析完一个arg-type标签,就会调用一次本方法
     * 这里的identifier可以是全限定类名的子串,比如"Object"或"java.lang.Obj"等
     */
    public void addTypeIdentifier(String identifier) {
        this.typeIdentifiers.add(identifier);
    }

    /**
     * 判断目标方法是否需要进行Replace增强
     */
    @Override
    public boolean matches(Method method) {
        
        // 如果方法名称不一致,则不重写
        if (!method.getName().equals(getMethodName())) {
            return false;
        }
        
        // 如果Bean类只有一个该名称的方法,则重写该方法
        if (!isOverloaded()) {
            return true;
        }
        
        // 否则,说明有多个重载方法或者未对Bean类中的方法进行解析
        // 这种情况下,要求目标方法的参数类型和本类中的typeIdentifiers必须完全匹配
        if (this.typeIdentifiers.size() != method.getParameterCount()) {
            return false;
        }
        Class<?>[] parameterTypes = method.getParameterTypes();
        for (int i = 0; i < this.typeIdentifiers.size(); i++) {
            String identifier = this.typeIdentifiers.get(i);

            // 注意这里调用的是String的contains()方法而不是equals()方法
            if (!parameterTypes[i].getName().contains(identifier)) {
                return false;
            }
        }
        return true;
    }

    // 这里省略了equals()/hashcode()/toString()方法
}

5.2. MethodOverrides

/**
 * 代表MethodOverride集合
 * 一个Bean可以配置多个MethodOverride,因此使用本组件来管理单个Bean的所有MethodOverride配置
 * 用于判断某个Bean是否有要重写的方法,以及Bean的某个方法是否需要重写
 */
public class MethodOverrides {

    /**
     * 该Bean的所有MethodOverride配置;注意,这里是用CopyOnWriteArraySet集合来保存的
     */
    private final Set<MethodOverride> overrides = new CopyOnWriteArraySet<>();
    
    public MethodOverrides() {
    }
    
    public MethodOverrides(MethodOverrides other) {
        addOverrides(other);
    }
    
    public void addOverrides(@Nullable MethodOverrides other) {
        if (other != null) {
            this.overrides.addAll(other.overrides);
        }
    }
    
    public void addOverride(MethodOverride override) {
        this.overrides.add(override);
    }
    
    public Set<MethodOverride> getOverrides() {
        return this.overrides;
    }
    
    public boolean isEmpty() {
        return this.overrides.isEmpty();
    }

    /**
     * 判断目标方法是否需要重写;如果需要重写,则返回相应的MethodOverride
     */
    @Nullable
    public MethodOverride getOverride(Method method) {
        MethodOverride match = null;
        
        // 遍历overrides集合,获取到最后一个能和目标方法匹配的MethodOverride
        // 注意,由于overrides是CopyOnWriteArraySet类型,并且lookup-method标签先于replaced-method标签解析
        // 因此,如果LookupOverride和ReplaceOverride能同时匹配目标方法,则最终生效的是ReplaceOverride
        for (MethodOverride candidate : this.overrides) {
            if (candidate.matches(method)) {
                match = candidate;
            }
        }
        return match;
    }

    // 这里省略了equals()/hashcode()方法
}

5.3. prepareMethodOverride()

/**
 * 抽象的BeanDefinition
 */
public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
        implements BeanDefinition, Cloneable {

    /**
     * 该Bean的方法重写信息
     */
    private MethodOverrides methodOverrides = new MethodOverrides();

    /**
     * 验证并解析当前Bean的所有MethodOverride;在创建Bean前会先调用该方法
     */
    public void prepareMethodOverrides() throws BeanDefinitionValidationException {
        if (hasMethodOverrides()) {
            getMethodOverrides().getOverrides().forEach(this::prepareMethodOverride);
        }
    }

    /**
     * 验证并解析当前Bean的指定MethodOverride
     */
    protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
        
        // 获取Bean类中所有名称为methodName的方法(包括父类/接口中的方法和非公开的方法)
        int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
        
        // 没找到该名称的方法,则直接报错
        if (count == 0) {
            throw new BeanDefinitionValidationException(
                    "Invalid method override: no method with name '" + mo.getMethodName() +
                            "' on class [" + getBeanClassName() + "]");
        
        // 如果只有一个该名称的方法,则将MethodOverride的overloaded置为false,从而提高MethodOverride.match()方法的效率
        } else if (count == 1) {
            mo.setOverloaded(false);
        }
    }
}