AOP概述

AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。 是一种新的模块化机制,用来描述分散在对象,类,或函数中的横切关注点,分离关注点使解决特定领域问题的代码从业务逻辑中独立出来,业务逻辑代码中不在含义针对特定领域的代码调用,业务逻辑同特定领域问题的关系通过切面封装,维护,这样原本分散在整个应用程序中的变动可以很好地管理起来。

用人话说就是,通过切面完成特定逻辑(事务,入参出参日志等) 可以和业务逻辑(CRUD)抽离开,便于维护

  • Advice 通知:定义在连接点做什么,为切面增强提供植入接口。描述Spring AOP围绕方法调而注入的切面行为
  • Pointcut切入点:切点决定Advice通知应该作用在哪个连接点,也就是通过Poincut来定义需要增强的方法集合,这些集合可以按照一定规则来完成,这种情况下,Pointcut意味着标识方法(比如事务切面定义了事务注解方法上生效)切入点是一些列织入逻辑代码的连接点集合
  • Advisor通知器:整合Advice 和 Pointcut,定义应该在哪个关注点使用什么通知进行增强。

AOP重要接口和编程体验

我们先抛弃Spring框架,利用Spring AOP中存在的工具实现AOP增强。

基于Advice

image-20220824154409542

Advice接口的实现有AfterAdvice后置通知Beforeadvice前置通知MethodInterceptor方法拦截器可以看做是环绕通知。

  1. 服务类

    1
    2
    3
    4
    5
    public class AopService {
    public void doSomething(){
    System.out.println("service doSomething");
    }
    }
  2. 自定义advice 环绕通知

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class MyAdvice implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
    System.out.println("my advice before");
    // 方法执行
    Object res = invocation.proceed();
    System.out.println("my advice after");
    return res;
    }
    }
  3. 客户端

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    public class Client {
    public static void main(String[] args) {
    // 代理工程
    ProxyFactory proxyFactory = new ProxyFactory();
    // 目标对象
    AopService aopService = new AopService();

    // 设置需要代理的对象
    proxyFactory.setTarget(aopService);
    proxyFactory.addAdvice(new MyAdvice());

    // 生成代理对象
    AopService proxy = (AopService)proxyFactory.getProxy();
    proxy.doSomething();
    }
    }
    /*
    my advice before
    service doSomething
    my advice after
    */

基于Advisor

image-20220824162331408

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class Client {
public static void main(String[] args) {
// 代理工程
ProxyFactory proxyFactory = new ProxyFactory();
// 目标对象
AopService aopService = new AopService();

// advisor
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();
// 根据名称匹配方法的pointcut
NameMatchMethodPointcut pointcut = new NameMatchMethodPointcut();
// 指定只有doSomething才增强
pointcut.setMappedName("doSomething");
advisor.setPointcut(pointcut);
advisor.setAdvice(new MyAdvice());

// 设置需要代理的对象
proxyFactory.setTarget(aopService);
proxyFactory.addAdvice(new MyAdvice());

// 生成代理对象
AopService proxy = (AopService)proxyFactory.getProxy();
proxy.doSomething();
}
}

只有名称匹配的方法才生效。

Advisor接口具备方法Advice getAdvice()来获取通知。PointcutAdvisor实现了Advisor并且新增方法Pointcut getPointcut()来获取切入点的定义。Pointcut接口定义了两个方法ClassFilter getClassFilter(),MethodMatcher getMethodMatcher()分别是对类和方法的筛选,来决定Advise是不是应该作用于当前类。

ProxyFactory 和 ProxyFactoryBean

ProxyFactory

类图

image-20221204222328470

TargetSource 用于获取 AOP 调用的当前“目标”

image-20221204222936584

getTargetClass可以获取被代理对象的类型,getTarget可以获取被代理对象,HotSwappableTargetSource中的swap方法可以替换掉代理对象,Spring Aop常用的是SingletonTargetSource它持有了原始的被代理对象。

ProxyFactory是如何创建代理对象的

ProxyFactory类中有个getProxy()方法

1
2
3
4
5
6
7
8
9
10
public Object getProxy() {
return createAopProxy().getProxy();
}

protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}

createAopProxy()方法通过getAopProxyFactory()来创建代理对象,一般默认是AopProxyFactory的实现类DefaultAopProxyFactory

