spring源码阅读--aop实现原理分析

12 篇文章 18 订阅
订阅专栏

aop实现原理简介

首先我们都知道aop的基本原理就是动态代理思想,在 设计模式之代理模式中有介绍过这两种动态代理的使用与基本原理,再次不再叙述。

这里分析的是,在spring中是如何基于动态代理的思想实现aop的。为了方便了解接下来的源码分析,这里简单化了一个流程图分析aop的基本实现思想。


在这里插入图片描述

so,基于上面的流程,一步步分析spring源码中的aop实现方式。

采用一个简单的aop例子,利用基于注解配置方式的切面配置,分析一个简单的Before AOP例子。在spring boot下运行以下简单例子。

AOP的advisor和advice配置。

@Component
@Aspect
public class AopConfig {

    @Pointcut("execution(* com.garine.debug.testcase.model.AopObject..*(..))")
    public void mypoint(){
        //切面定义
    }

    @Before("mypoint()")
    public void doAround() throws Throwable {
        System.out.println("before logic");
    }
}

AopObject,被代理拦截对象。

@Component
public class AopObject {

    public void aoped(){
        System.out.println("logic");
    }
}

代理实现的处理器(BeanPostProcessor)

首先是第一步内容,对我们在AopConfig中的AOP配置内容进行解析并且保存到BeanFactory中,这个过程就是解析保存切面信息。

代理实现的源头–AnnotationAwareAspectJAutoProxyCreator

经过一遍的代码跟踪,我了解到注解方式的AOP配置,都离不开一个类–AnnotationAwareAspectJAutoProxyCreator,这个类继承了BeanPostProcessor接口,我们都知道BeanPostProcessor的实现类有多个执行处理节点,其中一个执行节点就是在Bean实例化之后。也就是在这个时机AnnotationAwareAspectJAutoProxyCreator拦截bean的初始化过程,根据提前解析得到的切面信息,对bean的方法进行尝试适配,如果有匹配则需要进行代理创建。

这里先分析的就是AnnotationAwareAspectJAutoProxyCreator,在bean实例化第一次查询所有切面信息时,就会解析保存Aop的信息到实例中,跟踪以下代码。

  • AbstractApplicationContext#refresh (上下文初始化主干方法)
    • AbstractApplicationContext#registerBeanPostProcessors (执行实例化并保存所有实现BeanPostProcessor接口的类

按照上面的逻辑,registerBeanPostProcessors 会比一般的bean实例化逻辑要早执行,因此我们接下来只需要分析AnnotationAwareAspectJAutoProxyCreator的初始化过程。

AnnotationAwareAspectJAutoProxyCreator的继承结构


在这里插入图片描述

通过上图可以知道,AnnotationAwareAspectJAutoProxyCreator是继承了BeanfactoryAware接口,所以在实例化时,会执行setFactory方法。而所有切面信息解析的执行者BeanFactoryAspectJAdvisorsBuilderAdapter初始化的时机也是在setFactory方法。

跟踪代码如下。

  • AbstractAdvisorAutoProxyCreator#setBeanFactory
    • AnnotationAwareAspectJAutoProxyCreator#initBeanFactory

在这个方法里面会新建一个BeanFactoryAspectJAdvisorsBuilderAdapter,这个对象会根据Beanfactory内的aop配置信息,进行解析保存。但是需要注意,此时虽然新建了BeanFactoryAspectJAdvisorsBuilderAdapter对象.但是此时还不会马上解析aop配置,需要在第一次个普通bean实例化时才执行解析aop配置。解析的方法就是

BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors,会在初次执行AnnotationAwareAspectJAutoProxyCreator调用postProcessBeforeInitialization时开始执行。

protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
   super.initBeanFactory(beanFactory);
    //aspectJAdvisorsBuilder#buildAspectJAdvisors就是解析配置入口
   this.aspectJAdvisorsBuilder =
         new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
}

代理对象(Proxy)的创建

解析并缓存切面

