Spring中AOP通俗入门理解

Posted 递归真的不会

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring中AOP通俗入门理解相关的知识,希望对你有一定的参考价值。

本文是刚学了AOP后整理的笔记,理解的可能有些偏差,欢迎补充。

目录

一、什么是AOP

二、AOP的作用及优势

三、AOP术语

四、基于XML的AOP开发

1、导入AOP相关坐标

 2、 创建目标接口和目标类(内部有切点)

目标接口

目标类Target

3、 创建切面类(内部有增强方法)

4、 将目标类和切面类的对象创建权交给spring

5、在applicationContext.xml中配置织入关系

导入aop命名空间

配置切点表达式和增强的织入关系

6、 测试

测试展示电脑

测试销售电脑

五、小结


一、什么是AOP

        首先看一下AOP概念

来源百度百科:

AOP全名Aspect Oriented Programming,意思是面向切面编程。通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。

        AOP是OOP的延续,是软件开发的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各个部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

         看完还是不懂,接下来以一个小案例来解释:

        你是一名广东顾客,想要买一台联想电脑,而联想电脑的官方店在北京。你可以直接到北京的官方店购买联想电脑,但是这样路途太遥远了。而在广东,有一家联想电脑代理商,他们可以到北京购买联想电脑,然后再销售给你,从中获取一定的代理费。而你则不用跑到北京的官方店购买,你只用跟代理商购买就行了。

        联想官方店在销售电脑前会展示电脑,接着再销售电脑。

        代理商在向你展示电脑前,会有个小广告“来这买,隔天送达”,说完再展示电脑;在销售电脑前,会告诉你收取代理费100元,然后再销售电脑,销售完后会再送你一个鼠标。完成上述动作后会说“谢谢惠顾”。

        AOP就可以理解为上面的代理商代理联想电脑官方店的过程。联想电脑官方店(目标对象Target)把展示电脑和销售电脑两个动作(连接点 Joinpoint)交给代理商(切面 Aspect)接管,代理商在展示电脑和销售电脑两个动作(切入点 Pointcut)前后又增加了其他动作(通知/增强 Advice),从而实现代理联想电脑(代理 Proxy),从而实现代理商的更多服务(织入 Weaving)

        实际上,就是Spring通过代理技术生成代理对象,代理对象方法执行时进行增强功能的介入,再去调用目标对象的方法,从而完成功能的增强。


二、AOP的作用及优势

作用:在程序运行期间,在不修改源码情况下对方法进行功能增强。

优势:减少重复代码,提高开发效率,并且便于维护。


三、AOP术语

术语名称解释
Target(目标对象)代理的目标对象
Proxy(代理)一个类被AOP织入增强后,就产生一个结果
Joinpoint(连接点)指被拦截到的点(即方法)。在spring中,这些点指方法,因为spring只支持方法类型的连接点。
Pointcut(切入点)指我们要对哪些Joinpoint进行拦截的定义
Advice(通知/增强)指拦截到的Joinpoint之后要做的事情就是通知
Aspect(切面)切入点和通知的结合
WeAving(织入)把增强应用到目标对象来创建新的代理对象的过程。spring采用动态代理织入,而AspectJ采用编译期织入和类装载期织入。

四、基于XML的AOP开发

AOP的步骤如下:

① 导入AOP相关坐标

② 创建目标接口和目标类(内部有切点,即方法)

③ 创建切面类(内部有增强方法)

④ 将目标类和切面类的对象创建权交给spring

⑤ 在applicationContext.xml中配置织入关系

⑥ 测试运行

还是以联想电脑及代理商为例说明:

1、导入AOP相关坐标

为了便于测试,一同导入了其它坐标(spring-test和junit)

  <dependencies>
    <!--导入spring的context坐标-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.0.5.RELEASE</version>
    </dependency>
    <!--aspectj的织入-->
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.8.4</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>5.0.5.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
    </dependency>
  </dependencies>

 2、 创建目标接口和目标类(内部有切点)

目标接口

目标接口是电脑公司接口,具有展示电脑show()和销售电脑sell(int money)两个行为。

/*目标接口*/
//电脑公司接口
public interface ComputerCompany 
    //展示电脑
    void show();
    //卖电脑
    String sell(int money);

目标类Target

目标类是联想电脑Lenovo,其实现电脑公司接口,并实现展示电脑和销售电脑两个行为。

/*目标类Target*/
//联想电脑公司
public class Lenovo implements ComputerCompany 
    //电脑展示
    public void show() 
        System.out.println("联想官方店电脑展示");
    

    //电脑销售
    public String sell(int money) 
        System.out.println("卖出电脑"+money+"元");
        return "联想官方店电脑";
    