DefaultAopProxyFactory # createAopProxy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// Spring支持优化 设置了代理目标类 用户没有指定代理的接口
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
// 代理目标类是一个接口 或者说已经被JDK动态代理了
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
// 使用JDK动态代理
return new JdkDynamicAopProxy(config);
}
// 使用cglib动态代理
return new ObjenesisCglibAopProxy(config);
}
else {
// 使用JDK动态代理
return new JdkDynamicAopProxy(config);
}
}

这里生成的AopProxy 才是负责生成代理对象的,其中spring内置了两种策略——JDK动态代理CGLIB动态代理

只有设置了需要代理目标类,或者说没有指定代理的接口,且代理目标类不是接口,不是已经被JDK动态代理后的类,那么才会使用CGLIB进行动态代理。

AopProxy

AopPorxy有2个实现类CglibAopProxyJdkDynamicAopProxy

JdkDynamicAopProxy

JdkDynamicAopProxy还实现了InvocationHandler

  • 生成代理对象getProxy()

    1
    2
    3
    4
    5
    6
    7
    8
    9
    @Override
    public Object getProxy(@Nullable ClassLoader classLoader) {
    if (logger.isTraceEnabled()) {
    logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
    }
    Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
    findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
    return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); //this只自己
    }
  • invoke()
    首先是对equals,hashCode的处理,目标对象声明了让目标对象执行,反之调用JdkDynamicAopProxy对应的方法,其次是如果配置中设置了暴露代理对象,那么将其放入到AopContext中的ThreadLocal

    1
    2
    3
    4
    5
    if (this.advised.exposeProxy) {
    // Make invocation available if necessary.
    oldProxy = AopContext.setCurrentProxy(proxy);
    setProxyContext = true;
    }

    然后获取当前对象的拦截器链,如果拦截器链为空 那么直接反射调用目标对象的方法。如果存在拦截器链那么new 一个ReflectiveMethodInvocation利用反射依次执行。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    target = targetSource.getTarget();
    Class<?> targetClass = (target != null ? target.getClass() : null);

    // Get the interception chain for this method.
    List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

    // Check whether we have any advice. If we don't, we can fallback on direct
    // reflective invocation of the target, and avoid creating a MethodInvocation.
    if (chain.isEmpty()) {
    // We can skip creating a MethodInvocation: just invoke the target directly
    // Note that the final invoker must be an InvokerInterceptor so we know it does
    // nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
    Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
    retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
    }
    else {
    // We need to create a method invocation...
    MethodInvocation invocation =
    new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
    // Proceed to the joinpoint through the interceptor chain.
    retVal = invocation.proceed();
    }

    Spring只支持方法拦截器MethodInterceptor进行代理增强,对于Advise都会适配成MethodInterceptor,Spring采用适配器模式,具体的适配器如下

    image-20220824172451573

    1
    2
    3
    4
    5
    6
    7
    public interface AdvisorAdapter {
    //支持什么Advise被适配
    boolean supportsAdvice(Advice advice);

    //适配
    MethodInterceptor getInterceptor(Advisor advisor);
    }

    Spring遍历每一个Advise责任链模式依次找到AdvisorAdapter然后调用适配方法得到一个MethodInterceptor,下面是适配成的MethodInterceptor

    image-20220824172904504

CGLIB动态代理

设置CallBack

首先new 一个Enhancer设置父类为被代理对象的类型,这里会将Aop的逻辑转变为一个DynamicAdvisedInterceptor,equals和hashCode方法也有对应的callBack

image-20220824174533939

注意这里的MethodInterceptororg.springframework.cglib.proxy.MethodInterceptor,其中的intercept 方法的逻辑和JDK动态代理的invoke类似,都是链式调用。

ProxyFactoryBean

image-20220824175124978

ProxyFactoryBean创建代理对象的逻辑和ProxyFactory类似,但是ProxyFactoryBean是一个FactoryBean,我们可以利用这一点在bean初始化的时候生成一个代理对象

使用ProxyFactoryBean或其他IOC类来创建AOP代理的最重要好处之一是,这意味着advice和切入点也可以由IoC管理ProxyFactoryBeangetObject()将创建一个包装目标对象的AOP代理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Override
@Nullable
public Object getObject() throws BeansException {
// 初始化advisor链条
initializeAdvisorChain();
if (isSingleton()) {
return getSingletonInstance();
}
else {
if (this.targetName == null) {
...
}
return newPrototypeInstance();
}
}

