spring之AOP源码解析

代码使用

package com.kcwl.klj.aspect;

@Aspect  //切面
@Component
@Slf4j
public class LogAspect {

    @Resource
    private KcwlSysLogServiceImpl kcwlSysLogService;

    //切点,切点里面写的是连接点的表达式
    // aop要作用到哪些方法上去呢?在下行的括号中进行描述,括号中的就是连接点,连接点的集合就是切点
    //可以这样理解:括号中的是连接点的表达式,该表达式会指向多个方法或者类,这些都是一条一条的数据,
    // 切点这个@PointCut是一张表,表中记录了多行数据
    @Pointcut("@annotation(com.kcwl.klj.annotation.OptLog)")
    public void aspectLog() {
    }

    //AfterReturning 表示在aspectLog()的这些连接点返回之后打印aop
    @AfterReturning("aspectLog()")
    public void insertLog(JoinPoint joinPoint) {
        //从切面织入点处通过反射机制获取织入点处的方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        //获取切入点所在的方法
        Method method = signature.getMethod();
        //获取操作
        OptLog optLog = method.getAnnotation(OptLog.class);
    }
}

源码

入口

public class SpringMain {

    public static void main(String[] args) {

        //初始化spring容器  在初始化的时候完成了依赖注入
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringTest.class);
        //下面这样代码我们需要注意,在getBean去get  IndexService这个bean之前,上面的那样代码已经get过一次IndexService这个bean了。
        //但是上面那行代码主要作用是初始化所有的bean,为什么还会执行get bean的方法呢?因为那行代码中要执行create 去创建bean的方法,在执行create之前需要先get一下判断是否已经创建完成这个bean
        System.out.println(context.getBean(IndexService.class));

    }
}

context.getBean(xxx.class)

在这里插入图片描述

1.查看getBeanFactory方法获取到的factory是什么

在这里插入图片描述
在这里插入图片描述
this.beanFactory则是指当前类的beanFactory属性,即下图中的属性,即DefaultListableBeanFactory
在这里插入图片描述

2.查看getBeanFactory.getBean()的源码

在这里插入图片描述
在这里插入图片描述

resolveBean()

 @Nullable
    private <T> T resolveBean(ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) {
        //NamedBeanHolder 可以理解为数据结构和map差不多,里面存了bean的名字和bean的实例
        //resolveNamedBean(xxxxx)该方法里面就已经实现了对bean的代理
        NamedBeanHolder<T> namedBean = this.resolveNamedBean(requiredType, args, nonUniqueAsNull);
        if (namedBean != null) {
            return namedBean.getBeanInstance();
        } else {
            BeanFactory parent = this.getParentBeanFactory();
            if (parent instanceof DefaultListableBeanFactory) {
                return ((DefaultListableBeanFactory)parent).resolveBean(requiredType, args, nonUniqueAsNull);
            } else if (parent != null) {
                ObjectProvider<T> parentProvider = parent.getBeanProvider(requiredType);
                if (args != null) {
                    return parentProvider.getObject(args);
                } else {
                    return nonUniqueAsNull ? parentProvider.getIfUnique() : parentProvider.getIfAvailable();
                }
            } else {
                return null;
            }
        }
    }

resolveNamedBean()

@Nullable
    private <T> NamedBeanHolder<T> resolveNamedBean(ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) throws BeansException {
        Assert.notNull(requiredType, "Required type must not be null");
        //根据bean的类型获取bean
        String[] candidateNames = this.getBeanNamesForType(requiredType);
        String[] var6;
        int var7;
        int var8;
        String beanName;
        //如果数组的长度大于1,说明获取到了这个类型的bean有多个
        if (candidateNames.length > 1) {
            List<String> autowireCandidates = new ArrayList(candidateNames.length);
            var6 = candidateNames;
            var7 = candidateNames.length;

            for(var8 = 0; var8 < var7; ++var8) {
                beanName = var6[var8];
                if (!this.containsBeanDefinition(beanName) || this.getBeanDefinition(beanName).isAutowireCandidate()) {
                    autowireCandidates.add(beanName);
                }
            }

            if (!autowireCandidates.isEmpty()) {
                candidateNames = StringUtils.toStringArray(autowireCandidates);
            }
        }

        //如果数组的长度等于1,说明该类型的bean只有1个,而且我们获取到了,那我们就将他封装为NamedBeanHolder返回,结束当前方法
        if (candidateNames.length == 1) {
            String beanName = candidateNames[0];
            //下面这行代码中的this.getBean(beanName, requiredType.toClass(), args)这个方法才是真正获取bean的方法
            return new NamedBeanHolder(beanName, this.getBean(beanName, requiredType.toClass(), args));
        } else {
            //否则如果长度大于1,则走下面的逻辑
            if (candidateNames.length > 1) {
            xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
            }

            return null;
        }
    }

