美文网首页
spring-aop

spring-aop

作者: Triste花刺 | 来源:发表于2018-06-25 22:56 被阅读0次

    Aop-面向切面编程,在程序中主要用来解决一些系统层面上的问题,比如:日志,事务,权限等。

    aop的一些基本概念:

    1. Aspect(切面):通常是一个类,里面可以定义切入点和通知
    2. JointPoint(连接点):程序执行过程中明确的点,一般是方法的调用
    3. Advice(通知):AOP在特定的切入点上执行的增强处理,有before,after,afterReturning,afterThrowing,around
    4. Pointcut(切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式

    例子(注解实现aop)

    1. 创建一个新的maven工程,并在pom文件中引入aop和ioc的相关依赖jar包
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-beans</artifactId>
                <version>4.2.4.RELEASE</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>4.2.4.RELEASE</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
                <version>4.2.4.RELEASE</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-expression</artifactId>
                <version>4.2.4.RELEASE</version>
            </dependency>
    
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>1.2.16</version>
            </dependency>
    
            <dependency>
                <groupId>commons-logging</groupId>
                <artifactId>commons-logging</artifactId>
                <version>1.2</version>
            </dependency>
    
            <dependency>
                <groupId>aopalliance</groupId>
                <artifactId>aopalliance</artifactId>
                <version>1.0</version>
            </dependency>
    
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjweaver</artifactId>
                <version>1.8.7</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aop</artifactId>
                <version>4.2.4.RELEASE</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aspects</artifactId>
                <version>4.2.4.RELEASE</version>
            </dependency>
    
    1. 在resource文件夹下创建spring的配置类,并开启启动注解扫描
    <?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"
           xmlns:context="http://www.springframework.org/schema/context"
           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">
    
        <!-- 开启spring的自动扫描-->
        <context:component-scan base-package="com.xun"></context:component-scan>
    
        <!-- 开启spring对注解aop的支持-->
        <aop:aspectj-autoproxy/>
    </beans>
    
    1. 创建一个service接口及其实现类(增强service业务方法)
    package com.xun.service.impl;
    
    import com.xun.service.AopService;
    import org.springframework.stereotype.Service;
    
    /**
    * @program:
    * @description:
    * @author: 寻。
    * @create: 2018-06-21 21:38
    **/
    @Service("aopService")
    public class AopServiceImpl implements AopService {
    
       public void save() {
           System.out.println("保存了客户。。。");
           int i=9/0;
       }
    
       public void update() {
           System.out.println("修改了客户。。。");
       }
    
       public int delete() {
           System.out.println("删除了客户。。。");
           return 0;
       }
    }
    
    1. 创建日志类用于增强service业务方法
    package com.xun.util;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.*;
    import org.springframework.stereotype.Component;
    
    /**
     * @program:
     * @description:
     * @author: 寻。
     * @create: 2018-06-21 21:42
     * @Aspect:声明当前类是一个切面
     **/
    @Component("logger")
    @Aspect
    public class Logger {
    
        /**
         * 声明切入点方法
         * 用于连接通知和被增强的方法
         * execution()切入点表达
         */
        @Pointcut("execution(* com.xun.service.impl.*.*(..))")
        private void pt(){}
        /**
         * 前置通知
         */
        @Before("pt()")
        public void beforePrintLog(){
            System.out.println("前置通知:Logger中的printLog方法执行了。。。。");
        }
    
        /**
         * 后置通知
         */
        @AfterReturning("pt()")
        public void afterPrintLog(){
            System.out.println("后置通知:Logger中的printLog方法执行了。。。。");
        }
    
        /**
         * 异常通知
         */
        @AfterThrowing("pt()")
        public void afterThrowingPrintLog(){
            System.out.println("异常通知:Logger中的printLog方法执行了。。。。");
        }
    
        /**
         * 最终通知
         */
        @After("pt()")
        public void finalPrintLog(){
            System.out.println("最终通知:Logger中的printLog方法执行了。。。。");
        }
    
        /**
         * 环绕通知
         *
         *  * 问题:当我们配置了环绕通知之后,切入点方法没有执行,而环绕通知里的代码执行了
         * 分析:由动态代理可知,环绕通知指的是invoke()方法,
         *      并且里边由明确的切入点方法调用,而我们现在环绕通知却没有明确切入点方法调用。
         * 解决:spring为我们提供了一个接口ProceedingJoinPoint,该接口可以作为环绕通知的方法参数来使用,
         *      程序运行时,spring框架会为我们提供该接口的实现类供我们使用,
         *      并且该接口中有一个proceed()方法,他的作用就等同于method.invoke()方法,
         *      就是明确调用业务层核心方法(切入点方法)
         */
        @Around("pt()")
        public Object aroundPrintLog(ProceedingJoinPoint pjp){
            Object rtValue = null;
            try {
                System.out.println("环绕通知:Logger中的printLog方法执行了。。。。前置通知");
                rtValue = pjp.proceed();
                System.out.println("环绕通知:Logger中的printLog方法执行了。。。。后置通知");
            } catch (Throwable throwable) {
                System.out.println("环绕通知:Logger中的printLog方法执行了。。。。异常通知");
                throwable.printStackTrace();
            }finally {
                System.out.println("环绕通知:Logger中的printLog方法执行了。。。。最终通知");
            }
            return rtValue;
        }
    }
    
    1. 创建一个测试类
    package com.xun;
    
    import com.xun.service.AopService;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    /**
     * @program:
     * @description:
     * @author: 寻。
     * @create: 2018-06-21 22:51
     *
     *
     **/
    public class Client {
    
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
            AopService aopService = (AopService) context.getBean("aopService");
            aopService.save();
        }
    }
    

    测试结果如下

    这里只截图了环绕通知的测试,我们看到service的核心业务方法已经被增强了


    image.png

    相关文章

      网友评论

          本文标题:spring-aop

          本文链接:https://www.haomeiwen.com/subject/aepuyftx.html