12Spring_AOP编程(AspectJ)_前置通知

本文详细介绍使用AspectJ实现AOP编程的过程,包括前置通知的定义及应用,并通过实例演示如何配置Spring支持AspectJ,以及如何利用前置通知增强目标方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

接下里的博客会一篇一篇的讲解每一个通知。其实AOP_AspectJ的编程与传统的AOP的编程的最大的区别就是写一个Aspect 支持多个Advice和多个PointCut 。而且我们写AOP_Aspctj不需要继承任何的接口,不像传统的AOP还要继承接口。

前置通知是在运行我们被代理的方法之前先执行的。

前置通知具有如下的特点:

1.在目标方法执行前 进行增强代码。

2.AspectJ 提供Advice无需实现任何借口, 可以将很多通知代码 写入一个类 (切面类)

3.前置通知定义方法: 无返回值,可以传入参数 JoinPoint 连接点

 

先拿出案例,再具体讲解:

案例结构图如下:

 

CustomerService.java是目标类(被代理的类)。

MyAspect.java是切面类(里面可以写很多个通知)

TestAop2.java是junit的测试类。

applicationContext.xml是Spring的配置文件

第一步:我们先写目标类(要被代理的类)

package cn.itcast.spring.d_aspectj;

//目标业务类
public class CustomerService {
    public void update() {
        System.out.println("this is update");
    }

    public void delete() {
        System.out.println("this is delete");
    }

    public void search() {
        System.out.println("this is search");
    }

}

第二步:我们写切面类

package cn.itcast.spring.d_aspectj;

import org.aspectj.lang.JoinPoint;

//切面类(内部可以写很多的Advice的方法)
public class MyAspect {
    //前置通知1,2
    
    public void before1()
    {
        System.out.print("前置通知1");
        
        
    }
    //这个方法传入了参数JoinPoint,通过这个参数我们其实可以得到很多的信息,
    //比如现在执行的是那个切点
    public void before2( JoinPoint joinPoint)
    {
        
        
        System.out.print("前置通知2");
    }
    

}

第三步:写配置文件

<!-- AspectJ AOP -->
<!-- 配置目标 -->
<bean id="CustomerService" class="cn.itcast.spring.d_aspectj.CustomerService"></bean>
 <!-- 配置切面类 -->
<bean id="MyAspect" class="cn.itcast.spring.d_aspectj.MyAspect"></bean>
 <aop:config>
 <!-- ref引用切面类 -->
 <aop:aspect ref="MyAspect">
 
     <aop:pointcut expression="execution(* cn.itcast.spring.d_aspectj.CustomerService.*(..))" id="mypointcut2"/>
     <aop:before method="before1" pointcut-ref="mypointcut2"  />
      <aop:before method="before2" pointcut-ref="mypointcut2"  />
 </aop:aspect>
 <!-- 解释一下上面的执行流程
 <bean id="CustomerService" class="cn.itcast.spring.d_aspectj.CustomerService"></bean>
 <bean id="MyAspect" class="cn.itcast.spring.d_aspectj.MyAspect"></bean>都是是创建目标的对象。没什么好说的
 
  <aop:pointcut expression="execution(* cn.itcast.spring.d_aspectj.CustomerService.*(..))" id="mypointcut2"/>
     <aop:before method="before1" pointcut-ref="mypointcut2"  />
      <aop:before method="before2" pointcut-ref="mypointcut2"  />
      是说我们先找到pointcut-ref="mypointcut2"然后根据mypointcut2找到cn.itcast.spring.d_aspectj.CustomerService.*(..),然后
       当每次执行cn.itcast.spring.d_aspectj.CustomerService.*(..)这里的方法时
      都是执行"MyAspect"(cn.itcast.spring.d_aspectj.MyAspect)里面的before1这个方法。
      同理我们找到pointcut-ref="mypointcut2"然后根据mypointcut2找到cn.itcast.spring.d_aspectj.CustomerService.*(..),然后
       当每次执行cn.itcast.spring.d_aspectj.CustomerService.*(..)这里的方法时
      都是执行"MyAspect"(cn.itcast.spring.d_aspectj.MyAspect)里面的before2这个方法。
      
 -->
</aop:config>

第四步:写JUnit测试代码:

//整合spring和junit

//指定spring配置文件位置
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext.xml")
public class TestAop2 {
    @Autowired
    private CustomerService customerService;
    @Test
    public void testbefore()
    {System.out.print(customerService.getClass().getName());
        customerService.delete();
        
    }
    

}

最后的输出的结果是:

前置通知1

前置通知2

this is delete

 

 

 

由上面可知MyAspect"这个切面类里面的before1(Advicebefore2(Advice)都可以去执行不同的pointCut(切点)。这就是所谓的一个Aspect 支持多个Advice和多个PointCut。

 

前置通知细节:

 

        1、 默认不能阻止目标方法执行,如果抛出异常,目标方法无法执行

 

       2、 可以传入JoinPoint 连接点参数 , 通过该参数可以获得当前拦截对象和方法信息 

 

最后再提醒一点:所有的所有都是基于动态代理模式,这里没有用到接口,所以这里的代理是Cglib代理。

验证一下:

TestAop2 的代码上中写

System.out.println(customerSetvice.getClass().getName());

输出是$$EnhancerByCGLIB$$

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值