Spring之AOP

1.AOP概述

简介:

AOP(Aspect Oriented Programming)面向切面编程,而面向切面编程是一种代码设计思想;

AOP的作用:

在不修改目标对象的情况下添加新的业务逻辑,增强方法

实现原理:

底层使用了动态代理技术实现AOP的面向切面编程思想

AOP中的术语:

1.连接点,即被代理对象中的所有方法

2.切入点,即被代理对象中需要被增强的方法

3.通知,目标对象需要增强的内容,或方法

4.切面,即由切入点和通知组成的一个关系网,也就是一个关系表

2.切入点表达式

指示符示例作用(细粒度)
beanbean(accountService)精确到IOC容器的bean
withinwithin(com.pkx.xml.service.impl.AccountServiceImpl)精确到类
executionexecution(public void com.pkx…save(…))精确到方法

概述:

​ 使用切入点表达式准确控制所有切入点,可以根据需要命名,这样的话方便管理切入点和通知之间的关系也就是方便管理切面;

特殊符号的使用:

符号说明
*匹配任意字符串
修饰符,表示一个或这0个
..匹配多层目录

execution:

execution(modififiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern?)

  • modififiers-pattern: 权限访问修饰符 (可填)
  • ret-type-pattern: 返回值类型 (必填)
  • declaring-type-pattern: 全限定类名 (可填)
  • name-pattern: 方法名 (必填)
  • param-pattern: 参数名 (必填)
  • throws-pattern: 异常类型 (可填)

XML配置:

配置位置:

<!--即xml文件中的这个标签下-->
<aop:config>
    <aop:pointcut expression="bean(配置内容)">
</aop:config>`
类型配置内容
bean<aop:config>
<aop:pointcut expression="bean(配置内容)">
</aop:config>
within<aop:config>
<aop:pointcut expression="within(配置内容)">
</aop:config>
execution<aop:config>
<aop:pointcut expression="execution(配置内容)">
</aop:config>

3.AOP通知

伪代码理解:

try{
    [前置通知]
    // 执行目标对象方法..
    targer.method(..);
    [后置通知]
} catch (Exception e){
    [异常通知]
} finally {
    [最终通知]
}

分类:

前置通知

后置通知

异常通知

最终通知

环绕通知

环绕通知

可以根据自己的需要设置通知

4.XML配置AOP

配置切入点:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <bean class="com.ps.service.AccountService" id="service"></bean>
    <bean class="com.ps.log.LogService" id="logService"></bean>

    <!--配置AOP
    proxy-target-class:配置选择那种代理模式,默认是自动选择,那个合适选择那个,也可以理解为是否强制使用cglib
            true:cglib动态代理模式
            false:jdk动态代理模式
    -->
    <aop:config proxy-target-class="true">
        <!--配置切入点,即配置要增强的方法
        id:切入点的名称
        expression:切入点表达式,即设置要增强的是那个类的那个方法,配置的是具体的方法
        -->
        <aop:pointcut id="pt"
                      expression="execution(void com.ps.service.AccountService.get())"/>
        <!--
        bean:切入点表达式,配置之后该类下的所有方法都是切入点,都需要增强
        *通配符依旧可以表示所有,所有的service结尾的bean下的所有方法都需要增强
        -->
        <aop:pointcut id="ppt"
                      expression="bean(*service)"/>
		<aop:pointcut id="pppt" expression="within(com.ps.service.AccountService)"/>
        <!--配置切面,即配置切入点和通知(增强)的关系
        ref:配置命名空间,也就是配置增强方法的类,这个类必须是IOC容器管理的类,也就是必须配置好的类
        -->
        <aop:aspect ref="logService">
            <!--后置通知,或者后置增强,也就是切入点方法执行之后执行-->
            <!--
            method:增强方法,或者通知方法
            pointcut-ref:引入的切入点,也就是要增强的那个方法
            -->
            <aop:after method="log" pointcut-ref="pt"></aop:after>
        </aop:aspect>
    </aop:config>   

</beans>

通知配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <bean class="com.ps.service.AccountService" id="service"></bean>
    <bean class="com.ps.log.LogService" id="logService"></bean>

    <aop:config>
        <aop:pointcut id="pt" expression="execution(void com.ps.service.AccountService.get())"/>

        <aop:aspect ref="logService">
            <!--配置顺序为:前置,后置,异常,最终通知-->
<!--            <aop:before method="before" pointcut-ref="pt"></aop:before>
            <aop:after-returning method="later" pointcut-ref="pt"></aop:after-returning>
            <aop:after-throwing method="exception" pointcut-ref="pt"></aop:after-throwing>
            <aop:after method="finalLog" pointcut-ref="pt"></aop:after>-->
            <!--环绕通知-->
            <aop:around method="around" pointcut-ref="pt"></aop:around>
        </aop:aspect>

    </aop:config>
</beans>

5.注解配置AOP

package com.ps.log;

import com.ps.service.AccountService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.test.annotation.Commit;


@Component
@Aspect
public class LogService {

    public void log() {
        System.out.println("记录日志信息");
    }

    @Pointcut("execution(void com.ps.service.AccountService.get())")
    public void pt() {

    }

//    @Before("execution(void com.ps.service.AccountService.get())")
    public void before() {
        System.out.println("before");
    }

//    @AfterReturning("within(com.ps.service.AccountService)")
    public void later() {
        System.out.println("later");
    }

//    @AfterThrowing("pt()")
    public void exception() {
        System.out.println("exception");
    }

    public void finalLog() {
        System.out.println("finalLog");
    }

    /**
     * 演示: 环绕通知
     *  优点:
     *      1. 通用: 可以代替前后异常最终四大通知
     *      2. 而且没有顺序BUG
     *      3. 可以获取到切入点  (权限很大)
     *	缺点:
     *		需要自己创建类类实现
     */
    @Around("pt()")
    public Object around(ProceedingJoinPoint point) {
        try {
            before();

            Object[] args = point.getArgs();
            Object result=point.proceed(args);

            later();

            return result;
        } catch (Throwable throwable) {

            exception();
        } finally {
            finalLog();
        }
        return null;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值