zoukankan      html  css  js  c++  java
  • Spring AOP设计

    Spring IOC设计到的设计模式: 工厂模式,模板方法模式,单例模式

    Spring AOP涉及到的设计模式: 工厂模式,代理模式

    1、Spring AOP目标

    将分散在程序各处的横切关注点剥离出来,并以集中的方式进行表达

    使得开发人员专注于业务逻辑的实现而非繁杂的非功能代码,简化了程序编写与单元测试

    应用场景:

      日志

      安全

      事务

    2、AOP核心概念

    Advice(通知)

      定义在连接点处的行为,围绕方法调用而进行注入

    Pointcut(切点)

      确定在哪些连接点处应用通知

    Advisor(通知器)

      组合Advice和Pointcut

    3、Spirng AOP实现

    ProxyFactoryBean

      --FactoryBean implementation that builds an  AOP proxy based on beans in Spring BeanFactory.

      --Spring AOP的底层实现与源头

    4、ProxyFactoryBean的典型配置

     5、ProxyFactoryBean的构成

    target

      目标对象,需要对其进行切面增强

    proxyInterfaces

      代理对象所实现的接口

    interceptorNames

      通知器(Advisor)列表,通知器中包含了通知(Advice)与切入点(Pointcut)

    6、ProxyFactoryBean的作用 

      总的来说,ProxyFactoryBean的作用可用下面这句话概括

      针对目标对象来创建代理对象,将对目标对象方法的调用转到对相应代理对象方法的调用,并且可以在代理对象方法调用前后执行与之匹配的各个通知器定义好的方法。

    7、目标代理对象的创建

    Spring通过两种方式来创建目标对象

      JDK动态代理

      CGLIB

    8、JDK动态代理

    如果目标对象实现了接口,那么Spring就会通过JDK动态代理为目标对象生成代理对象

    JdkDynamicAopProxy中getProxy方法

    public Object getProxy(ClassLoader classLoader) {
    		if (logger.isDebugEnabled()) {
    			logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
    		}
    		Class[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);
    		findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
    		return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    	}
    

      

    9、DefaultAopProxyFactory

    	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()) {
    				return new JdkDynamicAopProxy(config);
    			}
    			if (!cglibAvailable) {
    				throw new AopConfigException(
    						"Cannot proxy target class because CGLIB2 is not available. " +
    						"Add CGLIB to the class path or specify proxy interfaces.");
    			}
    			return CglibProxyFactory.createCglibProxy(config);
    		}
    		else {
    			return new JdkDynamicAopProxy(config);
    		}
    	}
    

      

     10、CGLIB代理(Cglib2AopProxy.java)

    如果目标类并未实现接口,那么spring就好使用CGLIB库创建代理

    创建代理对象

     11、Spring AOP拦截(动态代理方式)

    实际上是通过InvocationHandler的invoke方法实现的

    JdkDynamicAopProxy类本身实现了InvocationHandler接口

    JdkDynamicAopProxy类中的invoke方法中

     

    List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

    获取配置的拦截器链

    在该方式下,拦截器链中各个拦截器的调用时通过ReflectiveMethodInvocation对象中的proceed方法实现的

    proceed方法是一个递归方法

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

      

  • 相关阅读:
    使用 Fetch
    实现一个联系客服对话框的前端部分
    javascript之Object.defineProperty的奥妙
    vue之nextTick全面解析
    创建元素和删除元素
    vue.js应用开发笔记
    待字闺中之最多连续数的子集
    HDU-1212-Big Number
    虚方法【仅仅有虚方法或者抽象方法才干被子类方法重写】
    利用localStorage实现对ueditor编辑内容定时保存为草稿
  • 原文地址:https://www.cnblogs.com/linlf03/p/11184428.html
Copyright © 2011-2022 走看看