Spring框架之AOP简析

    xiaoxiao2021-12-04  46

    面向切面编程(AOP)是一种设计思想,是把应用软件分成两个部分:核心关注点和横切关注点

    在没有使用到AOP框架的时候我们经常会产生大量的重复的代码,尤其是在事务处理、日志记录等方面。由于这些经常是相同并且重复使用的代码,我们可以使用AOP框架将技术问题实现代码和业务处理(如日志)的实现代码分离,降低了两种代码的耦合性,利于代码的维护和重用。

    我们大致上可以这样理解AOP:面向对象编程(OOP)的思想主要处理的是对象间从上到下的关系,那么AOP就是一种从左到右横切的一种关系。比如说,我们现在有好几种业务流程从上到下,但是每种流程都包含了部分的日志处理,那么我们就可以将日志处理看做是一个切面,一个横切所有流程的切面,因为在每个流程的执行过程中,遇到需要进行日志记录的部分都会转去进行日志处理,这就是一个切面。

    首先看一下这样几个概念:

    切面(Aspect):一个关注点的模块化,这个关注点可能会横切多个对象连接点(Joinpoint):程序执行过程中的某个特定的点通知(Advice):在切面的某个特定的连接点上执行的动作切入点(Pointcut):匹配连接点的断言,在AOP中通知和一个切入点表达式关联引入(Introduction):在不修改类代码的前提下,为类添加新的属性和方法目标对象(Target Object):被一个或者多个切面所通知的对象AOP代理(AOP Proxy):AOP框架创建的对象,用来实现切面契约(aspect contract)(包括通知方法执行等功能)织入(Weaving):把切面连接到其他的应用程序类型或者对象上,并创建一个被通知的对象,分为:编译时织入,类加载时织入,执行时织入

    这里通过一个小的例子实现AOP的工作过程,以日志记录为例,模仿数据库的操作,同时生成日志。具体如下:

    首先是业务逻辑接口IStudentDao:

    public interface IStudentDao { public boolean save(String stuNumber, String stuName); public boolean update(String stuNumber, String stuName); public boolean delete(String stuNumber); }

    业务逻辑实现类StudentDaoImp:

    public class StudentDaoImpl implements IStudentDao { public boolean delete(String stuNumber) { System.out.println("执行delete!"); System.out.println("delete" + stuNumber + " 完成"); return true; } public boolean save(String stuNumber, String stuName) { System.out.println("执行save!"); System.out.println("save" + stuNumber + ", save" + stuName); return true; } public boolean update(String stuNumber, String stuName) { System.out.println("ִupdate!"); System.out.println("update" + stuNumber + ", " + stuName); return true; } }

    创建日志功能类,在实际被调用的方法执行完成之后,执行该类的方法LogAfterReturningAdvice.java:

    import java.lang.reflect.Method; import java.text.DateFormat; import java.util.Date; import org.springframework.aop.AfterReturningAdvice; public class LogAfterReturningAdvice implements AfterReturningAdvice { public void afterReturning(Object returnValue, Method targetMethod, Object[] methodArgs, Object targetClass) throws Throwable { boolean success = ((Boolean)returnValue).booleanValue(); if(success){ String className = targetClass.getClass().getName(); String methodName = targetMethod.getName(); Date date = new Date(); String curTime = DateFormat.getDateTimeInstance().format(date); String logInfo = "[" + curTime + "]" + className + "." + methodName + "() 方法被调用"; System.out.println(logInfo + "LogAfterReturningAdvice"); } } }

    然后创建配置文件,将业务代码和日志功能代码组装在一起aop-config.xml

    <?xml version='1.0' encoding='UTF-8'?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="studentPointcut" class="com.chinasei.spring.aop.StudentDaoImpl" /> <bean id="logAfterReturningAdvice" class="com.chinasei.spring.aop.LogAfterReturningAdvice" /> <bean id="studentAdvisor" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="proxyInterfaces"> <value>com.chinasei.spring.aop.IStudentDao</value> </property> <property name="interceptorNames"> <list><value>regexAdvisor</value></list> </property> <property name="target" ref="studentPointcut" /> </bean> </beans>

    对于上面的配置文件前面的两个bean用来定义业务处理逻辑和日志功能,其中id=studentPointcut的Bean是要代理的目标类。最后一个Bean是用来组装业务处理代码和日志功能代码的bean是使用ProxyFactoryBean类的实例(创建代理类的类)。

    然后创建一个测试类SpringAOPTest

    package com.chinasei.spring.aop; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class SpringAOPTest { public static void main(String[] args){ ApplicationContext context = new ClassPathXmlApplicationContext("aop-config.xml"); IStudentDao student = (IStudentDao)context.getBean("studentAdvisor"); student.save("1234561", "张三"); student.update("1234561", "李四"); student.delete("1234561"); } }

    执行结果如下:

    发现在每次执行完成逻辑操作之后都会进行日志的处理。

    上面的整个流程可以这样解释,首先通过ClassPathXmlApplicationContext类加载配置文件,生成上下文应用关系,然后通过applicationContext获取Bean,获取的Bean的id指向为studentAdvisor,这时,ProxyFactoryBean就会根据子元素的属性创建代理类,子元素中包含了3个标签,分别是proxyInterfaces,是要代理的类的接口,interceptorNames是要完成日志功能的类,即就是一系列的拦截器,可以认为是要通知执行的方法,最后一个子元素属性为target是实现业务处理的类。

    代理类创建完成之后就如同在studentDaoImpl类中的方法上,添加了通知,在该类中的方法执行完成返回之后就会执行logAfterReturningAdvice类中的方法。

    这一篇只是简单通过一个例子大致将AOP的流程串起来,具体的知识还有好多,比如Advice、Pointcut和Advisor,以及使用ProxyFactoryBean创建AOP代理,这些部分都包含了很多的内容,还需要更加深入的学习!

    转载请注明原文地址: https://ju.6miu.com/read-680270.html

    最新回复(0)