SpringAOP入门-面向切面编程

先解释一下到底什么是AOP吧。


如图,系统中有若干个模块,每个模块对应某功能,而还有些特定的功能是每个模块几乎都会用到的,比如日志这种,想要降低日志模块和每个模块的耦合,那么AOP就是必须的了。在这里,所谓的Aspect(切面)就是日志模块,而其他模块就是被切的。

AOP:面向切面编程

  • 切面:系统里面一个特定的模块,贯穿整个系统。比如日志。

  • 配置方式:java注解或者用xml配置。

  • 利用JAVA注解实现AOP

    1、配置Spring依赖(Spring版本最好选择4.0.0到5.0.0之间)

    <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>4.3.7.RELEASE</version>
    </dependency>
    <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>4.3.7.RELEASE</version>
    </dependency>
    <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>4.3.7.RELEASE</version>
    </dependency>
    <dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.8.9</version>
    </dependency>

    2、创建(生成)Spring配置文件

    如果用的是IntelliJ IDEA,可以快捷生成spring的配置文件,方法如下:

    右键项目名-->NEW-->XML Configuration File-->Spring Config

    生成了Spring配置文件后,添加关于AOP的文件头:

    <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">

    添加自动代理:

    <aop:aspectj-autoproxy expose-proxy="true"/>

    创建三个类,分别是:

    1、将被切入的类,也就是普通的Service

    public class CustomerService {
        private String name;
        private String url;
    
        public void setName(String name) {
            this.name = name;
        }
    
        public void setUrl(String url) {
            this.url = url;
        }
    
        public void printName() {
            System.out.println("Customer name : " + this.name);
        }
    
        public void printURL() {
            System.out.println("Customer website : " + this.url);
        }
    
        public void printThrowException() {
            throw new IllegalArgumentException();
        }
    }

    2、切面类,用于切入

    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    
    @Aspect
    public class MyAspect {
        @Pointcut("execution(* cn.jdfo.CustomerService.printName())")
        public void pointCut(){}
    
        @Before("pointCut()")
        public void logBefore(){
            System.out.println("before");
        }
    }

    切面类用了aspectj的注解,还有After、AfterRunning、AfterReturning、Around这些。

    Pointcut是一个切入点,上面的logBefore方法就是在printName方法结束之前执行。

    3、程序入口

    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class App {
        public static void main(String[] args) {
            ApplicationContext appContext = new ClassPathXmlApplicationContext(new String[] { "spring.xml" });
            CustomerService cust = (CustomerService) appContext.getBean("customerService");
            System.out.println("*************************");
            cust.printName();
            System.out.println("*************************");
            cust.printURL();
            System.out.println("*************************");
            try {
                cust.printThrowException();
            } catch (Exception ignored) {
            }
        }
    }

    这个程序在JAVA8中运行正常,但是在JAVA9运行会出现错误:

    java.lang.IllegalArgumentException: error at ::0 can't find referenced pointcut pointCut

    还不清楚发生这个错误的原因。

    另:ApplicationContext可以通过多种方式获得,这里用的是用于测试的一种,直接生成一个应用环境,而在实际应用中通常通过实现一个接口:ApplicationAware(好像这样的)。详见:

    接下来是通过xml配置实现AOP

    xml配置:

    <bean id="mysAspect" class="cn.jdfo.MySAspect"/>
        <aop:config>
            <aop:pointcut id="apointcut" expression="execution(* cn.jdfo.CustomerService.*(..))"/>
            <aop:aspect id="aaspect" ref="mysAspect">
                <aop:before method="logBefore" pointcut-ref="apointcut"/>
                <aop:after method="logAfter" pointcut-ref="apointcut"/>
            </aop:aspect>
        </aop:config>

    MySAspect类:

    public class MySAspect {
        public void logBefore(){
            System.out.println("before");
        }
        public void logAfter(){
            System.out.println("after");
        }
    }

    这个用JAVA9就没有问题,运行结果如下:

    *************************
    before
    Customer name : Jdfohewk
    after
    *************************
    before
    Customer website : http://www.baidu.com
    after
    *************************
    before
    after

    两种方法相比较,Spring AOP兼容性更好,而AspectJ暂时还不能很好地支持JAVA9,代码复杂程度二者差不多。所以我选择用Spring AOP...

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值