上面提到继承结构图中,AnnotationAwareAspectJAutoProxyCreator是实现了InstantiationAwareBeanPostProcessor接口的,InstantiationAwareBeanPostProcessor接口定义的postProcessBeforeInitialization方法是一个可以对已经注入依赖属性的bean对象实例进行编辑操作的接口,会在

  • AbstractAutowireCapableBeanFactory#doCreateBean
    • AbstractAutowireCapableBeanFactory#initializeBean(String, Object, RootBeanDefinition)
      • AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInstantiation

方法中执行InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation,初次初始化缓存切面信息的话就是在这个方法里面。。具体的调用链如上所示。这里的postProcessBeforeInstantiation方法实际上是AnnotationAwareAspectJAutoProxyCreator的实例进行调用,AnnotationAwareAspectJAutoProxyCreator实现InstantiationAwareBeanPostProcessor接口。

下面进入InstantiationAwareBeanPostProcessor#postProcessBeforeInitialization方法分析代码。

  • AbstractAutoProxyCreator#postProcessBeforeInstantiation
    • AspectJAwareAdvisorAutoProxyCreator#shouldSkip (关键代码)

进入如下代码AbstractAutoProxyCreator,这个实例也就是之前一开始初始化的AnnotationAwareAspectJAutoProxyCreator实例,进入实例的shouldSkip 方法,

	@Override
	protected boolean shouldSkip(Class<?> beanClass, String beanName) {
		// TODO: Consider optimization by caching the list of the aspect names
        //预先解析缓存切面信息
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
		for (Advisor advisor : candidateAdvisors) {
			if (advisor instanceof AspectJPointcutAdvisor) {
				if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {
					return true;
				}
			}
		}
		return super.shouldSkip(beanClass, beanName);
	}
  • AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors

方法findCandidateAdvisors代码如下,这里是预先解析缓存所有切面advisor信息,注意这一步操作是在AbstractAutoProxyCreator#postProcessBeforeInitialization处理,也就是开头提到的切面解析操作,解析完成就进行缓存。

@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.
    //这里就是前面提到的BeanFactoryAspectJAdvisorsBuilder解析所有切面信息的调用点
   advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
   return advisors;
}

然后继续在这里先提前看一下是如何解析aop配置的。跟踪BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors

public List<Advisor> buildAspectJAdvisors() {
   List<String> aspectNames = null;

   synchronized (this) {
      aspectNames = this.aspectBeanNames;
      if (aspectNames == null) {
         List<Advisor> advisors = new LinkedList<Advisor>();
         aspectNames = new LinkedList<String>();
          //查询出Beanfactory中所有已经注册的BeanName
         String[] beanNames =
               BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);
         for (String beanName : beanNames) {
            if (!isEligibleBean(beanName)) {
               continue;
            }
            // We must be careful not to instantiate beans eagerly as in this
            // case they would be cached by the Spring container but would not
            // have been weaved
            Class<?> beanType = this.beanFactory.getType(beanName);
            if (beanType == null) {
               continue;
            }
             //判断Bean是否是切面Bean,isAspect方法判断[标注1]
            if (this.advisorFactory.isAspect(beanType)) {
               aspectNames.add(beanName);
               AspectMetadata amd = new AspectMetadata(beanType, beanName);
               if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
                  MetadataAwareAspectInstanceFactory factory =
                        new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
                   //解析aop class的配置,包返回Advisor对象[标注2]
                  List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
                  if (this.beanFactory.isSingleton(beanName)) {
                     this.advisorsCache.put(beanName, classAdvisors);
                  }
                  else {
                     this.aspectFactoryCache.put(beanName, factory);
                  }
                  advisors.addAll(classAdvisors);
               }
               else {
                  // Per target or per this.
                  if (this.beanFactory.isSingleton(beanName)) {
                     throw new IllegalArgumentException("Bean with name '" + beanName +
                           "' is a singleton, but aspect instantiation model is not singleton");
                  }
                  MetadataAwareAspectInstanceFactory factory =
                        new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
                  this.aspectFactoryCache.put(beanName, factory);
                  advisors.addAll(this.advisorFactory.getAdvisors(factory));
               }
            }
         }
         this.aspectBeanNames = aspectNames;
         return advisors;
      }
   }

   if (aspectNames.isEmpty()) {
      return Collections.emptyList();
   }
   List<Advisor> advisors = new LinkedList<Advisor>();
   for (String aspectName : aspectNames) {
      List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
      if (cachedAdvisors != null) {
         advisors.addAll(cachedAdvisors);
      }
      else {
         MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
         advisors.addAll(this.advisorFactory.getAdvisors(factory));
      }
   }
   return advisors;
}