上面代码中的this.getBean(beanName, requiredType.toClass(), args)方法最终走到了这儿
在这里插入图片描述
上图中的doGetBean中的第一行代码如下:这行代码的作用是什么?
String beanName = this.transformedBeanName(name);

通过name获取beanName,这里不使用name直接作为beanName的原因有两点:
1.name可能会以&字符开头,表明调用者想获取factoryBean本身,而不是获取factoryBean实现类所创建的bean。在BeanFactory中,factoryBean的实现类和其他bean的存储方式是一致的,即<beanName,bean>,beanName中是没有&字符的。所以我们需要将name的首字符&移除,这样才能从缓存中获取到FactoryBean实例。

2.还是别名的问题,转换需要

接下来,执行了this.getSingleton(beanName)方法,该方法是去三个map中获取bean,此时拿出来的bean就已经是代理过的bean了。
说明什么?
说明在AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringTest.class);这样代码中就已经完成了代理并将代理后的bean放在了单例池中。
现在我们找一下在哪一步往单例池中放bean了
通过搜索我们可以看到下面的情况
在这里插入图片描述
找到了put bean的地方
在这里插入图片描述
我们继续往上找
最终发现是在createBean方法中将对象创建为代理对象的
在这里插入图片描述
在该方法中有一行代码如下
beanInstance = this.doCreateBean(beanName, mbdToUse, args);
该行代码实现了bean的创建,注意,如果只是创建bean则会将bean创建出来,如果该bean是被aop了,则会创建bean和这个bean的代理对象bean。

doCreateBean()

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
        //BeanWrapper相当于是bean的包装类  类似于有一个A类,类里面有一个Object B = new Object(),bean就是里面的B。我们通过BeanWrapper 的其他方法可以获取到B这个属性,就可以获取到bean了
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
        }

        if (instanceWrapper == null) {
            instanceWrapper = this.createBeanInstance(beanName, mbd, args);
        }

        //下面这行方法就是使用BeanWrapper获取到里面的B这个属性,就是bean这个原身属性
        Object bean = instanceWrapper.getWrappedInstance();
        Class<?> beanType = instanceWrapper.getWrappedClass();
        if (beanType != NullBean.class) {
            mbd.resolvedTargetType = beanType;
        }

        synchronized(mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                try {
                    this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                } catch (Throwable var17) {
                    throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", var17);
                }

                mbd.postProcessed = true;
            }
        }

        boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
        if (earlySingletonExposure) {
            if (this.logger.isTraceEnabled()) {
                this.logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
            }

            this.addSingletonFactory(beanName, () -> {
                return this.getEarlyBeanReference(beanName, mbd, bean);
            });
        }

        //将bean赋值给了exposedObject这个对象
        Object exposedObject = bean;

        try {
            //设置属性,非常重要
            this.populateBean(beanName, mbd, instanceWrapper);
            //执行后置处理器,aop就是在这里完成的处理  执行完这行代码之后,exposedObject中的bean的属性值就变成了代理的bean了
            exposedObject = this.initializeBean(beanName, exposedObject, mbd);
        } catch (Throwable var18) {
            if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
                throw (BeanCreationException)var18;
            }

            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
        }

        if (earlySingletonExposure) {
            Object earlySingletonReference = this.getSingleton(beanName, false);
            if (earlySingletonReference != null) {
                if (exposedObject == bean) {
                    exposedObject = earlySingletonReference;
                } else if (!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) {
                    String[] dependentBeans = this.getDependentBeans(beanName);
                    Set<String> actualDependentBeans = new LinkedHashSet(dependentBeans.length);
                    String[] var12 = dependentBeans;
                    int var13 = dependentBeans.length;

                    for(int var14 = 0; var14 < var13; ++var14) {
                        String dependentBean = var12[var14];
                        if (!this.removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                            actualDependentBeans.add(dependentBean);
                        }
                    }

                    if (!actualDependentBeans.isEmpty()) {
                        throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
                    }
                }
            }
        }

        try {
            this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
            return exposedObject;
        } catch (BeanDefinitionValidationException var16) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);
        }
    }

