一、什么是AOP?
aop技术是面向切面编程思想,作为OOP的延续思想添加到企业开发中,用于弥补OOP开发过程中的缺陷而提出的编程思想。AOP底层也是面向对象;只不过面向的不是普通的Object对象,而是特殊的AOP对象。AOP的关注点是组成系统的非核心通用服务模块(比如登录检查等),相对于普通对象,aop不需要通过继承、方法调用的方式来提供功能,只需要在xml文件中以引用的方式,将非核心服务功能引用给需要改功能的核心业务逻辑对象或方法中。最终实现对象的解耦。spring 中ioc技术实现了核心业务逻辑对象之间的解耦(如LoginAction与DaoImpl),
aop技术实现的是核心业务逻辑对象与非核心通用服务之间的解耦(如LoginAction与LoginCheckInterceptor).
二、AOP相对于OOP有什么好处?
OOP,面对对象编程思想。OOP的问题不存在于开发阶段,在开发阶段和首次测试阶段中,使用OOP是效率最高也是最简单的一种方式。OOP问题体现在软件开发完毕之后的二次测试阶段,软件修改完毕之后,需要对软件中修改的方法进行重新测试,之后才可以上线运行。这时测试的对象是当前修改的方法 以及 和该方法具有级联/依赖关系的所有的其他方法。这样做显然了延长二次测试周期。
而使用aop在二次测试时,因为他是配置在xml文件中的,所以并不需要测试相关的所有类。
三、spring中如何使用aop?
我们使用一个例子来介绍下如何在spring中使用aop,
这里我们提供一个类StuAction,为这个类中的核心业务逻辑方法(addStu、delStu)添加登录检查的功能。
public class StuAction {
public String addStu(){
System.out.println("处理客户端提交的addStu.action请求");
//int i = 1/0;
return "success";
}
public String delStu(){
System.out.println("处理客户端提交的selStu.action请求");
return "success";
}
}
spring中的AOP技术提供了四种基本类型的通知:
- before通知 ~ 核心方法执行之前的通知 MethodBeforeAdvice
- after通知 ~ 核心方法执行之后的通知 AfterReturningAdvice
- around通知 ~ 核心方法执行时的通知before+after filter、interceptor都是一种around通知 MethodInterceptor
- throws通知 ~ 核心方法执行出现异常之后执行的通知 ThrowsAdvice
这四种通知我们都来测试下:
注意:在测试athrows通知时把StuAction中的int i = 1/0;
取消注释,我们创建一个异常来进行测试。
另外,after通知主要用来核心方法调用结束后输出日志,所以这里用到了log4j , 不明白的可以关注我的博客,下篇博客说下怎么使用log4j,这里不再赘述。
// 定义一个实现MethodBeforeAdvice的通知类 - before通知
public class LoginCheckAdvice implements MethodBeforeAdvice {
// 该方法会在核心方法执行之前自动执行
@Override
public void before(Method arg0, Object[] arg1, Object arg2)
throws Throwable {
System.out.println("判断当前是否存在登录用户");
// 根据判断的结果决定是否执行后续的核心方法
}
}
// after通知
public class LoggerAdvice implements AfterReturningAdvice{
private static Logger logger =
Logger.getLogger(LoggerAdvice.class);
// 该方法会在核心方法执行完毕之后自动执行
@Override
public void afterReturning(Object arg0, Method arg1, Object[] arg2,
Object arg3) throws Throwable {
// TODO Auto-generated method stub
System.out.println("核心方法执行完毕之后进行日志记录");
// 记录一条日志信息
logger.error("这是一条error级别的日志信息");
logger.warn("这是一条warn级别的日志信息");
logger.info("这是一条info级别的日志信息");
logger.debug("这是一条debug级别的日志信息");
}
}
// around通知
public class AroundAdvice implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
//struts2 interceptor ActionInvocation调度者
System.out.println("around通知-核心方法执行之前");
Object result = invocation.proceed();
// 将请求的执行权限转交给核心业务逻辑方法 addStu/selStu
// result - 核心方法的执行结果 addStu()/selStu()
System.out.println("result--"+result); // success
System.out.println("around通知-核心方法执行之后");
return result;
}
}
// throws通知
public class ExceptionAdvice implements ThrowsAdvice {
//该方法会在核心方法执行出现异常之后自动执行
public void afterThrowing(Method method, Object[] args,
Object target, Exception ex){
System.out.println("核心方法执行出现异常了...异常信息"+ex.getMessage());
}
}
log4j.properties
log4j.rootLogger=info,etoak1,etoak2
log4j.appender.etoak1=org.apache.log4j.ConsoleAppender
log4j.appender.etoak1.layout=org.apache.log4j.TTCCLayout
log4j.appender.etoak2=org.apache.log4j.FileAppender
log4j.appender.etoak2.file=C://log4j.html
log4j.appender.etoak2.layout=org.apache.log4j.HTMLLayout
好了,准备工作完毕,那我们如何在spring容器中配置aop呢?
重点的来了!
在applicationContext.xml中配置aop:
首先导入spring 中aop下所有包,log4j 包
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
<!--
引入aop命名空间、schame文件
需求 : 使用spring提供的AOP技术为
添加登录检查的辅助功能
1 将登录检查的功能封装成一种spring中的AOP组件
AOP组件[struts2拦截器 filter过滤器 spring通知]
2 将通知类、核心业务逻辑对象[具有依赖关系的两个对象]
配置在ioc容器中
-->
<bean id="action" class="com.etoak.action.StuAction"/>
<bean id="lc" class="com.etoak.util.LoginCheckAdvice"/>
<bean id="logger" class="com.etoak.util.LoggerAdvice"/>
<bean id="around" class="com.etoak.util.AroundAdvice"/>
<bean id="exce" class="com.etoak.util.ExceptionAdvice"></bean>
<!--
3 使用AOP方式将通知类引用给业务逻辑对象
aop:config : 配置一个aop组件[通知类的使用方式]
3.1 描述需要将这个通知类提供的功能引用给谁
aop:pointcut 配置切入点
切入点 : 用于描述通知执行的地点[在哪执行]
地址 : 在哪个/哪些方法周围执行
切入点指向的是需要添加登录检查功能的一组方法
expression属性(表达式):通知执行一个表达式,将表达式的执行结果作为切入点
表达式的执行结果指向的也是一组方法
execution(* com.etoak.action.*.*(..))
execution(1 2) 执行()中表达式的内容
1 用于限定方法的返回值 *
2 用于限定方法的位置、名字
com.etoak.action.*.*(..)
3.2 组装通知类+切入点 形成一个AOP组件[切面]
-->
<aop:config>
<aop:pointcut expression="execution(* com.etoak.action.Stu*.add*(..)) || execution(* com.etoak.action.*.del*(..))" id="pc"/>
<aop:advisor advice-ref="lc" pointcut-ref="pc"/><!-- 将id="lc"这个通知类提供的功能引用给 id="pc"这个切入点指向的那组方法. -->
<aop:advisor advice-ref="logger" pointcut-ref="pc"/>
<aop:advisor advice-ref="around" pointcut-ref="pc"/>
<aop:advisor advice-ref="exce" pointcut-ref="pc"/>
</aop:config>
</beans>
使用test类测试一下:
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
StuAction la = (StuAction)ac.getBean("action");
la.addStu();
la.delStu();
}
}
结果如下:
相信这个显示已经很直白了吧?
aop的使用就这么简单!
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-15 05:33:53