**[标注1]如何判断类是否是aop切面配置类? **

通过以下代码。

@Override
public boolean isAspect(Class<?> clazz) {
   return (hasAspectAnnotation(clazz) && !compiledByAjc(clazz));
}

private boolean hasAspectAnnotation(Class<?> clazz) {
    //包含@Aspect注解
   return (AnnotationUtils.findAnnotation(clazz, Aspect.class) != null);
}

[标注2]如何解析为Advisor对象?

  • ReflectiveAspectJAdvisorFactory#getAdvisors 遍历所有没被@PointCut注解标注的方法,也就是遍历切面内容方法
    • ReflectiveAspectJAdvisorFactory#getAdvisor 处理所有没被@PointCut注解标注的方法,候选切面内容方法

代码如下。

@Override
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
      int declarationOrderInAspect, String aspectName) {

   validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
   //解析判断候选方法是否有@Before,@After,@Around等注解,如果有,就继续执行新建Advisor对象。
   AspectJExpressionPointcut expressionPointcut = getPointcut(
         candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
   if (expressionPointcut == null) {
      return null;
   }
//创建advisor
   return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
         this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}

最终循环解析,@Before,@After,@Around等标注的方法都会新建一个Advisor对象。新建的Advisor对象都保存在BeanFactoryAspectJAdvisorsBuilder#advisorsCache中,当AnnotationAwareAspectJAutoProxyCreator拦截bean的创建过程时,从这里面适配是否有切面可用。

这里解析得到的Advisor,大概有以下信息。下面的信息中,并没有对@PointCut注解做处理,pointCut属性只得出一个"mypoint()",此时还不知道Advisor实际对应的拦截表达式。


在这里插入图片描述

拦截表达式还是空的,会在AnnotationAwareAspectJAutoProxyCreator#postProcessAfterInstantiation第一次执行时解析拦截表达式。


在这里插入图片描述

适配切面

在AbstractAutoProxyCreator#postProcessAfterInitialization执行时,找到上面AbstractAutoProxyCreator#postProcessBeforeInitialization缓存的所有的切面信息,之后是如何进行切面适配,从而决定是否需要进行代理对象的创建呢?

在调用AbstractAutoProxyCreator#postProcessAfterInitialization方法时,进行切面适配,并且会根据适配创建代理对象。根据以下调用链。

  • AbstractAutoProxyCreator#postProcessAfterInitialization

    • AbstractAutoProxyCreator#wrapIfNecessary

      protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
         if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
            return bean;
         }
         if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
            return bean;
         }
         if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
         }
      
         // Create proxy if we have advice.
          //查找匹配切面
         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;
      }
      
      • AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean
        • AbstractAdvisorAutoProxyCreator#findEligibleAdvisors
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    //从缓存取出所有切面信息
   List<Advisor> candidateAdvisors = findCandidateAdvisors();
    //根据advisor信息中的表达式进行方法对class的匹配
   List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
   extendAdvisors(eligibleAdvisors);
   if (!eligibleAdvisors.isEmpty()) {
      eligibleAdvisors = sortAdvisors(eligibleAdvisors);
   }
   return eligibleAdvisors;
}

此时如果是第一次执行适配方法findAdvisorsThatCanApply的话,candidateAdvisors中的拦截表达式还是空的,需要进行表达式获取,也就是@Pointcut的value。spring的操作的在第一次执行findAdvisorsThatCanApply时解析获取拦截表达式的值,获得拦截表达式值之后就跟当前class的方法进行匹配看是否需要进行代理。继续往下跟踪代码

  • AopUtils#canApply(org.springframework.aop.Advisor, java.lang.Class<?>, boolean)
    • AopUtils#canApply(org.springframework.aop.Pointcut, java.lang.Class<?>, boolean)
      • AspectJExpressionPointcut#getClassFilter
        • AspectJExpressionPointcut#checkReadyToMatch
