spring -- AOP

AOP — 面向切面编程

1.什么是AOP?
面向切面编程,能够让我们在不影响原有功能的前提下,为软件横向扩展 功能 ,是指在程序运行期间,将某段代码切入到指定方法的指定位置运行的编程方式

2.AOP通知类型

  • 前置通知 — 目标方法执行前通知
  • 后置通知 — 目标方法执行后通知,无论方法正常结束还是异常结束
  • 返回通知 — 在目标方法正常返回之后通知
  • 异常通知 — 在目标方法出现异常的情况下通知
  • 环绕通知 — 动态代理,手动执行目标方法

图解:

在这里插入图片描述

3.AOP中的一些术语

  1. target:目标类,需要被代理的类。例如:UserService
  2. Joinpoint(连接点):所谓连接点是指那些可能被拦截到的方法。例如:所有的方法
  3. PointCut 切入点:已经被增强的连接点。例如:addUser()
  4. advice 通知/增强,增强代码。例如:after、before
  5. Weaving(织入):是指把增强advice应用到目标对象target来创建新的代理对象proxy的过程.
  6. proxy 代理类
  7. Aspect(切面): 是切入点pointcut和通知advice的结合
    一个线是一个特殊的面。
    一个切入点和一个通知,组成成一个特殊的面。

在这里插入图片描述

4.spring中使用注解制作切面类
a. 使用 @Aspect注解告诉spring容器,这是一个切面类
b. 可以抽取一个方法来写公共的切入点表达式
*号代表任意类型的返回值,然后是所在的类和方法名,*号同样代表任意,(…)表示任意参数在这里插入图片描述

    @Aspect
    @Component
    public class LogAspect {
        /**
         * 切面类
         */
        private Logger logger = LoggerFactory.getLogger(getClass());
    
        //切入点
        @Pointcut("execution(public * com.kevin.library.controller.*.*(..))")
        public void webLog() {
        }
    
        //前置通知
        @Before("webLog()")
        public void before(JoinPoint joinPoint)throws Throwable {
            // 接收到请求,记录请求内容
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();
            // 记录下请求内容
            logger.info("URL : " + request.getRequestURL().toString());
            logger.info("HTTP_METHOD : " + request.getMethod());
            logger.info("IP : " + request.getRemoteAddr());
            logger.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
            logger.info("ARGS : " + Arrays.toString(joinPoint.getArgs()));
        }
    
        //后置通知
        @AfterReturning(returning = "ret", pointcut = "webLog()")
        public void afterReturning(Object ret) throws Throwable {
            // 处理完请求,返回内容
            logger.info("方法的返回值 : " + ret);
        }
    
        //后置异常通知
        @AfterThrowing("webLog()")//JoinPoint一定要出现在参数表的第一位
        public void returnThrowing(JoinPoint joinPoint) {
            logger.info("方法异常时执行");
        }
    
        //最终通知
        @After("webLog()")
        public void after(JoinPoint joinPoint) {
            logger.info("方法最终执行");
        }
    
        //环绕通知
        @Around("webLog()")
        public Object arround(ProceedingJoinPoint pjp) {
            logger.info("方法环绕start.....");
            try {
                Object o =  pjp.proceed();
                logger.info("方法环绕proceed,结果是 :" + o);
                return o;
            } catch (Throwable e) {
                e.printStackTrace();
                return null;
            }
        }
    }

原来我们需要在配置文件中使用标签
这也是我们spring aop的一种写法


      在xml里面配置文件中aop
                       i.将切面类交给spring管理
                       
                       ii.声明Aop配置
                       <aop:config>
                       iii.定义切入点
                       aop:pointcut
                       iiii.定义通知类型
                       <aop:aspect ref = "切面类的引用">
                           前置通知
                           <aop:before method="切面类的方法名" pointcut-ref="切入点表达式是引用"/>
                           后置通知<aop:afterRunturning method="切面类的方法名" pointcut-ref="切入点表达式是引用"/>
                           异常通知<aop:after-throwing method="切面类的方法名" pointcut-ref="切入点表达式是引用"/>
                           最终通知<aop:after method="切面类的方法名" pointcut-ref="切入点表达式是引用"/>
                           注意:异常通知只有出现了异常了 才会有通知
                       </aop:aspect>

xml配置版

    	  <!--在源码中,只要proxy-target-class="true" expose-proxy="true" 其中一个为true,则强制使用cglib字节码增强
            如果不配置,默认都为false,则根据接口情况选择
            如果目标类是接口   则使用 jdk动态代理
            如果不是 则使用ObjensesisCglibAopProxy
        -->
        <aop:config proxy-target-class="true" expose-proxy="true">
            <aop:aspect ref="aspect">
                <aop:pointcut id="pointCut" expression="execution(public * main.java.config.*.*(..))"></aop:pointcut>
                <aop:before method="before" pointcut-ref="pointCut"></aop:before>
                <aop:after method="after" pointcut-ref="pointCut"></aop:after>
                <aop:after-returning method="afterReturning" pointcut-ref="pointCut"></aop:after-returning>
                <aop:after-throwing method="returnThrowing" pointcut-ref="pointCut"></aop:after-throwing>
                <aop:around method="arround" pointcut-ref="pointCut"></aop:around>
            </aop:aspect>
        </aop:config>

上边提到的源码

    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);
                }
                return CglibProxyFactory.createCglibProxy(config);
            }
            else {
                return new JdkDynamicAopProxy(config);
            }
        }

怎样开启注解AOP

    <!-- 开启对aop注解的支持 -->
        <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

也可以直接在配置类使用注解

    @EnableAspectJAutoProxy
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值