3、 创建切面类(内部有增强方法)

代理商代理销售联想电脑,在展示电脑前会打广告,输出“来这买,隔天送达”。在展示电脑和销售电脑前,告知“收取代理费100元”,在销售电脑后,会再“送一个鼠标”。结束服务后,会说“谢谢惠顾”。

/*切面类Aspect*/
//联想电脑代理商
public class Agent 
    //展示电脑前
    public void before()
        System.out.println("来这买,隔天送达");
    

    //展示电脑、销售电脑前后
    public Object arround(ProceedingJoinPoint pjp) throws Throwable 
        System.out.println("收取代理费100元");
        Object proceed=pjp.proceed();
        System.out.println("送一个鼠标");
        return proceed;
    

    //结束服务
    public void after()
        System.out.println("谢谢惠顾");
    

4、 将目标类和切面类的对象创建权交给spring

创建一个applicationContext.xml配置文件,配置目标类Lenovo和切面类Agent。

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


    <!--配置目标类-->
    <bean id="Lenovo" class="com.qianhan.aop.Lenovo"></bean>
    <!--配置切面类-->
    <bean id="Agent" class="com.qianhan.aop.Agent"></bean>

</beans>

5、在applicationContext.xml中配置织入关系

导入aop命名空间

配置切点表达式和增强的织入关系

    <aop:config>
        <aop:aspect ref="Agent">
            <!--在电脑展示方法前增强-->
            <aop:before method="before" pointcut="execution(public void com.qianhan.aop.Lenovo.show())"></aop:before>
            <!--在展示电脑和销售电脑前后增强-->
            <aop:around method="arround" pointcut="execution(* com.qianhan.aop.*.*(..))"></aop:around>
            <!--在服务结束后增强-->
            <aop:after method="after" pointcut="execution(* com.qianhan.aop.*.*(..)))"></aop:after>
        </aop:aspect>
    </aop:config>

 整理:以上整个applicationContext.xml配置文件如下:

<?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 id="Lenovo" class="com.qianhan.aop.Lenovo"></bean>
    <!--配置切面类-->
    <bean id="Agent" class="com.qianhan.aop.Agent"></bean>

    <aop:config>
        <aop:aspect ref="Agent">
            <!--在电脑展示方法前增强-->
            <aop:before method="before" pointcut="execution(public void com.qianhan.aop.Lenovo.show())"></aop:before>
            <!--在展示电脑和销售电脑前后增强-->
            <aop:around method="arround" pointcut="execution(* com.qianhan.aop.*.*(..))"></aop:around>
            <!--在服务结束后增强-->
            <aop:after method="after" pointcut="execution(* com.qianhan.aop.*.*(..)))"></aop:after>
        </aop:aspect>
    </aop:config>

</beans>

6、 测试

编写测试类,如下所示

测试展示电脑

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class AopTest 
    //目标对象
    @Autowired
    private ComputerCompany company;

    /*测试代理商展示电脑*/
    @Test
    public void test1()
        company.show();
    

测试结果如下:

如果没有代理商的增强,应该是只输出“联想官方店电脑展示”。增强后则多了另外四句。

测试销售电脑

    /*测试代理商销售电脑*/
    @Test
    public void test2()
        String computer = company.sell(5000);
        System.out.println("购买到了:"+computer);
    

 如果没有代理商的增强,应该是只输出“卖出电脑5000元”和“购买到了:联想官方店电脑”。增强后则多了另外三句。


五、小结

        通过以上案例可看出,AOP就是通过预编译方式和运行期动态代理实现在不修改源代码的情况下,给程序动态统一添加特定功能的一种技术。 AOP主要功能是日志记录,性能统计,安全控制,事务处理,异常处理等等。

        如果说面向对象编程时关注将需求功能分为不同的并且相对独立,封装良好的类,具有总结的行为,依靠继承和多态等来定义彼此的关系的话,那么面向切面编程则是希望能够将通用需求功能从不相关的类当中分离出来,能够使得很多类共享一个行为,一旦发生变化,不必修改很多类,只要修改这个行为即可。

        

以上是关于Spring中AOP通俗入门理解的主要内容,如果未能解决你的问题,请参考以下文章

通俗易懂式分析静态代理模式_ _扎根spring AOP必须要掌握的代理模式之静态代理

Spring AOP入门基础-继承装饰者,代理的选择

Spring中AOP的一个通俗易懂的理解(转)

Spring入门到进阶 - Spring AOP

SpringBoot默认开启AOP,采用Cglib代理方式?(Spring AOP快速入门)

SpringBoot默认开启AOP,采用Cglib代理方式?(Spring AOP快速入门)