2024年Spring AOP源码学习:创建 AOP 代理,如何一步步成为一名架构师

最后

这份文档从构建一个键值数据库的关键架构入手,不仅带你建立起全局观,还帮你迅速抓住核心主线。除此之外,还会具体讲解数据结构、线程模型、网络框架、持久化、主从同步和切片集群等,帮你搞懂底层原理。相信这对于所有层次的Redis使用者都是一份非常完美的教程了。

image

整理不易,觉得有帮助的朋友可以帮忙点赞分享支持一下小编~

你的支持,我的动力;祝各位前程似锦,offer不断!!!

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

// 1.5 解析标记AspectJ注解中的增强方法

List classAdvisors = this.advisorFactory.getAdvisors(factory);

// 1.6 放到缓存中

if (this.beanFactory.isSingleton(beanName)) {

// 如果beanName是单例则直接将解析的增强方法放到缓存

this.advisorsCache.put(beanName, classAdvisors);

} else {

// 如果不是单例,则将factory放到缓存,之后可以通过factory来解析增强方法

this.aspectFactoryCache.put(beanName, factory);

}

// 1.7 将解析的增强器添加到advisors

advisors.addAll(classAdvisors);

} else {

// 如果per-clause的类型不是SINGLETON

// Per target or per this.

if (this.beanFactory.isSingleton(beanName)) {

// 名称为beanName的Bean是单例,但切面实例化模型不是单例,则抛异常

throw new IllegalArgumentException(“Bean with name '” + beanName +

“’ is a singleton, but aspect instantiation model is not singleton”);

}

MetadataAwareAspectInstanceFactory factory =

new PrototypeAspectInstanceFactory(this.beanFactory, beanName);

// 将factory放到缓存,之后可以通过factory来解析增强方法

this.aspectFactoryCache.put(beanName, factory);

// 解析标记AspectJ注解中的增强方法,并添加到advisors中

advisors.addAll(this.advisorFactory.getAdvisors(factory));

}

}

}

// 1.9 将解析出来的切面beanName放到缓存aspectBeanNames

this.aspectBeanNames = aspectNames;

// 1.10 最后返回解析出来的增强器

return advisors;

}

}

}

// 2.如果aspectNames不为null,则代表已经解析过了,则无需再次解析

// 2.1 如果aspectNames是空列表,则返回一个空列表。空列表也是解析过的,只要不是null都是解析过的。

if (aspectNames.isEmpty()) {

return Collections.emptyList();

}

// 2.2 aspectNames不是空列表,则遍历处理

List advisors = new LinkedList();

for (String aspectName : aspectNames) {

// 根据aspectName从缓存中获取增强器

List cachedAdvisors = this.advisorsCache.get(aspectName);

if (cachedAdvisors != null) {

// 根据上面的解析,可以知道advisorsCache存的是已经解析好的增强器,直接添加到结果即可

advisors.addAll(cachedAdvisors);

} else {

// 如果不存在于advisorsCache缓存,则代表存在于aspectFactoryCache中,

// 从aspectFactoryCache中拿到缓存的factory,然后解析出增强器,添加到结果中

MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);

advisors.addAll(this.advisorFactory.getAdvisors(factory));

}

}

// 返回增强器

return advisors;

}

1.5 解析标记 AspectJ 注解中的增强方法,见代码块7。

代码块7:getAdvisors


@Override

public List getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {

// 1.前面我们将beanClass和beanName封装成了aspectInstanceFactory的AspectMetadata属性,

// 这边可以通过AspectMetadata属性重新获取到当前处理的切面类

Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();

// 2.获取当前处理的切面类的名字

String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();

// 3.校验切面类

validate(aspectClass);

// We need to wrap the MetadataAwareAspectInstanceFactory with a decorator

// so that it will only instantiate once.

// 4.使用装饰器包装MetadataAwareAspectInstanceFactory,以便它只实例化一次。

MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =

new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

List advisors = new LinkedList();

// 5.获取切面类中的方法(也就是我们用来进行逻辑增强的方法,被@Around、@After等注解修饰的方法,使用@Pointcut的方法不处理)

for (Method method : getAdvisorMethods(aspectClass)) {

// 6.处理method,获取增强器

Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);

if (advisor != null) {

// 7.如果增强器不为空,则添加到advisors

advisors.add(advisor);

}

}

// If it’s a per target aspect, emit the dummy instantiating aspect.

