Spring中的AOP 面向切面编程
一,什么是AOP
AOP(Aspect Oriented Programming)面向切面编程,是Spring框架中的内容,它是针对于一个事件的某个步骤或阶段,主要应用于:日志,事务处理,异常处理等方面,它的原理是:通过过滤,对指定的一些操作直接添加设定好的方法,不需要频繁的调用,在不使用接口的情况下实现java的动态代理。
AOP技术利用一种称为“横切”的技术,剖解开封装对象的内部,将影响多个类的公共行为封装到一个可重用的模块中,并将其命名为Aspect切面。所谓的切面,简单来说就是与业务无关,却为业务模块所共同调用的逻辑,将其封装起来便于减少系统的重复代码,降低模块的耦合度,有利用未来的可操作性和可维护性。
利用AOP可以对业务逻辑各个部分进行隔离,从而使业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高开发效率。
Spring AOP 模块提供拦截器来拦截一个应用程序,例如,当执行一个方法时,你可以在方法执行之前或之后添加额外的功能。
二 AOP术语
三 通知的类型
Spring 方面可以使用下面提到的五种通知:
四 Spring 中基于AOP的XML架构
以银行系统的存款和转账流程来说,其中都存在相同的验证流程,AOP思想则是将这些相同的流程抽离出来,以存钱/转账方法为切入点,分别在此切入点之前或之后建立配置。
代码展示:
为了在本节的描述中使用 aop 命名空间标签,你需要导入 spring-aop 架构,如下所述:
<?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
</beans> ">
首先创建存款和转账的接口
package cn.tb.dao;
public interface BankDao {
//存钱
public void saveMoney();
//转账
public void remirt();
}
然后设置相关流程
验证事务
package cn.tb.impl;
public class AdminCheck {
public void check(){
System.out.println("权限验证开始");
}
}
处理和提交事务
package cn.tb.impl;
import org.aspectj.lang.ProceedingJoinPoint;
public class TransactionManager {
public void beginTransaction(){
System.out.println("开始事务处理");
}
public void commitTrnasaction(){
System.out.println("提交事务处理");
}
public void doInceptor(ProceedingJoinPoint point) throws Throwable{
beginTransaction();
point.proceed();
commitTrnasaction();
}
}
执行相关操作
package cn.tb.impl;
import cn.tb.dao.BankDao;
public class BankDaoImpl implements BankDao{
@Override
public void saveMoney() {
System.out.println("正在存钱");
}
@Override
public void remirt() {
System.out.println("正在转账");
}
}
日志写入
package cn.tb.impl;
public class LogManager {
//日志
public void writeLog(){
System.out.println("日志正在写入");
}
}
最后配置完整的Spring 中基于AOP的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
">
<!--注入bean-->
<bean class="cn.tb.impl.AdminCheck" id="adminCheck"></bean>
<bean class="cn.tb.impl.BankDaoImpl" id="bankDao"></bean>
<bean class="cn.tb.impl.LogManager" id="logManager"></bean>
<bean class="cn.tb.impl.TransactionManager" id="transactionManager"></bean>
<!--开始spring aop 面向切面配置-->
<aop:config>
<!--切入点 什么时机,什么时候切入-->
<aop:pointcut id="serviceInceptor" expression="execution(* cn.tb.impl.*.*(..))"></aop:pointcut>
<!--前置通知 在一个方法执行之前,执行通知。-->
<aop:aspect ref="adminCheck">
<aop:before method="check" pointcut-ref="serviceInceptor"></aop:before>
</aop:aspect>
<!--环绕通知 在建议方法调用之前和之后,执行通知。-->
<aop:aspect ref="transactionManager">
<aop:around method="doInceptor" pointcut-ref="serviceInceptor"></aop:around>
</aop:aspect>
<!--后置通知 在一个方法执行之后,不考虑其结果,执行通知。-->
<aop:aspect ref="logManager">
<aop:after method="writeLog" pointcut-ref="serviceInceptor"></aop:after>
</aop:aspect>
</aop:config>
</beans>
测试
package cn.tb.test;
import cn.tb.dao.BankDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
test1();
System.out.println("-------------");
test2();
}
//存钱
private static void test1() {
ApplicationContext alc = new ClassPathXmlApplicationContext("Spring.xml");
BankDao dao = alc.getBean("bankDao", BankDao.class);
dao.saveMoney();
}
//转账
private static void test2() {
ApplicationContext alc = new ClassPathXmlApplicationContext("Spring.xml");
BankDao dao = alc.getBean("bankDao", BankDao.class);
dao.remirt();
}
}
测试结果: