zoukankan      html  css  js  c++  java
  • 【spring源码学习】spring的AOP面向切面编程的实现解析

    动态代理解析:https://blog.csdn.net/wonking666/article/details/79542820

    一:Advice(通知)
    (1)定义在连接点做什么,为切面增强提供织入接口。在spring aop中主要描述围绕方法调用而注入的切面行为。
    (2)spring定义了几个时刻织入增强行为的接口
      =>org.springframework.aop.BeforeAdvice
       org.springframework.aop.MethodBeforeAdvice
      =>org.springframework.aop.AfterAdvice
       org.springframework.aop.AfterReturningAdvice
      =>org.springframework.aop.ThrowsAdvice

    二:PointCut(切点)
    (1)决定Advice应该作用那些连接点。也就是说通过PointCut来定义需要增强的方法集合。
    (2)spring定义的PointCut的接口
      =>org.springframework.aop.Pointcut
      =>org.springframework.aop.TruePointcut
      => org.springframework.aop.support.JdkRegexpMethodPointcut
    (3)相关接口。PointCut接口会返回两个对象,一个ClassFilter,一个是MethodMatcher
      =>org.springframework.aop.ClassFilter    
      =>org.springframework.aop.TrueClassFilter

      =>org.springframework.aop.MethodMatcher  匹配当前方法是否需要执行增强逻辑,也就是是否需要执行Advice接口的方法。
      =>org.springframework.aop.TrueMethodMatcher

    三:通知器皿(Advisor)
      (1)完成对目标方法的切面增强设计(advice)和关注点的设计(PoinCut)以后,需要一个对象把他们结合起来,完成这个作用的就是(Advisor)
      (2)spring定义的Advisor接口
      =>org.springframework.aop.Advisor
          =>org.springframework.aop.PointcutAdvisor
          =>org.springframework.aop.support.DefaultPointcutAdvisor


      (3)Advisor的控制器的接口
      =>org.springframework.aop.framework.adapter.AdvisorAdapter
      =>org.springframework.aop.framework.adapter.AfterReturningAdviceAdapter  目标方法执行完执行该增强的控制器
      =>org.springframework.aop.framework.adapter.MethodBeforeAdviceAdapter  目标方法未执行前执行该增强的控制器
      =>org.springframework.aop.framework.adapter.ThrowsAdviceAdapter   目标方法执行过程抛出异常执行该增强的控制器

    四:springAop的相关
      (1)springAop的核心技术是动态代理。动态代理的技术是jdk的一个特征。
      (2)springAop的代理对象生成案例
        =>org.springframework.aop.framework.ProxyFactoryBean
        =>org.springframework.aop.framework.ProxyFactory


    五:ProxyFactoryBean的工作流程。
    (1)实现FactoryBean接口的类,在想IOC容器申请bean的时候,其实返回的是该类执行getObject()方法的返回。
    (2)ProxyFactoryBean的getObject()方法返回的是目标对象的代理对象。
      其执行过程
      =>根据配置的interceptorNames的属性值先初始化代理增强的链子.根据interceptorNames从IOC容器中得到增强类的bean,然后判断其类型,形成DefaultPointcutAdvisor对象。
      =>根据配置的targetName属性值从IOC容器中得到目标对象的bean,形成一个SingletonTargetSource对象。
      =>将其本身作为一个aop代理对象创建的数据配置类,创建一个动态代理对象,返回给ioc容器申请。
    (3)在执行目标对象的方法过程中,会根据执行的方法的对象,从代理链子里找到所有的Advisor对象,然后利用其属性Pointcut对象获取ClassFilter, MethodMatcher来判断当前Advisor是否要执行。如果执行,则加入执行代理链子中。以jdk动态代理为例子,是org.springframework.aop.framework.JdkDynamicAopProxy类中invoke(Object proxy, Method method, Object[] args)方法中这句代码List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);。该句代码中this.advised其实就是ProxyFactoryBean本身。

    六案例

    一:Advice的对象

    package com.mobile.thinks.aop.advice;
    
    import java.lang.reflect.Method;
    
    import org.springframework.aop.MethodBeforeAdvice;
    
    public class LoginBeforeAdvice implements MethodBeforeAdvice{
    
        @Override
        public void before(Method method, Object[] args, Object target)throws Throwable {
            System.out.println("LoginBeforeAdvice.before()执行方法为==>"+method.getName());
            System.out.println("LoginBeforeAdvice.before()执行参数为==>"+args);
            System.out.println("LoginBeforeAdvice.before()执行的目标为==>"+target.getClass());
        }
        
        
    
    }
    View Code

    二:目标对象

    package com.mobile.thinks.service.impl;
    
    import java.util.Date;
    
    import org.springframework.stereotype.Service;
    
    import com.mobile.thinks.entity.User;
    import com.mobile.thinks.service.UserInfoService;
    
    @Service(value="userInfoServiceImpl")
    public class UserInfoServiceImpl implements UserInfoService{
    
        
        @Override
        public User loginByUserNameAndPassWord(String userName, String passWord) {
            User user=new User();
            
            user.setAddress("三门峡");
            user.setAge(28);
            user.setCreateTime(new Date());
            user.setName(userName);
            return user;
        }
    
        
    }
    View Code

    三:配置文件

     <!-- 测试ProxyFactoryBean -->
           <!--定义一个advice  -->
           <bean name="loginBeforeAdvice" class="com.mobile.thinks.aop.advice.LoginBeforeAdvice" />
        <!-- 定义FactoryBean -->
        <bean name="userInfoService" class="org.springframework.aop.framework.ProxyFactoryBean">
            <!-- 要代理的目标对象,在ioc容器中的名字 -->
            <property name="targetName">
                <value>userInfoServiceImpl</value>
            </property>
            <!-- 要植入增强功能的advice在IOC容器中的名字 -->
            <property name="interceptorNames">
                <list><value>loginBeforeAdvice</value></list>
            </property>
        </bean>
    View Code

    七:spring内部基于该中方式实现动态代理的案例。spring提供的HttpInvoker远程调用.可以阅读该类getObject方法。实现对Facade接口代理

    org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean

    ==============================spring的自动进行对bean进行代理的创建类=============================== 

    1、org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator

    2、上述类是org.springframework.beans.factory.config.BeanPostProcessor接口的实现类

    3、ioc在创建bean时,postProcessAfterInstantiation会执行方法,并对当前bean检查,是否需要代理。

    4、检查逻辑,每一个切面,都会有自己的Pointcut,去适配当前的bean。需要则动态代理,不需要则返回。

    事务管理实现动态代理的切面:

    事务代理的切面:org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor

    pointcut的类:org.springframework.transaction.interceptor.TransactionAttributeSourcePointcut

    事务增强的类:org.springframework.transaction.interceptor.TransactionInterceptor

    ==============================spring的具体实现===============================

    1、Advisor包换了Advice和Pointcut
    2、Advice里是面向切面的增强逻辑实现
    3、Pointcut里包含了ClassFilter和MethodMatcher。通过对类进行过滤或者方法进行过滤,决定一个类是否需要进行动态代理,添加增强逻辑。

    
    

    1、spring容器中会注册:org.springframework.aop.framework.autoproxy.InfrastructureAdvisorAutoProxyCreator

    该类是org.springframework.beans.factory.config.BeanPostProcessor的实现,该类会在客户端向spring申请bean的时候,进行代理类的创建,

    2、向spring容器中获取所有实现advisor接口的List<Advisor>。

    3、org.springframework.aop.support.AopUtils类的findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz)

    根据当前要被创建的bean的Class和beanName,去适配所有的List<Advisor>,看那些是适合当前bean的增强。

    先根据advisor中的Pointcut的ClassFilter和MethodMatcher的方法决定

    先根据ClassFilter决定,如ClassFilter决定不了,则根据MethodMatcher匹配bean的所有方法,包括接口和继承的类的方法。

    4、通过2,3步确定那些List<Advisor>可以对当前bean进行动态代理增强,然后进行代理类的创建。

    org.springframework.aop.framework.JdkDynamicAopProxy(代理类的执行入口)

    org.springframework.aop.framework.ProxyFactory(所有适合当前List<Advisor>进行增强的信息会被存储到proxyFactory中)

    org.springframework.aop.framework.AdvisedSupport是ProxyFactory的父类





    spring的动态代理实现的基本逻辑
    1、从ioc容器中找到所有实现了Advisor接口的bean,并将其缓存
    2、扫描:每初始化一个bean,进行扫描的时候,都要用spring容器里的每一个Advisor里的Pointcut进行过滤,看当前类的是否需要进行增强。如果需要,把匹配通过的Advisor形成一个集合。
    3、扫描后,如果返回的Advisor集合里不为空,说明该类需要代理,则创建代理对象。并将每一个Advisor里的Advice作为增强加入的增强链条中。(advice有排序功能,决定那个增强先被代理执行)


    jdk动态代理的分析:https://www.cnblogs.com/huansky/p/9573202.html



  • 相关阅读:
    NodeJs 的Module.export 和 export
    Angular 调试
    设计模式 -- 访问者
    typescript 枚举
    Swagger 实践 <二>
    eventFlow 系列 <三> 查询所有
    成员变量的隐藏和方法的重写
    Facetoprocess_program_design
    ATM_tests
    transmission protocol
  • 原文地址:https://www.cnblogs.com/shangxiaofei/p/7262445.html
Copyright © 2011-2022 走看看