if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {

// 8.如果寻找的增强器不为空而且又配置了增强延迟初始化,那么需要在首位加入同步实例化增强器(用以保证增强使用之前的实例化)

Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);

advisors.add(0, instantiationAdvisor);

}

// Find introduction fields.

// 9.获取DeclareParents注解

for (Field field : aspectClass.getDeclaredFields()) {

Advisor advisor = getDeclareParentsAdvisor(field);

if (advisor != null) {

advisors.add(advisor);

}

}

return advisors;

}

6.处理 method,获取增强器,见代码块8。

代码块8:getAdvisor


@Override

public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,

int declarationOrderInAspect, String aspectName) {

// 1.校验切面类

validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());

// 2.AspectJ切点信息的获取(例如:表达式),就是指定注解的表达式信息的获取,如:@Around(“execution(* com.joonwhee.open.aop..(…))”)

AspectJExpressionPointcut expressionPointcut = getPointcut(

candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());

// 3.如果expressionPointcut为null,则直接返回null

if (expressionPointcut == null) {

return null;

}

// 4.根据切点信息生成增强器

return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,

this, aspectInstanceFactory, declarationOrderInAspect, aspectName);

}

2.AspectJ 切点信息的获取,见代码块9。

4.根据切点信息生成增强器,见代码块11。

代码块9:getPointcut


private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {

// 1.查找并返回给定方法的第一个AspectJ注解(@Before, @Around, @After, @AfterReturning, @AfterThrowing, @Pointcut)

// 因为我们之前把@Pointcut注解的方法跳过了,所以这边必然不会获取到@Pointcut注解

AspectJAnnotation<?> aspectJAnnotation =

AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);

// 2.如果方法没有使用AspectJ的注解,则返回null

if (aspectJAnnotation == null) {

return null;

}

// 3.使用AspectJExpressionPointcut实例封装获取的信息

AspectJExpressionPointcut ajexp =

new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);

// 提取得到的注解中的表达式,

// 例如:@Around(“execution(* com.joonwhee.open.aop..(…))”),得到:execution(* com.joonwhee.open.aop..(…))

ajexp.setExpression(aspectJAnnotation.getPointcutExpression());

ajexp.setBeanFactory(this.beanFactory);

return ajexp;

}

1.获取方法上的AspectJ注解,见代码块10。

代码块10:findAspectJAnnotationOnMethod


protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {

// 设置要查找的注解类

Class<?>[] classesToLookFor = new Class<?>[]{

Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class};

for (Class<?> c : classesToLookFor) {

// 查找方法上是否存在当前遍历的注解,如果有则返回

AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class) c);

if (foundAnnotation != null) {

return foundAnnotation;

}

}

return null;

}

代码块11:new InstantiationModelAwarePointcutAdvisorImpl


public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,

Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,

MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {

// 1.简单的将信息封装在类的实例中

this.declaredPointcut = declaredPointcut;

this.declaringClass = aspectJAdviceMethod.getDeclaringClass();

this.methodName = aspectJAdviceMethod.getName();

this.parameterTypes = aspectJAdviceMethod.getParameterTypes();

// aspectJAdviceMethod保存的是我们用来进行逻辑增强的方法(@Around、@After等修饰的方法)

this.aspectJAdviceMethod = aspectJAdviceMethod;

this.aspectJAdvisorFactory = aspectJAdvisorFactory;

this.aspectInstanceFactory = aspectInstanceFactory;

this.declarationOrder = declarationOrder;

this.aspectName = aspectName;

// 2.是否需要延迟实例化

if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {

// Static part of the pointcut is a lazy type.

Pointcut preInstantiationPointcut = Pointcuts.union(

aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);

// Make it dynamic: must mutate from pre-instantiation to post-instantiation state.

// If it’s not a dynamic pointcut, it may be optimized out

// by the Spring AOP infrastructure after the first evaluation.

this.pointcut = new PerTargetInstantiationModelPointcut(

this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);

this.lazy = true;

} else {

// A singleton aspect.

this.pointcut = this.declaredPointcut;

this.lazy = false;

// 3.实例化增强器:根据注解中的信息初始化对应的增强器

this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);

}

}

3.实例化增强器:根据注解中的信息初始化对应的增强器,见代码块12。

代码块12:instantiateAdvice


private Advice instantiateAdvice(AspectJExpressionPointcut pcut) {

return this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pcut,

this.aspectInstanceFactory, this.declarationOrder, this.aspectName);

}

