Spring学习三(AOP面向切面编程)

本文介绍了AOP(面向切面编程)的概念及其在Spring框架中的应用。详细解释了AOP的基本原理,包括如何通过预编译方式和运行期动态代理实现程序功能的统一维护。此外还介绍了AOP的重要概念,如Target目标类、JoinPoint连接点、PointCut切入点、Advice增强、Weaving织入等,并提供了基于XML配置和AspectJ注解方式的AOP实现示例。

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

1、AOP面向切面编程

这里写图片描述
AOP(Aspect Oriented Programming)面向切面编程。通过预编译方式和运行期动态代理实现程序功能的统一维护。
AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

1、这种在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。
2、将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。

AOP其实是将琐碎的事务和逻辑代码相分离,以便我们更好的关注逻辑代码
代码逻辑比如是插入一条数据,那么琐碎事务就包括获取连接和关闭连接,事务开始,事务提交。
切面就是指在大堆繁琐事务中的逻辑代码。

AOP原理
AOP采取横向的抽取机制,取代传统由于继承产生的代码重复

AOP是在编译时期运用反射机制,通过代理方式向目标类植入代码
这里写图片描述

2、重要概念

1、Target :目标类,需要被增强程序。
2、JoinPoint:连接点,目标类中可以被增强的方法。例如:addUser、updateUser
3、PointCut:切入点,已经被增强的连接点JointPoint。增强已经生效。例如:addUser
切入点 是 连接点 一个子集。
4、Advice:增强/通知,用于增强的方法。例如:before() /after()
5、Intruduction 引介,特殊通知:类添加方法或字段等。(了解)
6、Weaving 织入:将通知(增强)应用目标类,生产代理过程。
7、Proxy:代理
8、Aspect 切面:将通知Adivce 和 切入点 PointCut 结合在一起。

这里写图片描述

入门Demo
这里写图片描述
1、UserService代码

public interface UserService {
    void addUser();

    void deleteUser();
}

2、UserServiceImpl代码

public class UserServiceImpl implements UserService{

    public void addUser() {
        // TODO Auto-generated method stub
        System.out.println("user add");

    }

    public void deleteUser() {
        // TODO Auto-generated method stub
        System.out.println("user delete");
    }

}

3、MyAspect代码

public class MyAspect implements MethodInterceptor {

    public Object invoke(MethodInvocation arg0) throws Throwable {
        // TODO Auto-generated method stub
        System.out.println("开启事务");
        //执行目标方法
        Object obj=arg0.proceed();
        System.out.println("关闭事务");
        return obj;
    }

}

4、beans.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">

    <!-- 1 目标类 -->
    <bean id="userServiceId" class="com.example.demo1.UserServiceImpl"></bean>  

    <!-- 2 确定通知 -->
    <bean id="myAspect" class="com.example.demo1.MyAspect"></bean>

    <!-- 3 编写aop,通过配置文件,将通知去增强目标类 
        * 如果要使用切入点表达式,必须导入apsjectj的jar: com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
    -->
    <aop:config>
        <!-- 3.1 声明切入点(确定对那些方法进行增强) -->
        <aop:pointcut expression="execution(* com.example.demo1.*.*(..))" id="myPointCut"/>
        <!-- 3.2声明切面:切入点 和 通知 结合
            * advisor :特殊的切面,只有一个切入点 和一个通知
            * aspect:就是切面,可以有多个切入点和多个通知 
        -->
        <aop:advisor advice-ref="myAspect" pointcut-ref="myPointCut"/>

    </aop:config>



</beans>

5、测试

    @Test
    public void testAop() {
        ///com/example/demo1/beans.xml
        String xmlPath = "com/example/demo1/beans.xml";
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
        UserService userService = (UserService) applicationContext
                .getBean("userServiceId",UserService.class);
        userService.addUser();
        userService.deleteUser();

    }

3、Aspect J

AspectJ是一个基于Java语言的AOP框架
@Aspect 是AspectJ1.5新增功能,通过JDK5注解技术,允许直接在Bean类中定义切面
新版本Spring框架,建议使用AspectJ方式来开发AOP

AspectJ规定6种通知类型:
before:前置通知,目标方法前执行。
afterReturning:后置通知,目标方法后执行。
around:环绕通知,目标方法前后执行。
afterThrowing:抛出通知,目标方法发生异常。
after:最终通知,无论什么情况都会执行。
declare-parents:引介

Aspectj演示demo(注解方式)
1、OrderService类

public interface OrderService {
   void addOrder();
   void updateOrder();
}

2、OrderService实现

@Service
public class OrderServiceImpl implements OrderService {

    public void addOrder() {
        // TODO Auto-generated method stub
        System.out.println("addOrder service");
    }

    public void updateOrder() {
        // TODO Auto-generated method stub
        System.out.println("updateOrder service");

    }

}

3、MyAspect代码

package com.example.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class MyAspect {

    @Before("execution(* com.example.aspect.*.*(..))")
    public void myBefore(JoinPoint joinPoint) {
        System.out.println("前置通知----" + joinPoint.getSignature().getName());
    }

    @AfterReturning(value = "execution(* com.example.aspect.*.*(..))", returning = "val")
    public void myAfterReturning(JoinPoint joinPoint, Object val) {
        System.out.println("后置通知" + val);
    }

    // 方法有要求:返回值Object,参数类型 ProceedingJoinPoint,抛出异常 Throwable
    @Around("execution(* com.example.aspect.*.*(..))")
    public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("环绕前------");

        // 执行目标类
        Object obj = joinPoint.proceed();

        System.out.println("环绕后------");

        return obj;
    }

    // @AfterThrowing(value="execution(* cn.itcast.d_aspectj.b_annotation.*.*(..))",
    // throwing="e")
    public void myAfterThrowing(JoinPoint joinPoint, Throwable e) {
        System.out.println("抛出异常通知" + e.getMessage());
    }

    @After("myPointCut()")
    public void myAfter() {
        System.out.println("最终");
    }

    // 共享表达式,添加到一个特殊的方法上,私有,没有返回值,方法名称自定义
    // * 使用时,在注解中,当成方法调用。例如:@After("myPointCut()")
    @Pointcut("execution(* com.example.aspect.*.*(..))")
    private void myPointCut() {

    }
}

4、beans.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"
       xmlns:context="http://www.springframework.org/schema/context"
       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
                           http://www.springframework.org/schema/context 
                           http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 1.注解类可以使用扫描 ,生成<bean>-->
    <context:component-scan base-package="com.example.aspect"></context:component-scan>
    <!-- 2.使AspectJ 自动代理 -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

5、测试用例

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:com/example/aspect/beans.xml")
public class AspectTest {

    @Autowired
    private OrderService orderService;

    @Test
    public void aspectTest1() {
        orderService.addOrder();
        orderService.updateOrder();
    }
}

运行结果
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值