private void checkReadyToMatch() {
   if (getExpression() == null) {
      throw new IllegalStateException("Must set property 'expression' before attempting to match");
   }
   if (this.pointcutExpression == null) {
      this.pointcutClassLoader = (this.beanFactory instanceof ConfigurableBeanFactory ?
            ((ConfigurableBeanFactory) this.beanFactory).getBeanClassLoader() :
            ClassUtils.getDefaultClassLoader());
       //解析得到拦截表达式,例如根据@Before的value来关联查询出对应的表达式
      this.pointcutExpression = buildPointcutExpression(this.pointcutClassLoader);
   }
}

最终解析完之后,advisor中的表达式信息结构如下图。包含在pointcut属性中,匹配时就根据pointcutExpression循环进行匹配class的方法。有兴趣的可以继续调试看看是如何实现匹配表达式的。

在这里插入图片描述

##  创建代理对象

如果在上面的匹配切面过程中,发现适配的切面,那就需要进行代理对象的创建了。

我们回到上面的AbstractAutoProxyCreator#wrapIfNecessary,主要看代码如下。

  // Create proxy if we have advice.
    //查找匹配切面
   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;
   }

所以,继续看

  • AbstractAutoProxyCreator#createProxy

的创建代理对象方法。设置ProxyFactory创建Proxy需要的一切信息。

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

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

    //新建代理对象工厂
   ProxyFactory proxyFactory = new ProxyFactory();
   proxyFactory.copyFrom(this);

    //设置工厂代理类
   if (!proxyFactory.isProxyTargetClass()) {
      if (shouldProxyTargetClass(beanClass, beanName)) {
         proxyFactory.setProxyTargetClass(true);
      }
      else {
         evaluateProxyInterfaces(beanClass, proxyFactory);
      }
   }

    //设置拦截切面
   Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
   for (Advisor advisor : advisors) {
      proxyFactory.addAdvisor(advisor);
   }

    //设置被代理对象
   proxyFactory.setTargetSource(targetSource);
   customizeProxyFactory(proxyFactory);
   proxyFactory.setFrozen(this.freezeProxy);
   if (advisorsPreFiltered()) {
      proxyFactory.setPreFiltered(true);
   }
//创建代理对象
   return proxyFactory.getProxy(getProxyClassLoader());
}

下面看ProxyFactory是如何创建代理对象,继续跟踪proxyFactory.getProxy(getProxyClassLoader());

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

createAopProxy()作用是根据class的种类判断采用的代理方式,看如下实现

  • DefaultAopProxyFactory#createAopProxy

    @Override
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    	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.");
    		}
    		if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
                //采用jdk动态代理必须基于接口
    			return new JdkDynamicAopProxy(config);
    		}
            //基于cglib实现代理不需要接口
    		return new ObjenesisCglibAopProxy(config);
    	}
    	else {
    		return new JdkDynamicAopProxy(config);
    	}
    }
    

所以在当前调试的例子中,使用cglib代理。所以执行如下代理。

@Override
public Object getProxy(ClassLoader classLoader) {
     //。。。。。。
      // Configure CGLIB Enhancer...
      Enhancer enhancer = createEnhancer();
      if (classLoader != null) {
         enhancer.setClassLoader(classLoader);
         if (classLoader instanceof SmartClassLoader &&
               ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
            enhancer.setUseCache(false);
         }
      }
      enhancer.setSuperclass(proxySuperClass);
      enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
      enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
      enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
	//获取拦截回调函数
      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
      enhancer.setCallbackFilter(new ProxyCallbackFilter(
            this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
      enhancer.setCallbackTypes(types);

      // Generate the proxy class and create a proxy instance.
    //返回一个cglib代理对象
      return createProxyClassAndInstance(enhancer, callbacks);
   }
   catch (CodeGenerationException ex) {
       //、、、、、、
   }
}

getCallbacks(rootClass);在这个获取回调函数的方法中,普通的aop采用的回调函数是如下的方式。

// Choose an "aop" interceptor (used for AOP calls).
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);

cglib 的aop回调函数如下。