// ReflectiveAspectJAdvisorFactory.java

@Override

public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,

MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {

// 1.获取切面类

Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();

// 2.校验切面类(重复校验第3次…)

validate(candidateAspectClass);

// 3.查找并返回方法的第一个AspectJ注解

AspectJAnnotation<?> aspectJAnnotation =

AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);

if (aspectJAnnotation == null) {

return null;

}

// If we get here, we know we have an AspectJ method.

// Check that it’s an AspectJ-annotated class

// 4.如果我们到这里,我们知道我们有一个AspectJ方法。检查切面类是否使用了AspectJ注解

if (!isAspect(candidateAspectClass)) {

throw new AopConfigException("Advice must be declared inside an aspect type: " +

“Offending method '” + candidateAdviceMethod + “’ in class [” +

candidateAspectClass.getName() + “]”);

}

if (logger.isDebugEnabled()) {

logger.debug("Found AspectJ method: " + candidateAdviceMethod);

}

AbstractAspectJAdvice springAdvice;

// 5.根据方法使用的aspectJ注解创建对应的增强器,例如最常见的@Around注解会创建AspectJAroundAdvice

switch (aspectJAnnotation.getAnnotationType()) {

case AtBefore:

springAdvice = new AspectJMethodBeforeAdvice(

candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);

break;

case AtAfter:

springAdvice = new AspectJAfterAdvice(

candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);

break;

case AtAfterReturning:

springAdvice = new AspectJAfterReturningAdvice(

candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);

AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();

if (StringUtils.hasText(afterReturningAnnotation.returning())) {

springAdvice.setReturningName(afterReturningAnnotation.returning());

}

break;

case AtAfterThrowing:

springAdvice = new AspectJAfterThrowingAdvice(

candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);

AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();

if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {

springAdvice.setThrowingName(afterThrowingAnnotation.throwing());

}

break;

case AtAround:

springAdvice = new AspectJAroundAdvice(

candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);

break;

case AtPointcut:

if (logger.isDebugEnabled()) {

logger.debug(“Processing pointcut '” + candidateAdviceMethod.getName() + “'”);

}

return null;

default:

throw new UnsupportedOperationException(

"Unsupported advice type on method: " + candidateAdviceMethod);

}

// Now to configure the advice…

// 6.配置增强器

// 切面类的name,其实就是beanName

springAdvice.setAspectName(aspectName);

springAdvice.setDeclarationOrder(declarationOrder);

// 获取增强方法的参数

String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);

if (argNames != null) {

// 如果参数不为空,则赋值给springAdvice

springAdvice.setArgumentNamesFromStringArray(argNames);

}

springAdvice.calculateArgumentBindings();

// 最后,返回增强器

return springAdvice;

}

代码块13:findAdvisorsThatCanApply


public static List findAdvisorsThatCanApply(List candidateAdvisors, Class<?> clazz) {

if (candidateAdvisors.isEmpty()) {

return candidateAdvisors;

}

List eligibleAdvisors = new LinkedList();

// 1.首先处理引介增强(@DeclareParents)用的比较少可以忽略,有兴趣的参考:https://www.cnblogs.com/HigginCui/p/6322283.html

for (Advisor candidate : candidateAdvisors) {

if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {

eligibleAdvisors.add(candidate);

}

}

boolean hasIntroductions = !eligibleAdvisors.isEmpty();

// 2.遍历所有的candidateAdvisors

for (Advisor candidate : candidateAdvisors) {

// 2.1 引介增强已经处理,直接跳过

if (candidate instanceof IntroductionAdvisor) {

// already processed

continue;

}

// 2.2 正常增强处理,判断当前bean是否可以应用于当前遍历的增强器(bean是否包含在增强器的execution指定的表达式中)

if (canApply(candidate, clazz, hasIntroductions)) {

eligibleAdvisors.add(candidate);

}

}

return eligibleAdvisors;

}

2.2 正常增强处理,判断当前 bean 是否可以应用于当前遍历的增强器,这边表达式判断的逻辑比较复杂,可以简单的理解为:判断 bean 是否包含在增强器的 execution 指定的表达式中。

代码块14:createProxy