BeanWrapper

public interface BeanWrapper extends ConfigurablePropertyAccessor {
    void setAutoGrowCollectionLimit(int var1);

    int getAutoGrowCollectionLimit();

    ---------------------BeanWrapper的重要的两个方法------------------------------------
    Object getWrappedInstance();

    Class<?> getWrappedClass();
	----------------------BeanWrapper的重要的两个方法-----------------------------------
    PropertyDescriptor[] getPropertyDescriptors();

    PropertyDescriptor getPropertyDescriptor(String var1) throws InvalidPropertyException;
}

在这里插入图片描述

完成aop的代码

exposedObject = this.initializeBean(beanName, exposedObject, mbd);
在这里插入图片描述

initializeBean()

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged(() -> {
                this.invokeAwareMethods(beanName, bean);
                return null;
            }, this.getAccessControlContext());
        } else {
            this.invokeAwareMethods(beanName, bean);
        }

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            //第七次执行后置处理器,执行后置处理的before
            wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
        }

        try {
            //执行bean的 生命周期回调中的init  例如 @PostConstruct
            this.invokeInitMethods(beanName, wrappedBean, mbd);
        } catch (Throwable var6) {
            throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
        }

        if (mbd == null || !mbd.isSynthetic()) {
            //执行第八次后置处理器,执行后置处理器的after方法
            wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }

        return wrappedBean;
    }

在这里插入图片描述

applyBeanPostProcessorsAfterInitialization()实现了aop代理

   public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
        Object result = existingBean;

        Object current;
        for(Iterator var4 = this.getBeanPostProcessors().iterator(); var4.hasNext(); result = current) {
            BeanPostProcessor processor = (BeanPostProcessor)var4.next();
            current = processor.postProcessAfterInitialization(result, beanName);
            if (current == null) {
                return result;
            }
        }

        return result;
    }

AnnotationAwareAspectJAutoProxyCreator

当BeanPostProcessor 为AnnotationAwareBeanPostProcessor的时候,current变成了代理bean
在这里插入图片描述
走进这个后置处理器的postProcessAfterInitialization方法
该后置处理器继承了AbstractAutoProxyCreator这个抽象父类,走的是父类的postProcessAfterInitialization这个方法

public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
        if (bean != null) {
            Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
            if (this.earlyProxyReferences.remove(cacheKey) != bean) {
                return this.wrapIfNecessary(bean, beanName, cacheKey);
            }
        }

        return bean;
    }

wrapIfNecessary

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
            return bean;
        } else if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
            return bean;
        } else if (!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) {
            Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);
            if (specificInterceptors != DO_NOT_PROXY) {
                this.advisedBeans.put(cacheKey, Boolean.TRUE);
                //通过该行代码实现了代理bean的创建
                Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
                this.proxyTypes.put(cacheKey, proxy.getClass());
                return proxy;
            } else {
                this.advisedBeans.put(cacheKey, Boolean.FALSE);
                return bean;
            }
        } else {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }
    }

createProxy 创建代理对象

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);
        }

    	//创建了一个代理工厂factory
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.copyFrom(this);
        if (!proxyFactory.isProxyTargetClass()) {
            if (this.shouldProxyTargetClass(beanClass, beanName)) {
                proxyFactory.setProxyTargetClass(true);
            } else {
                this.evaluateProxyInterfaces(beanClass, proxyFactory);
            }
        }

        Advisor[] advisors = this.buildAdvisors(beanName, specificInterceptors);
        proxyFactory.addAdvisors(advisors);
        proxyFactory.setTargetSource(targetSource);
        this.customizeProxyFactory(proxyFactory);
        proxyFactory.setFrozen(this.freezeProxy);
        if (this.advisorsPreFiltered()) {
            proxyFactory.setPreFiltered(true);
        }

        return proxyFactory.getProxy(this.getProxyClassLoader());
    }

