怎么理解AOP

    面试的时候,你跟我说说spring AOP吧?

       我就会不假思索的说,spring的AOP是基于动态代理,会生成一个代理对象,而这个代理对象

   就会调用目标对象的方法,并在它的前后增加业务逻辑!!然后,就没了.......

   如此 , 核心的概念就被我三言两语给盖过去了..........

 

所以,今天痛下决心,好好的钻研下AOP,力求能够全面,清晰的解释清楚!!

 

1. 关键字:

    要解释清楚AOP,面向切面的编程!

    那么 , 切面,代理对象,目标对象,编织,拦截 这五个概念一定要清楚!

    说起AOP,首先想到的就是日志管理,我们想在某个方法调用的时候,将某些信息写入日志!

    要达到我们的目的,可以通过直接在每个方法中都添加相同逻辑!

    可是,这样明显不是合适的,共性太多,一些相同的逻辑在重复的书写,说明还可以抽象!

    其二,如果你接下来,像修改写入日志的内容,那么不得不又重新的去修改每个方法!

    耦合度太高!

    既然刚说了有共性,那么就为什么不把这些代码抽象出来,成为一个单独的类!这个类就可以看成

    一个切面!其实,对于切面,可以这样想,当一个方法执行时,它总是一步一步的

   比如下面的testCompute() , 它实际作用的是compute() , 它应当也可以看成一个切面

   log() 日志处理 , 也是这个方法的一部分 , ----- 切面 ,同样对于startTrancation() ;

  void testCompute () {
      log();
      startTrancation();
      compute();
      endTrancation();
      log();
  }

 

    而原来那个要添加日志处理的类就是目标对象!

    我们把切面与目标对象编织在一起 , 就会得到代理对象,它就是目标对象被切面增强后的对象!

    当一个请求传过来的时候,代理对象就会拦截(控制对象访问) , 由它来处理相应的请求,它就会根据

    配置信息,在原方法的前后添加逻辑,再调用目标对象的方法!

 

2. 怎么知道给那个类,那个方法,何时添加额外的逻辑?

    通过定义:

    Pointcut : 那些方法需要注入切面的行为!它是一个方法的集合

    JoinPoint :连接点 一个pointcut 对应多个 joinPoint

    Advice  : 建议 , 你要添加的逻辑 ,可以指定位置!

    Advisor  :那个方法上定义那个advice

 

3. 怎么编织的,也就是说怎么得到代理对象的?

    JDK动态代理机制 JDK动态代理实现原理  这篇文章分析的很清楚

       从 Proxy 的静态方法 newProxyInstance() 入手,三个参数 : class[] interfaces , InvocationHandler handler ClassLoader loader

         三者的作用:

            interfaces  则是你要代理的接口 , 可以代理多个接口,但是必须是接口,不能为具体实现的类!

            handler : 通过它里面的invoke 方法,你就可以为不同的方法,添加advice! 通过反射调用目标类中的方法

            loader : 类加载环境

      通过他生成的代理对象,是一个新的类,同样有相应的class文件!他的方法跟它代理的接口中的方法一样,因为它必须实现这些接口!

      只是实现的时候,是调用handler中的invoke() 方法,这也是为什么下面invoke()是回调方法,当要调用目标类的

      某个方法的时候,就会调用invoke方法!

      其实这样看的话,代理类和目标类,都是实现了相同的接口,代理类在目标类的基础上对相应方法的实现增加了额外的操作!

      但是,要知道一点,代理类的生成不是我们事先写好了的代码,而是在运行的时候动态的生成!它是一个新的类!与目标类不存在什么继承,

      实现的关系!

 

    cglib:

        通过字节码操作!不局限于只能代理接口!

  • CGLIB可以生成目标类的子类,并重写父类非final修饰符的方法(功能增强)。

 

4. 怎么拦截的?

   当调用某个pointCut 指定的方法时,实质上调用的是代理类的这个方法,而代理类的实现就是通过调用,handler的invoke方法。

   就像通过Jdk提供的代理模式一样,你必须实现InvocationHandler 接口 , 因为它里面

   的回调方法关系到切面是否执行!

   在Spring 的AOP中,我们不必自己实现InvocatiionHandler , 我们要做的就是定义切面

   并在配置文件中告诉spring , 我要在这些方法(pointcut)的这些地方(before , after) 添加advice!

   然后,spring就会把这些advice 添加到一个拦截器链中,就像过滤器一样!

   回调方法invoke()调用的时候,就会使用这个拦截器链,然后,就会遍历这个拦截器链,看我这个

  方法中是否第一你这个拦截器(advisor) , 然后就是一个递归调用的过程!

  JdkDynamicProxy invoke():

    // 把请求的方法 , 加入拦截器链中

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

 

 

5. 代理对象什么时候生成的?生命周期?

  

 <context:annotation-config/>
 <context:component-scan base-package="com.bjsxt"/>
 
 <bean id = "litcpt" class="com.bjsxt.aop.LogInterceptor" />
 <aop:config>
     <aop:aspect id="logAsp" ref="litcpt">
     	<aop:pointcut expression="execution(* com.bjsxt.dao..*.*(..))" id="pointCut"/>
     	<aop:before method="Before" pointcut-ref="pointCut"/>
     </aop:aspect>
 </aop:config>

   上面这种配置,初始化的时候,会生成DAO的代理吗?

    会,初始化的时候就会生成!

   

启动spring容器时发生了什么:

  • 实例化bean
  • 解析aop:config的配置,当解析到切入点表达式时,将切入点表达式中的类和Spring容器中的类进行匹配,匹配成功生成代理对象(通知+目标方法)
  • 在生成代理对象时,Spring会检查目标类有没有实现接口,如果有,采用JDK Proxy生成代理对象;没有则采用CGlib产生代理对象。
  •  测试类中调用ctx.getBean时发生了什么:如果要取的bean有代理对象返回代理对象,没有则返回对象本身。

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值