spring框架基础(04):aop切面编程概念,几种实现方式演示

     2022-04-02     354

关键词:

本文源码:GitHub·点这里 || GitEE·点这里

一、AOP基础简介

1、切面编程简介

AOP全称:Aspect Oriented Programming,面向切面编程。通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。核心作用:可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的复用性和开发效率。AOP提供了取代继承和委托的一种新的方案,而且使用起来更加简洁清晰,是软件开发中的一个热点理念。

2、AOP术语

技术图片

(1)、通知类型:Advice

前置通知[Before]:目标方法被调用之前;
返回通知[After-returning]:目标方法执行成功之后;
异常通知[After-throwing]:在目标方法抛出异常之后; 
后置通知[After]:目标方法完成之后;
环绕通知[Around]:在目标方法执行前后环绕通知;

(2)、连接点:JoinPoint

程序执行的某一个特定位置,如类初始前后,方法的运行前后。

(3)、切点:Pointcut

连接点是指那些在指定策略下可能被拦截到的方法。

(4)、切面:Aspect

切面由切点和通知的结合。

(5)、引入:Introduction

特殊的增强,为类添加一些属性和方法。

(6)、织入:Weaving

将增强添加到目标类的具体连接点上的过程。编译期织入,这要求使用特殊编译器;类装载期织入,这要求使用特殊的类加载器;动态代理织入,在运行期为目标类添加增强生成子类的方式,Spring采用的是动态代理织入,而AspectJ采用编译期织入和类装载期织入。

(7)、代理:Proxy

类被AOP织入后生成一个结果类,它是融合了原类和增强逻辑的代理类。

二、AOP编程实现方式

案例基于如下类进行:

public class Book {
    private String bookName ;
    private String author ;
}
public interface BookService {
    void addBook (Book book) ;
}
public class BookServiceImpl implements BookService {
    @Override
    public void addBook(Book book) {
        System.out.println(book.getBookName());
        System.out.println(book.getAuthor());
    }
}

1、JDK动态代理

public class BookAopProxyFactory {
    public static BookService createService() {
        // 目标类
        final BookService bookService = new BookServiceImpl() ;
        // 切面类
        final BookAspect bookAspect = new BookAspect();
        /*
         * 代理类:将目标类(切入点)和 切面类(通知) 结合
         */
        BookService proxyBookService = (BookService) Proxy.newProxyInstance(
                BookAopProxyFactory.class.getClassLoader(),
                bookService.getClass().getInterfaces(),
                new InvocationHandler() {
                    public Object invoke(Object proxy, Method method,
                                         Object[] args) throws Throwable {
                        // 前执行
                        bookAspect.before();
                        // 执行目标类的方法
                        Object obj = method.invoke(bookService, args);
                        // 后执行
                        bookAspect.after();
                        return obj;
                    }
                });
        return proxyBookService ;
    }
}

2、CgLib字节码增强

采用字节码增强框架cglib,在运行时创建目标类的子类,从而对目标类进行增强。

public class BookAopCgLibFactory {
    public static BookService createService() {
        // 目标类
        final BookService bookService = new BookServiceImpl() ;
        // 切面类
        final BookAspect bookAspect = new BookAspect();
        // 核心代理类
        Enhancer enhancer = new Enhancer();
        // 确定父类
        enhancer.setSuperclass(bookService.getClass());
        // 设置回调函数
        enhancer.setCallback(new MethodInterceptor() {
            public Object intercept(Object proxy, Method method,
                                    Object[] args,
                                    MethodProxy methodProxy) throws Throwable {
                bookAspect.before();
                Object obj = method.invoke(bookService, args);
                bookAspect.after();
                return obj;
            }
        });
        BookServiceImpl proxyService = (BookServiceImpl) enhancer.create();
        return proxyService ;
    }
}

3、Spring半自动代理

spring 创建代理对象,从spring容器中手动的获取代理对象。

  • 配置文件
<!-- 创建目标类 -->
<bean id="bookService" class="com.spring.mvc.service.impl.BookServiceImpl" />
<!-- 创建切面类 -->
<bean id="myAspect" class="com.spring.mvc.config.BookAopSpringHalf" />
<!-- 创建代理类 -->
<bean id="proxyFactory" class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="interfaces" value="com.spring.mvc.service.BookService" />
    <property name="target" ref="bookService" />
    <property name="interceptorNames" value="myAspect" />