protected Object createProxy(

Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {

if (this.beanFactory instanceof ConfigurableListableBeanFactory) {

AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);

}

// 1.初始化ProxyFactory

ProxyFactory proxyFactory = new ProxyFactory();

// 从当前对象复制属性值

proxyFactory.copyFrom(this);

// 检查proxyTargetClass属性,判断对于给定的bean使用类代理还是接口代理,

// proxyTargetClass值默认为false,可以通过proxy-target-class属性设置为true

if (!proxyFactory.isProxyTargetClass()) {

// 检查preserveTargetClass属性,判断beanClass是应该基于类代理还是基于接口代理

if (shouldProxyTargetClass(beanClass, beanName)) {

// 如果是基于类代理,则将proxyTargetClass赋值为true

proxyFactory.setProxyTargetClass(true);

} else {

// 评估bean的代理接口

evaluateProxyInterfaces(beanClass, proxyFactory);

}

}

// 将拦截器封装为Advisor(advice持有者)

Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);

// 将advisors添加到proxyFactory

proxyFactory.addAdvisors(advisors);

// 设置要代理的类,将targetSource赋值给proxyFactory的targetSource属性,之后可以通过该属性拿到被代理的bean的实例

proxyFactory.setTargetSource(targetSource);

// 自定义ProxyFactory,空方法,留给子类实现

customizeProxyFactory(proxyFactory);

// 用来控制proxyFactory被配置之后,是否还允许修改通知。默认值为false(即在代理被配置之后,不允许修改代理类的配置)

proxyFactory.setFrozen(this.freezeProxy);

if (advisorsPreFiltered()) {

proxyFactory.setPreFiltered(true);

}

// 2.使用proxyFactory获取代理

return proxyFactory.getProxy(getProxyClassLoader());

}

2.使用 proxyFactory 获取代理,见代码块15。

代码块15:getProxy


public Object getProxy(ClassLoader classLoader) {

// 1.createAopProxy:创建AopProxy

// 2.getProxy(classLoader):获取代理对象实例

return createAopProxy().getProxy(classLoader);

}

1.createAopProxy:创建AopProxy,见代码块16。

2.getProxy(classLoader):获取代理对象实例,跟我们自己写的代理类似,JDK 动态代理见代码块18,CGLIB 代理见代码块19。

代码块16:createAopProxy


protected final synchronized AopProxy createAopProxy() {

if (!this.active) {

// 1.激活此代理配置

activate();

}

// 2.创建AopProxy

return getAopProxyFactory().createAopProxy(this);

}

@Override

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {

// 1.判断使用JDK动态代理还是Cglib代理

// optimize:用于控制通过cglib创建的代理是否使用激进的优化策略。除非完全了解AOP如何处理代理优化,

// 否则不推荐使用这个配置,目前这个属性仅用于cglib代理,对jdk动态代理无效

// proxyTargetClass:默认为false,设置为true时,强制使用cglib代理,设置方式:<aop:aspectj-autoproxy proxy-target-class=“true” />

// hasNoUserSuppliedProxyInterfaces:config是否存在代理接口或者只有SpringProxy一个接口

if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {

// 拿到要被代理的对象的类型

Class<?> targetClass = config.getTargetClass();

if (targetClass == null) {

// TargetSource无法确定目标类:代理创建需要接口或目标。

throw new AopConfigException("TargetSource cannot determine target class: " +

“Either an interface or a target is required for proxy creation.”);

}

// 要被代理的对象是接口 || targetClass是Proxy class

// 当且仅当使用getProxyClass方法或newProxyInstance方法动态生成指定的类作为代理类时,才返回true。

if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {

// JDK动态代理,这边的入参config(AdvisedSupport)实际上是ProxyFactory对象

// 具体为:AbstractAutoProxyCreator中的proxyFactory.getProxy发起的调用,在ProxyCreatorSupport使用了this作为参数,

// 调用了的本方法,这边的this就是发起调用的proxyFactory对象,而proxyFactory对象中包含了要执行的的拦截器

return new JdkDynamicAopProxy(config);

}

// Cglib代理

return new ObjenesisCglibAopProxy(config);

} else {

// JDK动态代理

return new JdkDynamicAopProxy(config);

}

}

这边创建 AopProxy 的参数 config(AdvisedSupport)实际上是代码块14中的 proxyFactory 对象。

具体为:AbstractAutoProxyCreator 中的 proxyFactory.getProxy 发起的调用,在 ProxyCreatorSupport 使用了 this 作为参数调用了本方法,这边的 this 就是发起调用的 proxyFactory对象,而 proxyFactory 对象中包含了要执行的的拦截器(Advisor)。

