NO.11 Spring AOP

本文介绍了Spring AOP的概念、术语及应用场景,并提供了详细的配置实例,帮助读者掌握如何利用Spring AOP进行开发。

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

NO.11 Spring AOP

一:概念理解

Spring AOP(Aspect Oriented Program)面向切面,集成了aspectj这个工具, 措施是采用横向抽取的机制取代了传统向继承体系的重复代码使用,比如说想要开发一些其他的功能,如性能监控、事务的管理、日志或权限的管理等,都可以用AOP。上节所述的代理机制也是AOP的一个思想,是采用手动的方式/最基本的方式使用AOP的思想。

二:使用例子

把业务bean放到service层去处理,现在想要通过AOP对service进行编程,编程之后,希望能够代理业务bean进行日志打印等操作。

1)性能监控
2)事务管理 操作数据库,采用mvc分层,数据库操作在dao层,实际的业务处理在service层,应该在service层处理事务机制,那么,在service层如何让处理事务机制呢?在spring中就是采用aop的思想。
3)安全检查 也就是所谓的权限。
可将这些代码单独的抽离出去,不跟实际业务发生在一起,就是让代码与实际业务隔离,降低程序的耦合性。
4)缓存优化
5)记录日志

三: AOP的术语

(1)连接点:(JoinPoint):指的是那些被拦截到的点(在Spring AOP中也就是方法)。假如说有一条业务线正在执行,通过控制层到达服务层再到Dao层,到服务层时会调用服务层里的一个方法,在执行service方法时被aop拦截代理,代理之后,由AOP代理执行,这个方法就称为一个连接点,也就是aop与这条业务线有了一个连接。AOP在代理方法时通过这个业务的执行,spring aop最低拦截/执行级别就是方法,不能再深入到某一行的代码,最小单元就是方法。方法执行时,可以进行代理,假如说是存钱操作,代理之后,由AOP代理执行,在连接点处打印日志。假如又有第二个业务支付,同样有一个连接点。只要AOP拦截了service中的某个方法,这个方法就称为连接点。
(2)切面:如果service中有很多连接点的话,由这些连接点组成的面叫做切面。
(3)切入点:指哪些被拦截到的点的定义,匹配连接点的断言。 AOP会处理几个功能,如记录日志、权限管理等,如果没有权限执行存钱操作,那么需要进行拦截,这样的由多个功能作用于一个方法,每个功能叫做一个切入点。
(4)通知: 拦截到连接点后,所要做的事情就是通知 (1、前置通知 2、后置通知 3、异常通知 4、环绕通知<前置通知和后置通知结合在一起>)。 用AOP做方法的一个代理,当已经控制或代理方法之后,这个方法要执行,如果AOP是打印日志的,一次日志的打印,就是一次通知。或者做权限的控制,有权限检查了一次使之通过,没有权限不通过,又进行了一次通知。对连接点所做的作用/告知,就是所谓的通知。
(5)目标对象:被一个或者多个切面所通知的对象,也被称作被通知对象。
(6)代理对象:AOP框架创建的对象,它和目标对象遵循同样的接口,使用它的方式和使用目标对象的方式是一样的,但是它是目标对象的增强版,“通知”中的代码执行将会被代理对象的方法调用触发。在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。

四:在Spring中进行AOP的开发

Spring 本身没有AOP的组件,需要将 aspectJ安装到Spring 平台上。
基于XML的配置Spring AOP开发
Spring AOP相关Jar包:
spring-aop-4.3.3.RELEASE.jar
aspectjweaver-1.8.5.jar
aspectjrt-1.8.5.jar
pom文件中需要添加

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>4.3.10.RELEASE</version>
    </dependency>
    <dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>1.8.5</version>
    </dependency>
    <dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.8.5</version>
    </dependency>

想要在配置文件中进行AOP的开发,首先定义一个spring的配置文件applicationContext-aop-xml.xml,同样需要引入aop的命名空间。

需要怎样的操作去替换上节写的手工代理类?
两种配置方法:
1>采用xml配置开发spring组件
2>采用注解的方式

Spring AOP开发步骤:
(1)将业务bean初始化到ioc容器中
将bean——StuCardServiceImpl配置到xml当中去
(2)配置通知类
(3)AOP配置
1>配置切点
属性expression:表达式 类似模糊查询
可通过表达式代替方法中的参数(..)表示方法中的任意参数。
2>配置aspect 通过属性ref指定通知类
前置通知,通知方法method,当运行pointcut-ref时触发。

<?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:context="http://www.springframework.org/schema/context"
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/context
               http://www.springframework.org/schema/context/spring-context.xsd 
               http://www.springframework.org/schema/aop
               http://www.springframework.org/schema/aop/spring-aop.xsd">

        <bean id="stuCardService" class="com.xt.spring.aop.xml.StuCardServiceImpl"></bean> 

        <!-- 配置通知类 -->
        <bean id="loggerAspect" class="com.xt.spring.aop.xml.LoggerAspect"></bean>

        <aop:config>
            <!-- 拦截类里的一个方法 -->
            <aop:pointcut expression="execution(void com.xt.spring.aop.xml.StuCardServiceImpl.deposit(..))" id="stuCardDeposit"/>
            <aop:aspect ref="loggerAspect">
                <aop:before method="beforeMethodAdvice" pointcut-ref="stuCardDeposit"/>
            </aop:aspect>
        </aop:config>
</beans>

如果想要拦截所有方法,可将execution(void com.xt.spring.aop.xml.StuCardServiceImpl.deposit(..))中的deposit改为“*”。
StuService类

package com.xt.spring.aop.xml;

public interface StuCardService {
    public void deposit(String cardNo,String i);
    public void payMoney(String cardNo,String money);
}

StuService实现类

package com.xt.spring.aop.xml;

public class StuCardServiceImpl implements StuCardService{

    public void deposit(String cardNo, String money) {
        System.out.println("向学生卡" + cardNo + "存钱:" + money);
    }
    public void payMoney(String cardNo, String money) {
        System.out.println("使用学生卡" + cardNo + "支付:" + money);
    }
}

通知类

package com.xt.spring.aop.xml;

import org.aspectj.lang.JoinPoint;

public class LoggerAspect {

    //自定义前置通知
    public void beforeMethodAdvice(JoinPoint jp){
        System.out.println("方法:"+ jp.getSignature().getName() + "被执行,前置通知被触发.......");
    }
    public void afterMethodAdvice(JoinPoint jp){
        System.out.println("方法:"+ jp.getSignature().getName() + "被执行,后置通知被触发.......");
    }
}

测试类

package com.xt.spring.aop.xml;

import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AOPTest {

    private ApplicationContext ioc;

    @Before
    public void iocInit(){
        ioc = new ClassPathXmlApplicationContext("applicationContext-aop-xml.xml");
    }
    @Test
    public void test(){
        StuCardService scs = ioc.getBean("stuCardService",StuCardService.class);  
        scs.deposit("4512324", "500");
        scs.payMoney("4512324", "500");
    }
}

通过配置产生关系,降低耦合度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值