</bean>
  • 切面类
public class BookAopSpringHalf implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        System.out.println("Method Before ...");
        Object obj = methodInvocation.proceed();
        System.out.println("Method After ...");
        return obj;
    }
}

4、Spring全自动代理

从spring容器获得目标类,如果配置Aop,spring将自动生成代理。

  • 配置文件
<!-- 创建目标类 -->
<bean id="bookService" class="com.spring.mvc.service.impl.BookServiceImpl" />
<!-- 创建切面类 -->
<bean id="myAspect" class="com.spring.mvc.config.BookAopSpringHalf" />
<!-- AOP编程配置 -->
<aop:config proxy-target-class="true">
    <aop:pointcut expression="execution(* com.spring.mvc.service.*.*(..))"
                  id="myPointCut"/>
    <aop:advisor advice-ref="myAspect" pointcut-ref="myPointCut"/>
</aop:config>

5、综合测试

@Test
public void test1 (){
    BookService bookService = BookAopProxyFactory.createService() ;
    Book book = new Book() ;
    book.setBookName("Spring实战");
    book.setAuthor("Craig Walls");
    bookService.addBook(book);
}
@Test
public void test2 (){
    BookService bookService = BookAopCgLibFactory.createService() ;
    Book book = new Book() ;
    book.setBookName("MySQL");
    book.setAuthor("Baron");
    bookService.addBook(book);
}
@Test
public void test3 (){
    String xmlPath = "spring-aop-half.xml";
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(xmlPath);
    BookService bookService = (BookService) context.getBean("proxyFactory");
    Book book = new Book() ;
    book.setBookName("红楼梦");
    book.setAuthor("曹雪芹");
    bookService.addBook(book);
}
@Test
public void test4 (){
    String xmlPath = "spring-aop-all.xml";
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(xmlPath);
    BookService bookService = (BookService) context.getBean("bookService");
    Book book = new Book() ;
    book.setBookName("西游记");
    book.setAuthor("吴承恩");
    bookService.addBook(book);
}

三、AspectJ切面编程

1、基础简介

AspectJ是一个基于Java语言的AOP框架,Spring2.0以后新增了对AspectJ切点表达式支持,通过JDK5注解技术,允许直接在类中定义切面,新版本Spring框架,推荐使用AspectJ方式来开发AOP编程。

2、XML配置方式

  • 切面类
public class BookAopAspectJ {
    public void myBefore(JoinPoint joinPoint){
        System.out.println("前置通知:" + joinPoint.getSignature().getName());
    }
    public void myAfterReturning(JoinPoint joinPoint,Object ret){
        System.out.println("后置通知:" + joinPoint.getSignature().getName() + " , -->" + ret);
    }
    public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{
        System.out.println("环绕通知前");
        Object obj = joinPoint.proceed();
        System.out.println("环绕通知前后");
        return obj;
    }
    public void myAfterThrowing(JoinPoint joinPoint,Throwable e){
        System.out.println("抛出异常通知 : " + e.getMessage());
    }
    public void myAfter(JoinPoint joinPoint){
        System.out.println("最终通知");
    }
}
  • 配置文件
<!-- 创建目标类 -->
<bean id="bookService" class="com.spring.mvc.service.impl.BookServiceImpl" />
<!-- 创建切面类 -->
<bean id="myAspect" class="com.spring.mvc.config.BookAopAspectJ" />
<!-- 配置AOP编程 -->
<aop:config>
    <aop:aspect ref="myAspect">
        <aop:pointcut expression="execution(* com.spring.mvc.service.impl.BookServiceImpl.*(..))" id="myPointCut"/>
        <!-- 前置通知-->
        <aop:before method="myBefore" pointcut-ref="myPointCut"/>
        <!-- 后置通知 -->
        <aop:after-returning method="myAfterReturning" pointcut-ref="myPointCut" returning="ret" />
        <!-- 环绕通知 -->
        <aop:around method="myAround" pointcut-ref="myPointCut"/>
        <!-- 抛出异常 -->
        <aop:after-throwing method="myAfterThrowing" pointcut-ref="myPointCut" throwing="e"/>
        <!-- 最终通知 -->
        <aop:after method="myAfter" pointcut-ref="myPointCut"/>
    </aop:aspect>
