spring_03AOP编程

本文介绍Spring AOP的基础概念,包括动态代理与CGLib代理的原理,并通过实例演示如何使用Spring AOP进行前置、后置及环绕等不同类型的增强。

AOP 编程

AOP( Aspect Oricented Programming ) 面向切面编程

是对所有对象或者是一类对象进行编程 

核心是(不  还)

    在不增加代码的基础上,还增加新的功能

spring AOP实现原理

  • 动态代理&CGLib代理

      spring能够为容器中管理的对象生成动态代理对象
    
      以前我们要使用动态代理,我们需要自己调用下面这个方法:
    
          Proxy.newProxyInstance(xx,xx,xx)
    
      生成代理对象
    
    
      spring能帮我们生成代理对象
  • 动态代理和CGLib代理的区别:

      动态代理:被代理的对象必须实现接口,才能产生代理对象,
    
          如果没有接口将不能使用动态代理技术
    
      cglib代理:第三方代理技术,cglib代理,可以对任何类生成代理,代理的原理是
    
          对目标对象进行继承代理。如果目标对象被final修饰,那么该类无法被
    
          cglib代理
  • 具体的顺序:有接口的话,优先使用 动态代理,没有的话使用cglib代理

AOP的一些术语:

  1. Joinpoint(连接点):

     目标对象中,所有可以增强的方法
  2. Pointcut(切入点):

     目标对象,已经增强的方法
  3. Afvice(通知/增强):

     增强的代码
  4. Target(目标对象):

     被代理的对象
  5. Weaving(织入):

     动词,将通知织入连接点形成切入点
  6. Proxy(代理):

     将通知织入目标对象后,形成代理对象
  7. aspect(切面):

     切入点+通知

使用spring中的AOP:

  1. 导包

     (4+2+2+2)4个核心+2个日志
    
     +(2)spring的aop包:
    
         spring-aop.jar 与 spring-aspects.jar
    
     +(2)spring需要第三方aop包:
    
         com.springsource.org.aopalliance-1.0.0.jar
    
         com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
  2. 准备目标对象

     package org.spring.service;
    
     public class UserService {
    
         public void save(){
             System.out.println("保存用户");
         }
         public void delete(){
             System.out.println("删除用户");
         }
         public void find(){
             System.out.println("查询用户");
         }
         public void update(){
             System.out.println("更新用户");
         }
     }
  3. 定义通知:

     前置通知
    
         目标方法运行之前调用
    
     后置通知(如果出现异常不会调用)
    
         在目标方法运行之后调用
    
    
     环绕通知
    
         在目标方法之前和之后都调用
    
     异常拦截通知
    
         如果出现异常,就会调用
    
     后置通知(无论是否出现异常都会调用)
    
         在目标运行之后调用
    
    
    
     特殊:环绕通知需要手动调用目标方法
    
    
     package org.spring.advice;
    
     import org.aspectj.lang.ProceedingJoinPoint;
    
     public class MyAdvice {
         //前置通知
         public void before(){
             System.out.println("前置通知");
         }
         //后置通知
         public void afterRunning(){
             System.out.println("后置通知(如果出现异常不会调用)");
         }
         //环绕通知
         public Object around(ProceedingJoinPoint  pjp) throws Throwable{
             System.out.println("环绕通知-前");
             Object procced = pjp.proceed();
             System.out.println("环绕通知-后");
             return procced;
         }
         //异常通知
         public void afterException(){
             System.out.println("异常通知");
         }
         //后置通知
         public void after(){
             System.out.println("后置通知(出现异常也会调用)");
         }
     }
  4. 配置进行织入,将通知织入目标对象中

     <!-- 准备工作:导入aop(约束)命名空间 -->
     <!-- 1.配置目标对象 -->
         <bean name="userService" class="org.spring.service.UserService"></bean>
     <!-- 2.配置通知对象 -->
         <bean name="myAdvice" class="org.spring.advice.MyAdvice"></bean>
     <!-- 3.配置将通知织入目标对象 -->
         <aop:config>
             <!-- 配置切入点
                 public void org.spring.service.UserService.save()
                 void org.spring.service.UserService.save()
                 * org.spring.service.UserService.save()
                 * org.spring.service.UserService.*()
                 * org.spring.service.UserService.*(..)
                 * org.spring.service.*Service.*(..)
                 * org.spring.service..*Service.*(..)
              -->
             <aop:pointcut expression="execution(* org.spring.service.*Service.*(..))" id="pc"/>
             <!-- 通知对象 -->
             <aop:aspect ref="myAdvice">
                 <!-- 指定通知类型与通知方法名以及切入点 -->
                 <aop:before method="before" pointcut-ref="pc"/>
                 <aop:after-returning method="afterRunning" pointcut-ref="pc"/>
                 <aop:around method="around" pointcut-ref="pc"/>
                 <aop:after-throwing method="afterException" pointcut-ref="pc"/>
                 <aop:after method="after" pointcut-ref="pc"/>
             </aop:aspect>
         </aop:config>

springAOP的注解配置

  1. applicationContext.xml中的配置

     <context:component-scan base-package="org.spring"></context:component-scan>
     <!--开启切面自动代理-->
     <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
  2. 通知中的注解:

     package org.spring.advice;
    
     import org.aspectj.lang.ProceedingJoinPoint;
     import org.aspectj.lang.annotation.After;
     import org.aspectj.lang.annotation.AfterReturning;
     import org.aspectj.lang.annotation.AfterThrowing;
     import org.aspectj.lang.annotation.Around;
     import org.aspectj.lang.annotation.Aspect;
     import org.aspectj.lang.annotation.Before;
     import org.aspectj.lang.annotation.Pointcut;
     import org.springframework.stereotype.Component;
     @Component("myAdvice")
     //表示该类是一个通知类
     @Aspect
     public class MyAdvice {
         //表示切入点的方法
         @Pointcut("execution(* org.spring.service.*Service.*(..))")
         public void pc(){}
    
         //前置通知
         @Before("MyAdvice.pc()")
         public void before(){
             System.out.println("前置通知");
         }
         //后置通知
         @AfterReturning("MyAdvice.pc()")
         public void afterRunning(){
             System.out.println("后置通知(如果出现异常不会调用)");
         }
         //环绕通知
         @Around("MyAdvice.pc()")
         public Object around(ProceedingJoinPoint  pjp) throws Throwable{
             System.out.println("环绕通知-前");
             Object procced = pjp.proceed();
             System.out.println("环绕通知-后");
             return procced;
         }
         //异常通知
         @AfterThrowing("MyAdvice.pc()")
         public void afterException(){
             System.out.println("异常通知");
         }
         //后置通知
         @After("MyAdvice.pc()")
         public void after(){
             System.out.println("后置通知(出现异常也会调用)");
         }
     }

转载于:https://www.cnblogs.com/nm666/p/8290097.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值