【Spring框架】AOP切面编程的理解与实现

AOP的概念

AOP(Aspect Oriented Programming),即面向切面编程,利用一种称为"横切"的技术,剖开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。

AOP开发术语

  • 连接点(Joinpoint):连接点是程序类中客观存在的方法,可被Spring拦截并切入内容。
  • 切入点(Pointcut):被Spring切入连接点。
  • 通知、增强(Advice):可以为切入点添加额外功能,分为:前置通知、后置通知、异常通知、环绕通知等。
  • 目标对象(Target):代理的目标对象
  • 引介(Introduction):一种特殊的增强,可在运行期为类动态添加Field和Method。
  • 织入(Weaving):把通知应用到具体的类,进而创建新的代理类的过程。
  • 代理(Proxy):被AOP织入通知后,产生的结果类。
  • 切面(Aspect):由切点和通知组成,将横切逻辑织入切面所指定的连接点中。

AOP增强类

前置增强:MethodBeforeAdvice

后置增强:AfterAdvice

后置增强:AfterReturningAdvice

异常增强:ThrowsAdvice

环绕增强:MethodInterceptor

切入点表达式

匹配包名:execution(* com.robot.service.* .*(…))

  • 返回值任意,com.robot.service包下面的任意类,下面的任意方法,参数任意
<!--匹配参数-->
<aop:pointcut id="myPointCut" expression="execution(* *(com.robot.pojo.User))" />
<!--匹配方法名(无参)-->
<aop:pointcut id="myPointCut" expression="execution(* save())" />
<!--匹配方法名(任意参数)-->
<aop:pointcut id="myPointCut" expression="execution(* save(..))" />
<!--匹配返回值类型-->
<aop:pointcut id="myPointCut" expression="execution(com.robot.pojo.User *(..))" />
<!--匹配类名-->
<aop:pointcut id="myPointCut" expression="execution(* com.robot.service.userService.impl.UserServiceImpl.*(..))" />
<!--匹配包名-->
<aop:pointcut id="myPointCut" expression="execution(* com.robot.service.*.*(..))" />
<!--匹配包名、以及子包名-->
<aop:pointcut id="myPointCut" expression="execution(* com.robot..*.*(..))" />

AOP的实现

1、环境搭建

导入依赖

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>5.1.6.RELEASE</version>
</dependency>

在配置文件中引入AOP命名空间

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       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
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd
       ">
</beans>

2、创建切面类

  • 以后置增强为例
  • 基础AfterReturningAdvice接口,重写afterReturning方法
public class MyAfterAdvice implements AfterReturningAdvice {
    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println("后置增强:" + method.getName() + " 增强方法:" + o.getClass().getSimpleName());
    }
}

3、创建需要被增强的类和接口

  • 将要实现的效果就是,在调用此方法时,此方法会被增强
public interface UserDao {
    int insert();
}
public class UserDaoImpl implements UserDao {
    public int insert() {
        System.out.println("UserDaoImpl::insert...");
        return 0;
    }
}

4、修改配置文件

  • 配置aop,expression为切入点表达式
  • 具体行为execution(* com.robot.service.* .*(…)):返回值任意,com.robot.service包下面的任意类,下面的任意方法,参数任意
<bean name="userService" class="com.robot.service.impl.UserServiceImpl"/>
<bean name="myAfterAdvice" class="com.robot.aop.MyAfterAdvice"/>

<aop:config>
    <aop:pointcut id="myPointcut" expression="execution(* com.robot.service.*.*(..))"/>
    <aop:advisor advice-ref="myAfterAdvice" pointcut-ref="myPointcut"/>
</aop:config>

5、测试

  • 调用service层中的方法
public class UserServiceTest {
    @Test
    public void userServiceTest() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService = (UserService) applicationContext.getBean("userService");
        userService.insert();
    }
}

结果如下

UserDaoImpl::insert...
后置增强:insert 增强方法:Integer

在被调用的insert()方法的后面切入了增强方法,输出了方法内的语句,说明方法增强成功

总结

  • 通过AOP提供的编码流程,更便利的定制切面,更方便的定制了动态代理。

  • 进而彻底解决了辅助功能冗余的问题;

  • 业务类中职责单一性得到更好保障;

  • 辅助功能也有很好的复用性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值