</aop:config>
  • 测试方法
@Test
public void test1 (){
    String xmlPath = "spring-aop-aspectj-01.xml";
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(xmlPath);
    BookService bookService = (BookService) context.getBean("bookService");
    Book book = new Book() ;
    book.setBookName("三国演义");
    book.setAuthor("罗贯中");
    bookService.addBook(book);
}

3、注解扫描方式

  • 配置文件
<!-- 开启类注解的扫描 -->
<context:component-scan base-package="com.spring.mvc.service.impl" />
<!-- 确定AOP注解生效 -->
<aop:aspectj-autoproxy />
<!-- 声明切面 -->
<bean id="myAspect" class="com.spring.mvc.config.AuthorAopAspectJ" />
<aop:config>
    <aop:aspect ref="myAspect" />
</aop:config>
  • 注解切面类
@Component
@Aspect
public class AuthorAopAspectJ {
    @Pointcut("execution(* com.spring.mvc.service.impl.AuthorServiceImpl.*(..))")
    private void myPointCut(){
    }
    @Before("execution(* com.spring.mvc.service.impl.AuthorServiceImpl.*(..))")
    public void myBefore(JoinPoint joinPoint){
        System.out.println("前置通知:" + joinPoint.getSignature().getName());
    }
    @AfterReturning(value="myPointCut()" ,returning="ret")
    public void myAfterReturning(JoinPoint joinPoint,Object ret){
        System.out.println("后置通知:" +
                joinPoint.getSignature().getName() + " , -->" + ret);
    }
    @Around(value = "myPointCut()")
    public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{
        System.out.println("环绕通知前");
        Object obj = joinPoint.proceed();
        System.out.println("环绕通知前后");
        return obj;
    }
    @AfterThrowing(
            value="execution(* com.spring.mvc.service.impl.AuthorServiceImpl.*(..))",
            throwing="e")
    public void myAfterThrowing(JoinPoint joinPoint,Throwable e){
        System.out.println("抛出异常通知 : " + e.getMessage());
    }
    @After("myPointCut()")
    public void myAfter(JoinPoint joinPoint){
        System.out.println("最终通知");
    }
}
  • 测试方法
@Test
public void test2 (){
    String xmlPath = "spring-aop-aspectj-02.xml";
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(xmlPath);
    AuthorService authorService = (AuthorService) context.getBean("authorService");
    System.out.println("作者:"+authorService.getAuthor());
}

四、源代码地址

GitHub·地址
https://github.com/cicadasmile/spring-mvc-parent
GitEE·地址
https://gitee.com/cicadasmile/spring-mvc-parent

技术图片

spring框架系列-深入浅出spring核心之面向切面编程(aop)

在​​Spring基础-Spring简单例子引入Spring的核心​​中向你展示了AOP的基础含义,同时以此发散了一些AOP相关知识点;本节将在此基础上进一步解读AOP的含义以及AOP的使用方式。@pdai引入我们在​​Spring基础-Spring简单例子引入Spring... 查看详情

spring框架--aop面向切面编程(代码片段)

Spring框架往期文章Spring框架(一)–spring搭建和IOCSpring框架(二)–SpringBean管理Spring框架(三)–SpringJDBCSpring框架(四)–AOP面向切面编程Spring框架(五)–Spring事务管理和Spring事务传播行为AOP(AspectOrientedProgramming面向切面编程)不使用AOP的开... 查看详情

spring基础_面向切面(aop)

...运行期间动态代理实现程序功能的统一维护的技术。AOP是Spring框架中的一个重要内容,利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。在... 查看详情

spring基础:aop概念和原理

文章目录AOP概念和原理一、AOP概念二、AOP原理三、AOP中的术语辨析1、连接点 Jointpoint2、切入点 Pointcut3、通知 Advice4、目标对象 Target5、切面Aspect6、织入WeavingAOP概念和原理一、AOP概念AOP切面编程一般可以帮助我们在不修改现有... 查看详情

spring框架--aop面向切面编程(代码片段)