this.getProxyClassLoader()这行代码的作用是什么?

为了动态加载类

我们最开始的target类是被classloader所加载的,但是如果创建代理对象的话,该代理对象proxy是没有被classloader所加载的,因此需要一个代理对象的classloader。

getProxy

public Object getProxy(@Nullable ClassLoader classLoader) {
        return this.createAopProxy().getProxy(classLoader);
    }

createAopProxy

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

      //获取aop代理工厂,调用工厂的创建aop代理的方法去创建代理对象
        return this.getAopProxyFactory().createAopProxy(this);
    }

createAopProxy

下面为createAopProxy方法所在的类的全部代码

public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
    public DefaultAopProxyFactory() {
    }

    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        //config.isOptimize() 恒定返回false
        //config.isProxyTargetClass()获取的是注解:@EnableAspectJAutoProxy(proxyTargetClass = true)中的true还是false,默认是false
        //this.hasNoUserSuppliedProxyInterfaces(config)  恒定为false
        if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
            return new JdkDynamicAopProxy(config);
        } else {
            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.");
            } else {
                return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));
            }
        }
    }

    private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
        Class<?>[] ifcs = config.getProxiedInterfaces();
        return ifcs.length == 0 || ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0]);
    }
}

AopProxy

是一个接口
在这里插入图片描述

public interface AopProxy {
    Object getProxy();

    Object getProxy(@Nullable ClassLoader var1);
}

为什么需要这个注解@EnableAspectJAutoProxy(proxyTargetClass = true)

在创建proxy代理工厂的时候,源码中会获取该注解上的proxyTargetClass的值,如果是false,则直接创建了JdkDynamicAopProxy -----jdk的动态代理。

如果为true,则判断如果target不是接口,当前target也不是代理类型的类的话,就创建ObjenesisCglibAopProxy,反之则创建JdkDynamicAopProxy。

JdkDynamicAopProxy jdk动态代理代理对象的方法

在这里插入图片描述

Proxy.newProxyInstance()

该方法已经是jdk的底层源码了
在这里插入图片描述

BeanPostProcessor

是一个接口,有非常多的类实现了这个接口
在这里插入图片描述
我们也可以自己写一个类实现该接口,重写里面的方法,就可以实现对bean的改造

在这里插入图片描述

面试题

aop和springaop有什么区别?

aop:编程目标。面向切面编程

springaop:实现目标的手段。除此之外AspectJ,手写一个JDK动态代理也可以实现aop

spring在2.5之前有自己的aop,但是非常复杂,于是借助了aspectj的语法完成了springaop的编程

aop的概念

aspect:切面

join point:连接点。比如我们添加了@A注解的方法要实现aop里的逻辑,那么被添加了@A注解的那些方法,每个方法都是一个连接点。

advice:通知

point cut:切点(连接点的集合)。一个连接点是一个方法,所有的方法加起来就是切点。

target:目标对象

weaving:织入。 A类中的a方法被加上了注解要实现aop,那么a就是连接点,A就是目标对象,advice通知A目标对象的过程就是织入。

proxy:代理

introduction:引入

springAop默认是什么代理?

可配置的,spring底层没有默认的配置,会看我们的机制是什么就用什么代理

@ComponentScan("com.guo.admin.web.spring")
@EnableAspectJAutoProxy(proxyTargetClass = true)//true则使用cglib代理
public class SpringTest {
    
}

如果这一行代码没有配置的话,则如果是实现了接口,则使用jdk动态代理,如果没有实现接口,则使用cglib代理

AOP五种通知

before在连接点前面执行,前置通知不会影响连接点的执行,除非此处抛出异常。

after在连接点执行完成后执行,不管是正常执行完成,还是抛出异常,都会执行返回通知中的内容。

after returning在连接点正常执行完成后执行,如果连接点抛出异常,则不会执行。

after throwing 连接点抛出异常后执行。

around环绕通知围绕在连接点前后,比如一个方法调用的前后。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GYX--UP

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值