无论是创建 JDK 动态代理还是 CGLIB 代理,都会传入 config 参数,该参数会被保存在 advised(AdvisedSupport)变量中,见代码块17。

代码块17:JDK 动态代理、CBLIB 代理构造函数


// JdkDynamicAopProxy.java

public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {

Assert.notNull(config, “AdvisedSupport must not be null”);

if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {

throw new AopConfigException(“No advisors and no TargetSource specified”);

}

// config赋值给advised

this.advised = config;

}

// ObjenesisCglibAopProxy.java

public ObjenesisCglibAopProxy(AdvisedSupport config) {

super(config);

}

// CglibAopProxy.java

public CglibAopProxy(AdvisedSupport config) throws AopConfigException {

Assert.notNull(config, “AdvisedSupport must not be null”);

if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {

throw new AopConfigException(“No advisors and no TargetSource specified”);

}

this.advised = config;

this.advisedDispatcher = new AdvisedDispatcher(this.advised);

}

代码块18:JdkDynamicAopProxy#getProxy


@Override

public Object getProxy(ClassLoader classLoader) {

if (logger.isDebugEnabled()) {

logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());

}

// 1.拿到要被代理对象的所有接口

Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);

findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);

// 2.通过classLoader、接口、InvocationHandler实现类,来获取到代理对象

return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);

}

最终,通过 JDK 动态代理的类被调用时,会走到 JdkDynamicAopProxy#invoke 方法。

代码块19:CglibAopProxy#getProxy


@Override

public Object getProxy(ClassLoader classLoader) {

if (logger.isDebugEnabled()) {

logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());

}

try {

// 1.拿到要代理目标类

Class<?> rootClass = this.advised.getTargetClass();

Assert.state(rootClass != null, “Target class must be available for creating a CGLIB proxy”);

// proxySuperClass默认为rootClass

Class<?> proxySuperClass = rootClass;

if (ClassUtils.isCglibProxyClass(rootClass)) {

// 如果rootClass是被Cglib代理过的,获取rootClass的父类作为proxySuperClass

proxySuperClass = rootClass.getSuperclass();

Class<?>[] additionalInterfaces = rootClass.getInterfaces();

for (Class<?> additionalInterface : additionalInterfaces) {

// 将父类的接口也添加到advised的interfaces属性

this.advised.addInterface(additionalInterface);

}

}

// Validate the class, writing log messages as necessary.

// 2.校验proxySuperClass,主要是校验方法是否用final修饰、跨ClassLoader的包可见方法,如果有将警告写入日志

validateClassIfNecessary(proxySuperClass, classLoader);

// Configure CGLIB Enhancer…

// 3.创建和配置Cglib Enhancer

Enhancer enhancer = createEnhancer();

if (classLoader != null) {

enhancer.setClassLoader(classLoader);

if (classLoader instanceof SmartClassLoader &&

((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {

enhancer.setUseCache(false);

}

}

// superclass为被代理的目标类proxySuperClass,通过名字可以看出,生成的代理类实际上是继承了被代理类

enhancer.setSuperclass(proxySuperClass);

enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));

enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);

enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));

// 4.获取所有要回调的拦截器

Callback[] callbacks = getCallbacks(rootClass);

Class<?>[] types = new Class<?>[callbacks.length];

for (int x = 0; x < types.length; x++) {

types[x] = callbacks[x].getClass();

}

// fixedInterceptorMap only populated at this point, after getCallbacks call above

// 在上面调用getCallbacks之后,此时仅填充fixedInterceptorMap

enhancer.setCallbackFilter(new ProxyCallbackFilter(

this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));

enhancer.setCallbackTypes(types);

// Generate the proxy class and create a proxy instance.

// 5.生成代理类并创建代理实例,返回代理实例