getSingletonInstance()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private synchronized Object getSingletonInstance() {
if (this.singletonInstance == null) {
// 没有创建过单例对象 进行创建
this.targetSource = freshTargetSource();
if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
// Rely on AOP infrastructure to tell us what interfaces to proxy.
Class<?> targetClass = getTargetClass();
if (targetClass == null) {
throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");
}
setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
}
// Initialize the shared singleton instance.
super.setFrozen(this.freezeProxy);
// 最终还是通过AopProxyFactory创建AopProxy生成代理对象
this.singletonInstance = getProxy(createAopProxy());
}
return this.singletonInstance;
}

Spring AOP 和IOC是如何结合起来的

我们在使用Spring AOP的时候会在启动类上加一个@EnableAspectJAutoProxy注解,这个注解@Import(AspectJAutoProxyRegistrar.class)导入了AspectJAutoProxyRegistrar,这个类实现了ImportBeanDefinitionRegistrar,Spring容器会调用其registerBeanDefinitions方法为我们注入BeanDefinition,后续会实例化一个AnnotationAwareAspectJAutoProxyCreator类型的bean,它是Spring IOC和AOP结合的关键

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

/**
* Register, escalate, and configure the AspectJ auto proxy creator based on the value
* of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
* {@code @Configuration} class.
*/
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// 注册AnnotationAutoProxyCreator
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}

}

AnnotationAwareAspectJAutoProxyCreator类结构图

image-20220824180746690

这其中最为关键的必然是AnnotationAwareAspectJAutoProxyCreator,它是一个BeanPostProcessor,从而在Spring 回调postProcessAfterInitialization对bean进行代理的增强,并且它实现了SmartInstantiationAwareBeanPostProcessor Spring容器创建bean的时候如果出现了循环依赖那么会调用到getEarlyBeanReference,在这个方法里面同样也会进行aop的增强

  • AbstractAutoProxyCreator 实现了SmartInstantiationAwareBeanPostProcessor是一个bean后置处理器,使用 AOP 代理包装每个符合条件的 bean,在调用 bean 本身之前委托给指定的拦截器,AOP代理发生的地方。

  • AbstractAdvisorAutoProxyCreator

    为了每一个Bean找到合适的Advisor并且进行,如果Advisor标注了@Order或者说实现了Ordered接口那么会进行排序。

  • AspectJAwareAdvisorAutoProxyCreator

    AbstractAdvisorAutoProxyCreator子类,对一个切面中的多个Advisor进行优先级排序

  • AnnotationAwareAspectJAutoProxyCreator

    AspectJAwareAdvisorAutoProxyCreator的子类,会将容器中标注了@AspectJ注解的类解析成Advisor(整合AdvicePointcut,定义应该使用哪个通知器并在哪个关注点使用它)

AbstractAutoProxyCreator的Aop增强

getEarlyBeanReference

在Spring进行bean的实例化后, 在bean创建完成后会向三级缓存提添加单例工厂,而此时三级缓存的出现特意为了解决有AOP代理时循环依赖问题的,getEarlyBeanReference会对bean使用SmartInstantiationAwareBeanPostProcessor的实现类进行处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// AbstractAutowireCapableBeanFactory
// addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
// AbstractAutoProxyCreator
public Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
this.earlyProxyReferences.put(cacheKey, bean); // 在map里面放入key和原始对象
return wrapIfNecessary(bean, beanName, cacheKey); //进行aop代理
}

而在bean实例化、填充属性后,初始bean时会调用BeanPostProcessorpostProcessAfterInitialization的方法,而对此时的AOP来说就进行了重要的一环wrapIfNecessary

1
2
3
4
5
6
7
8
9
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}

对于有AOP的对象,会在实例化后,就直接创建出代理对象并返回,但是这时,代理对象是没有初始化过的,是不可用的,所以Spring在创建代理时,持有了目标对象bean的引用

wrapIfNecessary

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 如果已经代理过就不代理
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
// 如果是基础组件类似于Advise、Pointcut、Advisor、AopInfrastructureBean对象也不代理
// 应该跳过的也不代理
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}

// Create proxy if we have advice.
// 找到当前bean对象合适的Advise和Advisor
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 创建代理
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}

this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}

其中shouldSkipAspectJAwareAdvisorAutoProxyCreator重写,如果AdvisorAspectJPointcutAdvisor并且切面名称和bean名称相同那么会跳过,这应该是我们标注@Aspect的时候需要保证这个类会被Spring加入到容器,所有需要加@Componet