public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
   Object oldProxy = null;
   boolean setProxyContext = false;
   Class<?> targetClass = null;
   Object target = null;
   try {
       //这里注入的advised就是之前创建的ProxyFactory对象
      if (this.advised.exposeProxy) {
         // Make invocation available if necessary.
         oldProxy = AopContext.setCurrentProxy(proxy);
         setProxyContext = true;
      }
      // May be null. Get as late as possible to minimize the time we
      // "own" the target, in case it comes from a pool...
      target = getTarget();
      if (target != null) {
         targetClass = target.getClass();
      }
       //根据切面信息创建切面内容调用链
      List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
      Object retVal;
      // Check whether we only have one InvokerInterceptor: that is,
      // no real advice, but just reflective invocation of the target.
      if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
         // 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 = methodProxy.invoke(target, argsToUse);
      }
      else {
         // We need to create a method invocation...
          //创建一个方法调用对象,具体调用实现没分析,Before逻辑大概是先调用切面,在反射调用目标方法
         retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
      }
      retVal = processReturnType(proxy, target, method, retVal);
      return retVal;
   }
   finally {
      if (target != null) {
         releaseTarget(target);
      }
      if (setProxyContext) {
         // Restore old proxy.
         AopContext.setCurrentProxy(oldProxy);
      }
   }
}
spring源码解析之AOP原理
韩猿外的博客
06-05 755
上一步我发现AnnotationAwareAspectJAutoProxyCreator在所有bean创建时进行了拦截,执行其的postProcessBeforeInstantiation方法,接下来我们继续通过断点调试查看该方法的进行的操作。我们继续完善之前的流程.。创建代理对象过程,会先创建一个代理工厂,获取到所有的增强器(通知方法),将这些增强器和目标类注入代理工厂,再用代理工厂创建对象。我们细看创建代理对象的过程,发现在创建之前首先会根据切入点表达式对增强器进行一一匹配,最终拿到所有的增强器。
spring源码解析】SpringAOP 框架原理
worn_xiao的博客
02-18 406
SpringAOP框架与实现原理 一 什么是AOP Aop面向切面编程,使用AOP我们可以对类似于日志,风控等系统需求进行模块化组织。简化系统需求与实现之间的对比关系。进而使得整个系统的实现更具模块化。使用传统的方式我们无法对类似日志,安全检查,事务管理等的横切关注点进行组织和实现。所以AOP引入了Aspect的概念。用来以模块化的方式对系统进行组织和封装。简单的说就是一些所有业务操作的公共操作。 二 SpringAOP的公民 2.1 joinPoint 连接点 系统运行之前AOP...
Spring AOP源码解析
m289111782的博客
05-05 189
AOP(Aspect-Oriented Programming:面向切面编程)能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。Spring AOP 就是基于动态代理的,如果要代理的对象,实现了某个接口,那么 Spring AOP 会使用JDK Proxy。
spring源码分析Aop
Evan's Blog ٩(๑❛ᴗ❛๑)۶
11-01 2127
今天读spring源码,读到aop相关内容,在此记录一下,以便以后复习和查阅。 一、spring如何实现Aop 这里简单的说下原理spring实例化bean要经历一套完整的生命周期,在这个过程会对要实例化的bean进行各种各样的处理,例如先new对象、进行属性注入、处理循环依赖、处理生命周期回调、实现Aop等等。这些操作实际都是通过spring的后置处理器,也就是通过BeanPostP...
Java:由浅入深揭开 AOP 实现原理
Java笔记虾
11-18 1085
概述: 最近在开发遇到了一个刚好可以用AOP实现的例子,就顺便研究了AOP实现原理,把学习到的东西进行一个总结。文章用到的编程语言为kotlin,需要的可以在IDEA直接转为java。 这篇文章将会按照如下目录展开: AOP简介 代码实现举例 AOP实现原理 部分源码解析 1. AOP简介 相信大家或多或少的了解过AOP,都知道它是面向...
Spring框架系列(9) - Spring AOP实现原理详解之AOP切面的实现.doc
07-08
分析 Spring AOP源码之前,我们需要了解 Spring IOC 的初始化过程和 Bean 的生命周期等。AOP 是基于 IOC 的 Bean 加载来实现的,所以理解 Spring AOP 的初始化必须要先理解 Spring IOC 的初始化。 二、AOP ...
深入解析Spring AOP源码:从原理到实现,全方位掌握Java AOP编程精髓
最新发布
12-13
Spring AOP(面向切面编程)作为Spring框架的一个重要部分,为Java开发者提供了一个...通过对Spring AOP源码的深入分析,我们可以更好地理解其内部工作原理,从而在实际开发更加灵活和高效地使用这一强大的编程范式。
合集Java流行框架分析Spring源码SpringBoot源码SpringAOP源码
11-01
Java流行框架分析,学习以及源码总结。项目持续更新,不建议直接Fork,欢迎star、watch。 对于框架底层的学习,需要反复、认真思考,并做到温故而知新,这样才能将底层原理吸收得更早。 学习一个框架的源码,...
spring-annotion:Spring源码分析以及注解开发
03-24
ext扩展原理包含beanFactoryPostProcessor,BeanDefinitionRegistryPostProcessor和事件监听器等---> tx Spring声明式事务模块---> config AOP IOC已经一些bean的流程配置模块--->启动也包含SpringMVC注解...
AOP实现原理
Mr.BoBo的博客
08-21 2835
AOP原理 简介 AOP(Aspect-OrientedProgramming)面向切面编程,可以理解为OOP的改进和完善,其编程思想是把散布于不同业务但功能相同的代码从业务逻辑抽取出来,封装成独立的模块,这些独立的模块被称为切面,切面的具体功能方法被称为关注点。在业务逻辑执行过程AOP会把分离出来的切面和关注点动态切入到业务流程,这样做的好处是提高了功能代码的重用性和可维护性。 AOP的相关术语: Joinpoint:连接点,可以被拦截到的点 Pointcut:切入点,真正被拦截到的点 Ad
Spring AOP源码解读
桐花思雨
01-23 4271
aop 是什么 AOP (Aspect-Oriented Programming,面向切面编程),可以说是 OOP 的补充和完善。OOP 引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。当我们需要为分散的对象引入公共行为的时候,OOP 则显得无能为力。OOP 允许你定义从上到下的关系,但并不适合定义从左到右的关系。例如日志功能。日志代码往往水平地散布在所有对象层次,而与它所散布到的对象的核心功能毫无关系。对于其他类型的代码,如安全性、异常处理和透明的持续性也是如此。这种散布
深度剖析Spring AOP源码,图文详解,小白也能看明白。
Java技术攻略的博客
03-13 1704
AOP 的全称是 “Aspect Oriented Programming”,即⾯向切⾯编程。在 AOP 的思想⾥⾯,周边功能(⽐如性能统计,⽇志,事务管理等)被定义为切⾯,核⼼功能和切⾯功能分别独 ⽴进⾏开发,然后把核⼼功能和切⾯功能“编织”在⼀起,这就叫 AOPAOP 能够将那些与业务⽆关,却为业务模块所共同调⽤的逻辑封装起来,便于减少系统的重复代码,降低模块间的 耦合度,并有利于未来的可拓展性和可维护性。我们再⼩节⼀下,⽂章先介绍了什么是 AOP,以及 AOP原理和示例。
Spring系列(五):Spring AOP源码解析
dijinan2423的博客
09-02 673
一、@EnableAspectJAutoProxy注解   在主配置类添加@EnableAspectJAutoProxy注解,开启aop支持,那么@EnableAspectJAutoProxy到底做了什么?接下来分析下:   @EnableAspectJAutoProxy点进去如下:   此时看到了我们非常熟悉的@Import注解,@Import(AspectJAut...
Spring AOP原理源码分析
morris
03-11 6705
@EnableAspectJAutoProxy @EnableAspectJAutoProxy注解用于开启AOP功能,那么这个注解底层到底做了什么呢? 查看@EnableAspectJAutoProxy的源码,发现它使用@Import注解向Spring容器注入了一个类型为AspectJAutoProxyRegistrar的Bean: class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar { @Overri
Spring-aop源码
weixin_44175409的博客
05-02 347
聊到spring肯定离不开IOC和AOPAOP也是其的大头,今天我们来研究一下AOP的底层实现原理。我们通过@Aspect注解的案例来一步一步深入看一下spring是怎么实现功能增强的。带着两个问题去探究:1.@Aspect是怎么通过解析器给方法进行增强的?
Spring源码分析-深入浅出AOP(图文分析)
热门推荐
进击的大叔
12-11 1万+
这篇文章主要解决三个问题 什么是AOP Spring 怎么实现的AOP AOP的应用场景 篇幅略长 ,建议一口气读完
spring Aop实现原理源码
我说我想
08-21 1962
前文《spring Aop前传》讲解了Aop编程范式的来历与工作原理,接下来将会介绍spring Aop作为一个aop的实现,那么它的工作方式是怎么样的呢?在介绍spring Aop底层工作方式之前,我们抛开spring Aop真正实现,基于当前对spring的认识做一个大胆的假设,在ioc容器,所有的对象都是bean,spring aop要做的就是将公共模块调用填充到制定bean里面,那么sp
springAOP源码解析(一)
KevinDai007的博客
11-15 434
首先讲一下aop的概念,aop面向切面编程.我的理解是这是面向对象思想的一种进阶,把特定的逻辑与主逻辑分开处理,再通过一定的方式组合起来形成完整的处理过程. 下面说一下AOP的几个重要概念(都是我自己的理解,概念上肯定有偏差,但便于我记忆): 通知(advice):即要在主逻辑处运行的逻辑.advice是个空接口,常用的实现由beforceAdvice、afterAdvice、ThrowsAdv
SpringBoot源码解析之AOP
z_Jimmy的博客
07-05 717
Spring Aop源码解析
dynamic-datasource-spring-boot-starter 源码分析
09-05
dynamic-datasource-spring-boot-starter 是一个基于 Spring Boot 的动态数据源库。它提供了在运行时动态切换数据源、动态创建数据源以及多租户的支持。 对于 dynamic-datasource-spring-boot-starter 的源码分析,可以从以下几个方面进行思考: 1. 数据源的自动装配:源码可能会使用 Spring Boot 的自动配置功能,通过扫描配置类或者注解的方式,自动将数据源相关的类和 bean 注入到应用程序。 2. 动态切换数据源的实现:动态切换数据源是 dynamic-datasource-spring-boot-starter 的核心功能之一。源码可能会涉及到 AOP、动态代理等技术,通过拦截器或者代理的方式,在运行时根据特定条件切换数据源。 3. 动态创建数据源的实现:动态-datasource-spring-boot-starter 提供了在运行时动态创建数据源的功能。源码可能会包含一些工厂类或者构建者模式的实现,根据配置信息动态创建数据源实例。 4. 多租户支持的实现:多租户是指一个系统可以同时服务于多个不同的客户或租户。dynamic-datasource-spring-boot-starter 也提供了对多租户的支持。源码可能会包含一些多租户相关的类和逻辑,如解析请求或者从配置文件获取租户信息等。 总结来说,dynamic-datasource-spring-boot-starter 源码分析涉及到数据源的自动装配、动态切换数据源的实现、动态创建数据源和多租户支持等方面的内容。可以通过阅读源码来深入了解其实现原理和技术细节,从而更好地使用和定制该库。

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
写文章

热门文章

  • spring源码阅读--@Transactional实现原理 59368
  • @Transactional注解不起作用解决办法及原理分析 38788
  • spring cloud Ribbon的使用和实现原理 32485
  • 快速搭建redis5.0集群 30748
  • spring boot整合redis集群,连接虚拟机redis集群,Unable to connect to 127 27570

分类专栏

  • spring boot 9篇
  • Reactive 1篇
  • nio 1篇
  • https 1篇
  • rmi 1篇
  • java lib 4篇
  • 虚拟机 1篇
  • zookeeper 2篇
  • dubbo 5篇
  • 消息中间件 14篇
  • activeMQ 7篇
  • kafka 6篇
  • jvm 4篇
  • spring源码 12篇
  • spring cloud 7篇
  • mybatis 4篇
  • redis 4篇
  • 设计模式 6篇
  • idea 1篇
  • jwt 1篇
  • nginx 3篇
  • mysql 5篇
  • git

最新评论

  • 深入了解mysql--gap locks,Next-Key Locks

    kanekijie: 读已提交隔离级别下加的是Record锁,感觉读已提交的那个举例,事务B应该需要等待锁吧,应该不能插入成功?

  • 深入了解mysql--gap locks,Next-Key Locks

    小陶要成大佬: 所以呢?为啥要有Next-Key Lock

  • spring源码阅读--@Transactional实现原理

    Lucien�Yao: spring-tx那个版本啊

  • spring源码阅读--@Transactional实现原理

    Lucien�Yao: 解析事务的代码在AOP里面吗

  • spring源码阅读--@Transactional实现原理

    阿白白又白: 感谢博主,你的文章让我得到一些收获!( ̄ˇ ̄)

最新文章

  • redis缓存一致性问题解决方案
  • mysql调优--从哪几个方面入手
  • 脏读、不可重复读、幻读和快照读、当前读
2019年12篇
2018年62篇

目录

目录

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值

深圳SEO优化公司青岛关键词按天扣费报价忻州百姓网标王推广推荐民治seo排名报价布吉网站优化软件推荐石岩关键词排名包年推广价格鹰潭百度网站优化价格重庆网站排名优化推荐淄博品牌网站设计多少钱枣庄百度竞价包年推广公司滁州营销网站公司安庆建站价格镇江SEO按天扣费价格泰州seo网站优化价格大鹏网站关键词优化报价无锡网站推广方案昭通SEO按效果付费报价鹰潭关键词按天计费公司龙岩网站推广系统多少钱合肥网站搜索优化价格武威网站优化按天计费公司江门至尊标王价格济南品牌网站设计推荐沧州百度关键词包年推广报价常德建站多少钱文山SEO按效果付费多少钱丹东SEO按效果付费推荐长春网站seo优化报价绥化百度seo松岗网站优化推广白银网站排名优化公司歼20紧急升空逼退外机英媒称团队夜以继日筹划王妃复出草木蔓发 春山在望成都发生巨响 当地回应60岁老人炒菠菜未焯水致肾病恶化男子涉嫌走私被判11年却一天牢没坐劳斯莱斯右转逼停直行车网传落水者说“没让你救”系谣言广东通报13岁男孩性侵女童不予立案贵州小伙回应在美国卖三蹦子火了淀粉肠小王子日销售额涨超10倍有个姐真把千机伞做出来了近3万元金手镯仅含足金十克呼北高速交通事故已致14人死亡杨洋拄拐现身医院国产伟哥去年销售近13亿男子给前妻转账 现任妻子起诉要回新基金只募集到26元还是员工自购男孩疑遭霸凌 家长讨说法被踢出群充个话费竟沦为间接洗钱工具新的一天从800个哈欠开始单亲妈妈陷入热恋 14岁儿子报警#春分立蛋大挑战#中国投资客涌入日本东京买房两大学生合买彩票中奖一人不认账新加坡主帅:唯一目标击败中国队月嫂回应掌掴婴儿是在赶虫子19岁小伙救下5人后溺亡 多方发声清明节放假3天调休1天张家界的山上“长”满了韩国人?开封王婆为何火了主播靠辱骂母亲走红被批捕封号代拍被何赛飞拿着魔杖追着打阿根廷将发行1万与2万面值的纸币库克现身上海为江西彩礼“减负”的“试婚人”因自嘲式简历走红的教授更新简介殡仪馆花卉高于市场价3倍还重复用网友称在豆瓣酱里吃出老鼠头315晚会后胖东来又人满为患了网友建议重庆地铁不准乘客携带菜筐特朗普谈“凯特王妃P图照”罗斯否认插足凯特王妃婚姻青海通报栏杆断裂小学生跌落住进ICU恒大被罚41.75亿到底怎么缴湖南一县政协主席疑涉刑案被控制茶百道就改标签日期致歉王树国3次鞠躬告别西交大师生张立群任西安交通大学校长杨倩无缘巴黎奥运

深圳SEO优化公司 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化