spring入门aop和ioc-AOP入门

时间:2024-06-08 20:24:05
  1. 导入坐标依赖

    <dependency>
                <groupId>aopalliance</groupId>
                <artifactId>aopalliance</artifactId>
                <version>1.0</version>
            </dependency>
            <!--Spring Aspects-->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aspects</artifactId>
                <version>5.0.2.RELEASE</version>
            </dependency>
            <!--aspectj-->
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjweaver</artifactId>
                <version>1.8.3</version>
            </dependency>
    
    <?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:context="http://www.springframework.org/schema/context"
           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/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd">
    </beans>
    
  2. 编写spirng配置文件中AOP的配置部分

        <!--    bean管理-->
        <bean id="us" class="com.qc.service.impl.UserServiceImpl"/>
        <bean id="myAspect" class="com.qc.util.MyAspect"/>
    
        <!--    配置aop-->
        <aop:config>
            <!--        配置切面-->
            <aop:aspect ref="myAspect">
                <!--            前缀通知-->
                <aop:before method="log1" pointcut="execution(public void com.qc.service.impl.UserServiceImpl.save())"/>
                <!--            后置通知-->
                <aop:after-returning method="log2"
                                     pointcut="execution(public void com.qc.service.impl.UserServiceImpl.save())"/>
                <!--            异常通知-->
                <aop:after-throwing method="log3"
                                    pointcut="execution(public void com.qc.service.impl.UserServiceImpl.save())"/>
                <!--            最终通知-->
                <aop:after method="log4"
                           pointcut="execution(public void com.qc.service.impl.UserServiceImpl.save())"/>
    
                <!--            环绕通知-->
                <aop:around method="aroundLog"
                            pointcut="execution(public void com.qc.service.impl.UserServiceImpl.save())"/>
            </aop:aspect>
        </aop:config>
    
    import org.aspectj.lang.ProceedingJoinPoint;
    
    public class MyAspect {
        // 自定义切面类 = 切入点+通知
        //通知
        public void log1() {
            System.out.println("前置增强的");
        }
    
        public void log2() {
            System.out.println("后置增强的");
        }
    
        public void log3() {
            System.out.println("异常增强的");
        }
    
        public void log4() {
            System.out.println("最终增强的");
        }
    
    
        public void aroundLog(ProceedingJoinPoint point) {
            try {
                log1();
                point.proceed(); // 目标方法调用
                log2();
            } catch (Throwable e) {
                e.printStackTrace();
                log3();
            } finally {
                log4();
            }
        }
    }
    

    注意环绕通知使用的接口

通知类型

  1. 前置通知:目标方法执行前进行增强
  2. 后置通知:目标方法执行后进行增强
  3. 异常通知:目标方法出现异常后进行增强
  4. 最终通知:目标方法无论是否异常都进行增强
  5. 环绕通知:目标方法执行前后,都进行增强,不过需要自己书写

切入点表达式

  • execution([修饰符] 返回值 包名.类名.方法名(参数))
  • 修饰符可以省略不写
  • 返回值类型不能省略,根据方法来编写返回值,可以用星号来代替
  • 包名类型方法名是不能省略的,但是可以用星号来代替,也可以部分代替
  • 参数如果是一个可以用星号来代替,如果是多个可以使用两个点

因此比较通用的表达式:

execution( com.qc.*.Service.save(…))