return createProxyClassAndInstance(enhancer, callbacks);

} catch (CodeGenerationException ex) {

throw new AopConfigException(“Could not generate CGLIB subclass of class [” +

this.advised.getTargetClass() + "]: " +

“Common causes of this problem include using a final class or a non-visible class”,

ex);

} catch (IllegalArgumentException ex) {

throw new AopConfigException(“Could not generate CGLIB subclass of class [” +

this.advised.getTargetClass() + "]: " +

“Common causes of this problem include using a final class or a non-visible class”,

ex);

最后

即使是面试跳槽,那也是一个学习的过程。只有全面的复习,才能让我们更好的充实自己,武装自己,为自己的面试之路不再坎坷!今天就给大家分享一个Github上全面的Java面试题大全,就是这份面试大全助我拿下大厂Offer,月薪提至30K!

我也是第一时间分享出来给大家,希望可以帮助大家都能去往自己心仪的大厂!为金三银四做准备!
一共有20个知识点专题,分别是:

Dubbo面试专题

JVM面试专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

Java并发面试专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

Kafka面试专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

MongDB面试专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

MyBatis面试专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

MySQL面试专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

Netty面试专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

RabbitMQ面试专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

Redis面试专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

Spring Cloud面试专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

SpringBoot面试专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

zookeeper面试专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

常见面试算法题汇总专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

计算机网络基础专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

设计模式专题

这个GItHub上的Java项目开源了,2020最全的Java架构面试复习指南

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

第一时间分享出来给大家,希望可以帮助大家都能去往自己心仪的大厂!为金三银四做准备!**
一共有20个知识点专题,分别是:

Dubbo面试专题

[外链图片转存中…(img-RCjkgosH-1715007365227)]

JVM面试专题

[外链图片转存中…(img-MhUzx2LW-1715007365228)]

Java并发面试专题

[外链图片转存中…(img-tFIQqDih-1715007365228)]

Kafka面试专题

[外链图片转存中…(img-PkKsvrbx-1715007365228)]

MongDB面试专题

[外链图片转存中…(img-sPeIbdqC-1715007365229)]

MyBatis面试专题

[外链图片转存中…(img-HJjychh7-1715007365229)]

MySQL面试专题

[外链图片转存中…(img-N63gkygp-1715007365229)]

Netty面试专题

[外链图片转存中…(img-h4yKgwuo-1715007365229)]

RabbitMQ面试专题

[外链图片转存中…(img-53iad3JQ-1715007365230)]

Redis面试专题

[外链图片转存中…(img-8ggofIUX-1715007365230)]

Spring Cloud面试专题

[外链图片转存中…(img-zduSr6jj-1715007365230)]

SpringBoot面试专题

[外链图片转存中…(img-sYAP4rfN-1715007365231)]

zookeeper面试专题

[外链图片转存中…(img-KHeaLVRS-1715007365231)]

常见面试算法题汇总专题

[外链图片转存中…(img-fjyANYdC-1715007365231)]

计算机网络基础专题

[外链图片转存中…(img-BYhNCn5q-1715007365232)]

设计模式专题

[外链图片转存中…(img-UcZ7dPNX-1715007365232)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

  • 24
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Spring AOP中,拦截器责任链处理过程是指当目标方法被多个通知匹配到时,Spring通过引入拦截器链来保证每个通知的正常执行。拦截器链是由一系列的拦截器组成的,每个拦截器都负责在目标方法的前后执行特定的逻辑。 在码中,拦截器责任链的处理过程主要通过MethodInvocation接口来实现。MethodInvocation接口提供了proceed()方法,用于执行拦截器链中下一个拦截器的逻辑。当调用proceed()方法时,会按照拦截器链的顺序依次执行每个拦截器的逻辑,直到达到链的末尾或者某个拦截器决定终止链的执行。 在拦截器责任链处理过程中,每个拦截器可以在目标方法的调用前后执行自定义的逻辑。拦截器可以对方法的参数进行检查、修改方法的返回值,或者在方法执行前后记录日志等操作。通过拦截器责任链的处理,Spring AOP能够实现面向切面编程的功能。 需要注意的是,拦截器链的执行顺序是根据拦截器的配置顺序确定的。在Spring的配置文件中,可以通过配置拦截器的顺序来控制拦截器链的执行顺序。这样可以确保每个拦截器按照预期的顺序执行,从而达到期望的功能效果。 总结起来,Spring AOP码的拦截器责任链处理过程主要通过MethodInvocation接口实现,它通过调用proceed()方法来依次执行拦截器链中每个拦截器的逻辑。拦截器链的执行顺序可以通过配置文件来控制,从而实现面向切面编程的功能。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Spring AOP码:拦截器责任链处理过程](https://blog.csdn.net/weixin_45031612/article/details/128806966)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [Spring AOP 自动代理码 DefaultAdvisorAutoProxyCreator](https://download.csdn.net/download/weixin_38530536/14854229)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [【SpringSpring AOP 码分析-拦截器链的执行过程(四)](https://blog.csdn.net/qq_46514118/article/details/121912507)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值