Spring AOP 是 Spring 框架的核心模块之一,它使用纯 Java 实现,因此不需要专门的编译过程和类加载器,可以在程序运行期通过代理方式向目标类织入增强代码。
Spring AOP 的代理机制
Spring 在运行期会为目标对象生成一个动态代理对象,并在代理对象中实现对目标对象的增强。
Spring AOP 的底层是通过以下 2 种动态代理机制,为目标对象(Target Bean)执行横向织入的。
Spring AOP 连接点
Spring AOP 并没有像其他 AOP 框架(例如 AspectJ)一样提供了完成的 AOP 功能,它是 Spring 提供的一种简化版的 AOP 组件。其中最明显的简化就是,Spring AOP 只支持一种连接点类型:方法调用。您可能会认为这是一个严重的限制,但实际上 Spring AOP 这样设计的原因是为了让 Spring 更易于访问。
方法调用连接点是迄今为止最有用的连接点,通过它可以实现日常编程中绝大多数与 AOP 相关的有用的功能。如果需要使用其他类型的连接点(例如成员变量连接点),我们可以将 Spring AOP 与其他的 AOP 实现一起使用,最常见的组合就是 Spring AOP + ApectJ。
Spring AOP 通知类型
AOP 联盟为通知(Advice)定义了一个 org.aopalliance.aop.Interface.Advice 接口。
Spring AOP 通知类型
AOP 联盟为通知(Advice)定义了一个 org.aopalliance.aop.Interface.Advice 接口。
一般切面的 AOP 开发
当我们在使用 Spring AOP 开发时,若没有对切面进行具体定义,Spring AOP 会通过 Advisor 为我们定义一个一般切面(不带切点的切面),然后对目标对象(Target)中的所有方法连接点进行拦截,并织入增强代码。
AOP基于XML配置的入门案例:
首先是导入架包和创建所需要的包
接下来创建service类,这个类完成核心功能操作
service类需要接口与实现类
先写接口:
public interface BookService {
void findAll();
void save(int a);
int del();
void update();
}
然后是它的实现类:
public class BookServiceImpl implements BookService {
@Override
public void findAll(){
System.out.println("查询所有");
}
@Override
public void save(int a) {
System.out.println("保存信息"+a);
}
@Override
public int del(){
System.out.println("删除信息");
return 5;
}
@Override
public void update(){
System.out.println("修改信息");
}
}
service包中的代码我们现在假定其为不可更改的核心代码,接下来做的是在不更改核心代码的情况下对核心代码进行增强:
接下来是logger包下的类,在开发中主要用于AOP的增强
public class Logger {
public void check(){ System.out.println("前置通知/增强:权限设置");}
public void logPrint(){ System.out.println("后置通知/增强:日志输出");}
public void exception(){ System.out.println("异常通知/增强:异常处理");}
public void distroy(){ System.out.println("最终通知/增强:资源释放");}
}
接下来在src包中创建spring.xml,在里面配置加载
<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">
<!-- 1.把所有类的对象交给IOC容器进行管理 -->
<bean id="logger" class="com.zhang.logger.Logger"/>
<bean id="bookService" class="com.zhang.service.impl.BookServiceImpl"/>
<!-- 2.AOP的配置:让增强类 的 哪个方法 动态进行何种增强 核心类 的 哪个方法 -->
<aop:config>
<!--2.AOP的配置:让增强类的那个方法 动态进行何种增强 核心类 的 那个方法-->
<aop:aspect id="check" ref="logger">
<aop:before method="check" pointcut="execution(* *..BookServiceImpl.*(..))"/>
<aop:after-returning method="logPrint" pointcut="execution(* *..BookServiceImpl.*(..))"/>
<aop:after-throwing method="exception" pointcut="execution(* *..BookServiceImpl.*(..))"/>
<aop:after method="distroy" pointcut="execution(* *..BookServiceImpl.*(..))"/>
</aop:aspect>
</aop:config>
</beans>
所有的配置都完成的情况下,我们可以在servlet包中进行测试
public class Test01 {
public static void main(String[] args) {
//先加载spring配置文件,通过容器获取对象
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
BookService bean = context.getBean(BookService.class);
bean.findAll();
bean.save(6);
bean.del();
bean.update();
}
}