1
2
@Aspect
@Component
找到所有合适的advice 和advisor
1
2
3
4
5
6
7
8
9
10
11
12
13
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 找到所有的advisor
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 找到适用于当前bean的advisor
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
// 子类扩展
extendAdvisors(eligibleAdvisors);
// 排序
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
  • findCandidateAdvisors方法会找到容器中所以的Advisor类型的bean,AnnotationAwareAspectJAutoProxyCreator进行了重写,它还会把所以标注了@Aspect注解的bean中的增强逻辑封装成Advisor
  • findAdvisorsThatCanApply这个方法内部逻辑基本上就是调用PointcutAdvisor获取类过滤器,方法匹配器进行匹配。
  • sortAdvisors 这里默认是通过@Order注解,或者Ordered接口进行排序,但是AspectJAwareAdvisorAutoProxyCreator进行了重写,因为它需要对同一个标注@Aspect切面里面的前置后置等进行排序
创建代理对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {

if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}

ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);

//这里的ProxyTargetClass 来自上面的copyFrom 取决于EnableAspectJAutoProxy注解的proxyTargetClass
//proxyTargetClass 表示是否使用基于CGLIB子类的代理
if (proxyFactory.isProxyTargetClass()) {
// Explicit handling of JDK proxy targets (for introduction advice scenarios)

if (Proxy.isProxyClass(beanClass)) {
// Must allow for introductions; can't just set interfaces to the proxy's interfaces only.
// 必须允许介绍;不能仅将接口设置为代理的接口。
for (Class<?> ifc : beanClass.getInterfaces()) {
proxyFactory.addInterface(ifc);
}
}
}
else {
// No proxyTargetClass flag enforced, let's apply our default checks...
// shouldProxyTargetClass 方法就是去BeanFactory中看当前bean的BeanDefinition中是否存在AutoProxy.PRESERVE_TARGET_CLASS_ATTRIBUTE=trued的attribute,当我们手动注入bean的时候可以使用这个强制让当前bean使用CGLIB增强
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
// 获取当前类中非Spring回调(InitializingBean,DisposableBean,Aware)类型的接口,且如果接口的方法大于0,那么会把接口类型加入到proxyFactory中,否则设置ProxyTargetClass(没有接口那么没办法使用JDK动态代理)
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// 主要是把上面找到的advise 适配成Advisor。调用的是advisorAdapterRegistry的wrap方法
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
// 这里的targetSource是SingletonTargetSource
proxyFactory.setTargetSource(targetSource);
//留给子类扩展的方法
customizeProxyFactory(proxyFactory);

proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}

//生成代理对象
return proxyFactory.getProxy(getProxyClassLoader());
}

这里其实和我们上面的Aop编程体验中基于Advisor类似,最后都是AopProxy创建代理对象

AnnotationAwareAspectJAutoProxyCreator

AnnotationAwareAspectJAutoProxyCreator会将@Aspect注解类解析成Advisor,下面我们重点看下AnnotationAwareAspectJAutoProxyCreator是怎么将@Aspect注解类解析成Advisor

1
2
3
4
5
6
7
8
9
10
11
@Override
protected List<Advisor> findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
if (this.aspectJAdvisorsBuilder != null) {
// 找到容器中所有的bean,如果bean标注了@Aspect注解就处理
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}

BeanFactoryAspectJAdvisorsBuilder,它会遍历所有bean,并调用isAspect方法

1
2
3
4
5
6
7
8
@Override
public boolean isAspect(Class<?> clazz) {
return (hasAspectAnnotation(clazz) && !compiledByAjc(clazz));
}

private boolean hasAspectAnnotation(Class<?> clazz) {
return (AnnotationUtils.findAnnotation(clazz, Aspect.class) != null);
}

然后调用ReflectiveAspectJAdvisorFactorygetAdvisors方法将其适配成多个Advisor,会遍历每一个没有标注@Pointcut的方法,然后获取@Around, @Before, @After, @AfterReturning, @AfterThrowing(如果没有那么直接返回)然后获取value中的内容包装成AspectJExpressionPointcut(AspectJ表达式pointcut),然后包装成InstantiationModelAwarePointcutAdvisorImpl在这个类中会把对应注解的方法封装成对应的AbstractAspectJAdvice的子类

image-20220824191958027

调用对应方法依旧采用反射,其子类在合适的实际进行调用。

参考:

https://www.cnblogs.com/cuzzz/p/16621320.html