• 1.springAOP原理分析


    环境:jdk1.8 + spring boot 2.0.9.RELEASE

    Spring AOP的实现本质上就是代理Proxy + 一系列的拦截器

    使用@Aspect,引入依赖

    <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjweaver</artifactId>
                <version>1.9.2</version>
     </dependency>
    

    1. AOP中的几个关键词介绍 (概念性的东西,copy别人的)

    • 切面(Aspect) :官方的抽象定义为“一个关注点的模块化,这个关注点可能会横切多个对象”。
    • 连接点(Joinpoint) :程序执行过程中的某一行为,个人理解为是对目标对象method的封装。
    • 通知(Advice) :“切面”对于某个“连接点”所产生的动作。
    • 切入点(Pointcut) :匹配连接点的断言,在AOP中通知和一个切入点表达式关联。
    • 目标对象(Target Object):被一个或者多个切面所通知的对象。
    • AOP代理(AOP Proxy): 在Spring AOP中有两种代理方式,JDK动态代理和CGLIB代理。

    可以通过以下方式定义一个切面,切入点表达式限定了那些对象需要被代理,以下仅以demoController为例

    @Aspect
    @Component
    public class DemoAspect {
    //定义一个切入点
    @Pointcut("execution (* com.test.mybatis.demo.DemoController.*(..))")
    public void cut(){
    }
    //前置通知 @Before("cut()") public void before(JoinPoint joinPoint) throws Throwable { System.out.println("before......"); } //环绕通知 @Around("cut()") public Object invoke(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { return proceedingJoinPoint.proceed(); } //后置通知 @After("cut()") public void after(JoinPoint joinPoint) throws Throwable { System.out.println("after......"); } }

    2. 先看下AOP中十分关键的一个类org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator,它实现了BeanPostProcessor,可以在bean初始化之后对其进行代理

    3. spring启动时候是如何利用这些切面生成代理对象的?

    aop中,在创建bean之前(上图1.1.1),会先判断这个beanClass是否是一个advisor(advisor是通知器,上面的DemoAspect中就包含3个通知器),

    其实一个通知可以理解为一个Method级别的拦截器,DemoAspect中相当于加了3个拦截器

    advisor本身不需要再被代理了,如果是advisor,将其缓存起来供后续判断使用

    	@Override
    	protected boolean shouldSkip(Class<?> beanClass, String beanName) {
    		// 查找所有的通知器
    		List<Advisor> candidateAdvisors = findCandidateAdvisors();
    		for (Advisor advisor : candidateAdvisors) {
    //beanName是否是某一个通知器的 if (advisor instanceof AspectJPointcutAdvisor && ((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) { return true; } } return super.shouldSkip(beanClass, beanName); }

    解析配置的切面信息:org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors

    public List<Advisor> buildAspectJAdvisors() {
    		List<String> aspectNames = this.aspectBeanNames;
    
    		if (aspectNames == null) {
    			synchronized (this) {
    				aspectNames = this.aspectBeanNames;
    				if (aspectNames == null) {
    					List<Advisor> advisors = new ArrayList<>();
    					aspectNames = new ArrayList<>();
    					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;
    						}
    
                                //是否是一个切面
    						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);
    
                                           //获取该切面中所有的通知器
    								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 ArrayList<>();
    		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;
    	}
    
    	@Override
    	public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
    		Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
    		String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
    		validate(aspectClass);
    
    		// We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
    		// so that it will only instantiate once.
    		MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
    				new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
    
    		List<Advisor> advisors = new ArrayList<>();
                    //遍历aspectClass中所有含有PointCut注解的方法
    		for (Method method : getAdvisorMethods(aspectClass)) {
                            //构建一个Advisor对象
    			Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
    			if (advisor != null) {
    				advisors.add(advisor);
    			}
    		}
    
    		// If it's a per target aspect, emit the dummy instantiating aspect.
    		if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
    			Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
    			advisors.add(0, instantiationAdvisor);
    		}
    
    		// Find introduction fields.
    		for (Field field : aspectClass.getDeclaredFields()) {
    			Advisor advisor = getDeclareParentsAdvisor(field);
    			if (advisor != null) {
    				advisors.add(advisor);
    			}
    		}
    
    		return advisors;
    	}
    
    
            @Override
    	@Nullable
    	public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
    			int declarationOrderInAspect, String aspectName) {
    
    		validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
                    //构建一个表达式对象
    		AspectJExpressionPointcut expressionPointcut = getPointcut(
    				candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
    		if (expressionPointcut == null) {
    			return null;
    		}
                    //返回一个Advisor
    		return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
    				this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
    	}
    public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
          Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
          MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
    
       this.declaredPointcut = declaredPointcut;
       this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
       this.methodName = aspectJAdviceMethod.getName();
       this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
       this.aspectJAdviceMethod = aspectJAdviceMethod;
       this.aspectJAdvisorFactory = aspectJAdvisorFactory;
       this.aspectInstanceFactory = aspectInstanceFactory;
       this.declarationOrder = declarationOrder;
       this.aspectName = aspectName;
    
       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;
         // 构建一个实现了MethodInterceptor的advice
          this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
       }
    }
    

    真正创建bean是从1.2开始的

    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;
    		}
    		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;
    	}
    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); if (!proxyFactory.isProxyTargetClass()) { if (shouldProxyTargetClass(beanClass, beanName)) { proxyFactory.setProxyTargetClass(true); } else { evaluateProxyInterfaces(beanClass, proxyFactory); } } Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
    //关联适用于此bean的通知 proxyFactory.addAdvisors(advisors);
    //关联被代理对象 proxyFactory.setTargetSource(targetSource); customizeProxyFactory(proxyFactory); proxyFactory.setFrozen(this.freezeProxy); if (advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } return proxyFactory.getProxy(getProxyClassLoader()); }

    创建代理对象时会判断是使用cglib还是jdk ,org.springframework.aop.framework.DefaultAopProxyFactory

            @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)) { return new JdkDynamicAopProxy(config); } return new ObjenesisCglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); } }

    这时已将目标对象,通知器(拦截器),关联起来共同组成了一个代理对象

    4.代理对象执行时如何使用通知器的?

    org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor#intercept

    	public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
    			Object oldProxy = null;
    			boolean setProxyContext = false;
    			Object target = null;
    			TargetSource targetSource = this.advised.getTargetSource();
    			try {
    				if (this.advised.exposeProxy) {
    					// Make invocation available if necessary.
    					oldProxy = AopContext.setCurrentProxy(proxy);
    					setProxyContext = true;
    				}
    				// Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
    				target = targetSource.getTarget();
    				Class<?> targetClass = (target != null ? target.getClass() : null);
    // 根据method查找所有的通知 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...
    // 组装一个CglibMethodInvocation,这里面维护了一个intercepterChain retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed(); } retVal = processReturnType(proxy, target, method, retVal); return retVal; } finally { if (target != null && !targetSource.isStatic()) { targetSource.releaseTarget(target); } if (setProxyContext) { // Restore old proxy. AopContext.setCurrentProxy(oldProxy); } } }

     再看下proceed()方法,保证先执行拦截器,具体的前置通知、后置通知,是由拦截器本身的排序和拦截器中的执行顺序同时控制的

    	@Override
    	@Nullable
    	public Object proceed() throws Throwable {
    		//	We start with an index of -1 and increment early.
    		if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
    			return invokeJoinpoint();
    		}
    
    		Object interceptorOrInterceptionAdvice =
    				this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
    		if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
    			// Evaluate dynamic method matcher here: static part will already have
    			// been evaluated and found to match.
    			InterceptorAndDynamicMethodMatcher dm =
    					(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
    			if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
    				return dm.interceptor.invoke(this);
    			}
    			else {
    				// Dynamic matching failed.
    				// Skip this interceptor and invoke the next in the chain.
    				return proceed();
    			}
    		}
    		else {
    			// It's an interceptor, so we just invoke it: The pointcut will have
    			// been evaluated statically before this object was constructed.
    //拦截器先执行 return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } }

     5. 通知的顺序,前置通知和后置通知,环绕通知,执行顺序的保证

     org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory中定义了这些常用通知的顺序,加载通知器时会根据这个顺序先将某个切面中定义的通知器进行排序

    static {
    		Comparator<Method> adviceKindComparator = new ConvertingComparator<>(
    				new InstanceComparator<>(
    						Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class),
    				(Converter<Method, Annotation>) method -> {
    					AspectJAnnotation<?> annotation =
    						AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
    					return (annotation != null ? annotation.getAnnotation() : null);
    				});
    		Comparator<Method> methodNameComparator = new ConvertingComparator<>(Method::getName);
    		METHOD_COMPARATOR = adviceKindComparator.thenComparing(methodNameComparator);
    	}
    

         

    	private List<Method> getAdvisorMethods(Class<?> aspectClass) {
    		final List<Method> methods = new ArrayList<>();
    		ReflectionUtils.doWithMethods(aspectClass, method -> {
    			// Exclude pointcuts
    			if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
    				methods.add(method);
    			}
    		});
    		methods.sort(METHOD_COMPARATOR);
    		return methods;
    	}
    

    这个方法会将所有的通知器进行排序,可以通过设置@Priority(1)来提高自定义通知器的优先级

     org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findEligibleAdvisors

        @Override
    	@Nullable
    	protected Object[] getAdvicesAndAdvisorsForBean(
    			Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
    
    		List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
    		if (advisors.isEmpty()) {
    			return DO_NOT_PROXY;
    		}
    		return advisors.toArray();
    	}
    
        protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    		List<Advisor> candidateAdvisors = findCandidateAdvisors();
    //查找适用于beanClass的advisor List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); extendAdvisors(eligibleAdvisors); if (!eligibleAdvisors.isEmpty()) { eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; } @Override @SuppressWarnings("unchecked") protected List<Advisor> sortAdvisors(List<Advisor> advisors) { List<PartiallyComparableAdvisorHolder> partiallyComparableAdvisors = new ArrayList<>(advisors.size()); for (Advisor element : advisors) { partiallyComparableAdvisors.add( new PartiallyComparableAdvisorHolder(element, DEFAULT_PRECEDENCE_COMPARATOR)); } List<PartiallyComparableAdvisorHolder> sorted = PartialOrder.sort(partiallyComparableAdvisors); if (sorted != null) { List<Advisor> result = new ArrayList<>(advisors.size()); for (PartiallyComparableAdvisorHolder pcAdvisor : sorted) { result.add(pcAdvisor.getAdvisor()); } return result; } else { return super.sortAdvisors(advisors); } }

    参考链接:https://blog.csdn.net/wyl6019/article/details/80136000

  • 相关阅读:
    body.filters 出现未指明错误
    利用sql server创建可重复运行的存储过程
    有关如何阻止ASP.NET的按钮控件提交页面的小发现
    ASP.NET 2.0中减少ViewState大小的一点小发现
    DataSet 的 Tables 属性对表名大小写敏感性的解惑[翻译]
    利用Sql Server Management Studio 创建视图的问题
    在用数据绑定的时候我为什么不能把焦点移出(Tab out)我的控件?(译)
    什么是 Change Notification,为什么它很重要(译)
    Rms For Sharepoint
    sharepoint 2010 容量边界
  • 原文地址:https://www.cnblogs.com/Hleaves/p/11322930.html
Copyright © 2020-2023  润新知