Spring框架往期文章Spring框架(一)–spring搭建和IOCSpring框架(二)–SpringBean管理Spring框架(三)–SpringJDBCSpring框架(四)–AOP面向切面编程Spring框架(五)–Spring事务管理和Spring事务传播行为AOP(AspectOrientedProgramming面向切面编程)不使用AOP的开... 查看详情

spring基础ioc(控制反转)aop(面向切面编程)log4j注解配置

学习示例代码,包含本篇介绍的Spring常用操作示例和所有所需jar文件下载地址:http://download.csdn.net/detail/daijin888888/95566971.什么是Spring,有什么作用 --Spring框架属于一个解决方案框架,可以对其他技术和框架进行整合应用。&nbs... 查看详情

spring框架aop增强,动态代理(代码片段)

...;(1)以AspectJ为代表的静态代理。(2)以SpringAOP为代表的动态代理。AOP的基本概念AOP:面向切面编程,不修改源代码的基础上对代理对象的功能进行增强,要指定增强位置配置该位置做的事情 1.切面(Aspest)... 查看详情

spring的aop面向切面编程

用设计模式是思想理解:面向切面编程1、spring自动生成代理类   Spring的AOP面向切面编程什么是AOP?1.AOP概念介绍  所谓AOP,即Aspect orientied program,就是面向方面(切面)的编程。   功能:让关注点代码与业... 查看详情

spring4——aop面向切面

...AspectOrientedProgramming(AOP),是软件开发中的一个热点,也是Spring框架中的一个重要内容。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。主... 查看详情

springaop——基础概念(代码片段)

前文的一些内容更多是针对Spring容器内部的一些特性的描述,接下来一个专题将描述SpringAOP的一些信息,配置细节等等。介绍面向切面编程(AOP)是一种新的针对程序结构的思路,它补足了面向对象编程(... 查看详情

面向切面编程的介绍和使用(spring框架)

Spring框架整理第二发,AOP的介绍和使用。AOP概述AOP:aspectorientedprogramming:面向切面编程OOP:ObjectOrientedprogramming:面向对象编程AOP和OOP是两种编程思想,AOP是OOP的一种补充。面向切面编程:是指在程序... 查看详情

spring的aop面向切面编程

什么是AOP?1.AOP概念介绍  所谓AOP,即Aspect orientied program,就是面向方面(切面)的编程。   功能:让关注点代码与业务代码分离!关注点:         重复代码就叫做关注点;业务代码: ... 查看详情

spring一文带你吃透aop面向切面编程技术(上篇)(代码片段)

个人主页:几分醉意的CSDN博客_传送门文章目录💖AOP概念✨AOP作用✨AOP术语✨什么时候需要用AOP💖Aspectj框架介绍✨Aspectj的5个通知注解✨Aspectj切入点表达式✨前置通知@Before💖投票传送门(欢迎伙伴们投票... 查看详情

spring面向切面编程(aop)

Spring系列教程Spring框架介绍Spring框架模块Spring开发环境搭建(Eclipse)创建一个简单的Spring应用Spring控制反转容器(InversionofControl–IOC)理解依赖注入(DI–DependencyInjection)BeanXML配置(1)-通过XML配置加载BeanBeanXML配置(2)-Bean作... 查看详情

aop面向切面编程

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

aop思想(面向切面编程)

...解AOP的童鞋看透弄懂AOP,也欢迎高手批评指正。先说一个Spring是什么吧,大家都是它是一个框架,但框架这个词对新手有点抽象,以致于越解释越模糊,不过它确实是个框架的,但那是从功能的角度来定义的,从本质意义上来讲... 查看详情

(语法基础)浅谈面向切面编程(aop)(代码片段)

...编程中合理的运用AOP思想是很有必要的二:AOP的基本概念基础概念:AOP中文翻译面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。三:通过动态代理实现AOP读完上面的概念,也许还不知道什... 查看详情

spring框架

1Spring框架   SpringFramework,它是很多模块的集合,使用这些模块可以很方便地协助我们进行开发。  这些模块是:核心容器、数据访问/集成,、Web、AOP(面向切面编程)、工具、消息和测试模块。比如:CoreContainer中的Core... 查看详情