- Spring中对于代理设计模式的实现使用的是AOP(面向切面编程)
- 一般业务层操作主要有几点
- 进行操作日志记录
- 进行数据层的具体操作
- 如果是更新处理,则需要进行事务的控制(提交或者回滚)
- 进行数据库的关闭,如果出现有错误则进行日志的记录
- AOP的作用是实现对所有的切入点可利用一个表达式直接通过配置文件准确的切入到要处理的业务层上
所有切入点有几种模式:
- 前置通知(Before Advice):在业务方法执行之前调用
- 后置通知(After Advice):在业务方法调用完成后执行,
- 后置返回通知(After Returning Advice):业务操作执行完毕返回执行结果
- 后置异常通知(After Throwing Advice):业务产生异常之后的通知处理
- 后置最终通知(After Finally Advice):不管是否出问题都要执行,类似于finlly异常处理
- 环绕通知(Round Advice):可以由用户在一个切入点上进行之前or之后的处理控制(传统动态代理)
AOP基础配置
- AOP这项技术主要用在业务层的控制上
- 对于AOP的处理操作更多的事以配置文件形式的方式出现
1、定义业务层接口和子类
package cn.liang.service;
public interface IMessageService {
public boolean remove(String mid) ;
}
package cn.liang.service.impl;
import org.apache.log4j.Logger;
import cn.liang.service.IMessageService;
public class MessageServiceImpl implements IMessageService {
@Override
public boolean remove(String mid) {
Logger.getLogger(IMessageService.class).info("【业务层】执行删除调用,删除的数据ID = " + mid);
return false;
}
}
2、定义一个描述AOP程序处理的结构类
package cn.liang.service.proxy;
import org.apache.log4j.Logger;
public class ServiceProxy {
public void beforeInvoke() {
Logger.getLogger(ServiceProxy.class).info("【ServiceProxy - BEFORE】在业务方法执行之前进行调用。");
}
public void afterInvoke() {
Logger.getLogger(ServiceProxy.class).info("【ServiceProxy - AFTER】在业务方法执行之后进行调用。");
}
}
3、配置applicationContext.xml文件
配置AOP所使用的命名空间信息
xmlns:aop="http://www.springframework.org/schema/aop
xsi:schemaLocation="http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd"
编写ServiceProxy程序类的执行方法映射到业务层方法上
<bean id="messageServiceImpl" class="cn.liang.service.impl.MessageServiceImpl"/>
<bean id="serviceProxy" class="cn.liang.service.proxy.ServiceProxy"/>
<aop:config> <!-- 针对于AOP的处理进行相应配置 -->
<!-- 定义业务操作的切入点 -->
<aop:pointcut expression="execution(* cn.liang.service..*.*(..))" id="defaultPointCut"/>
<!-- 定义好切入点之后实际上就表示已经可以将具体的方法操作定位到某些业务层的方法上了,那么随后还需要对其进行方法的调用配置 -->
<aop:aspect ref="serviceProxy">
<aop:before method="beforeInvoke" pointcut-ref="defaultPointCut"/>
<aop:after method="afterInvoke" pointcut-ref="defaultPointCut"/>
</aop:aspect>
</aop:config>
- Spring的AOP使用了AspectJ的表达式语法
- 语法结构"execution(* cn.liang.service...(..))"组成如下:
- execution():定义需要执行操作的切入点语法
- 主要组成:execution(修饰符匹配? 返回值类型匹配 操作类型匹配? 名称匹配(参数匹配) 抛出异常匹配)
- 本次处理没有涉及到操作符的匹配,基本设置就是public或private
- *:描述该方法的返回值,"*"表示任意的数据类型
- cn.liang.service..:描述的是要进行切入点匹配的包名称
- cn.liang.test.aop.service.back.open:可以表示为cn.liang..service..
- *.*:描述类中所有的方法,格式为:"类.方法"
- (..):描述参数
4、编写测试代码
package cn.liang.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import cn.liang.service.IMessageService;
public class TestAOP {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
IMessageService msgService = ctx.getBean("messageServiceImpl", IMessageService.class);
System.out.println(msgService.remove("101"));
}
}
5、输出结果
2018-12-05 16:25:34,183 INFO [cn.liang.service.proxy.ServiceProxy] - 【ServiceProxy - BEFORE】在业务方法执行之前进行调用。
2018-12-05 16:25:34,184 INFO [cn.liang.service.IMessageService] - 【业务层】执行删除调用,删除的数据ID = 101
2018-12-05 16:25:34,184 INFO [cn.liang.service.proxy.ServiceProxy] - 【ServiceProxy - AFTER】在业务方法执行之后进行调用。
false