AOP编程简介及其在Spring框架中的使用
2016-06-19 02:20
477 查看
AOP编程简介及其在Spring框架中的使用
额,最近一直没来逛自己的博客发现游客蛮多的:),从前段时间开始就一直在学ssh框架(已经搞定strut2和hibernate),javaweb的框架还是蛮多的吧,现在的ssm好像比较流行,不过既然手头有本ssh的书再加上自己没学过框架的知识,所以就先从ssh入手了。那这两天呢学了aop面向切面编程,所以就没忘来自己博客写一篇。也算是巩固一下自己知识。aop编程:
AOP与OOP互为补充,面向对象编程(OOP)将程序分解成各个层次的对象;面向切面编程(AOP)则是将程序运行过程中分解成各个切面。可以说OOP是从静态角度考虑程序结构而AOP是从动态角度考虑的。
AOP并不与某个具体类耦合。具有两个特性:1.各步骤之间具有良好的隔离性2.源代码无关性。
AOP的一些术语:
1.切面(aspect):切面用于组织多个advice,advice在切面中定义。
2.连接点(joinpoint):程序执行过程中明确的点,在spring中,连接点总是方法的调用。
3.增强处理(advice):AOP框架在特定切入点执行增强处理。
4.切入点(pointcut):可以插入增强处理的连接点。
OK!接下来代码演示吧,实例永远比空洞的知识强。
本实例是使用基于注解的方式,另外还有基于xml的。
先把实例必须的两个javabean贴出
package Before; //定义一个hello接口 public interface Hello { //hello的两个方法 public void foo(); public int addUser(String name ,String pass); }
package Before; import org.springframework.stereotype.Component; //注解component指定此为id为hello的bean //实现接口并实现方法 @Component("hello") public class HelloImpl implements Hello { @Override public void foo() { System.out.println("执行hello主键的foo方法"); } @Override public int addUser(String name,String pass) { System.out.println("执行hello组键的adduser组键"+name); return 20; } }
一.定义before增强处理
定义一个切面,定义一个before增强处理:
package Before; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; //定义一个切面 @Aspect public class AuthAspect { //所有方法的执行作为切入点 //括号中的是切入点表达式,文章最后进行介绍 @Before("execution(* Before.*.*(..))") public void authority(){ System.out.println("模拟进行权限检查"); } }
以下是spring配置文件:
<!--beans.xml spring的配置文件 --> <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www c4d3 .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-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd"> <!-- 自动搜索Bean组件 自动搜索切面类 --> <context:component-scan base-package="Before"> <context:include-filter type="annotation" expression="org.aspectj.lang.annotation.Aspect"/> </context:component-scan> <!-- 启动@AspectJ支持 --> <aop:aspectj-autoproxy/> </beans>
ok,接下来我们来写一个测试类
package Before; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class AspectTest { public static void main(String[] args) { // 创建Spring容器 ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); Hello hello = ctx.getBean("hello" , Hello.class); hello.foo(); hello.addUser("孙悟空" , "7788"); } }
上面的所有步骤全部搞定,运行,结果如下
对比我们不进行AOP处理的结果:
结果很明显,这就是aop的作用,在不改动源代码的基础上,对源代码进行增强处理。
2.AfterReturning增强处理
AfterReturning有的属性值指定形参名,回限制目标方法必须有符合这两个形参。
不多说,贴代码
package AfterReturning; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Aspect; @Aspect public class LogAspect { @AfterReturning(returning="rvt", pointcut="execution(* Before.*.*(..)) && args(pass,name)") //声明rvt时指定的类型会限制目标方法必须有返回值或者没有返回值 public void log(Object rvt,String pass,String name){ System.out.println("第一个参数"+pass); System.out.println("第二个参数"+name); System.out.println("获取目标方法的返回值"+rvt); System.out.println("模拟记录日志功能。。。"); } }
结果(此结果加上before处理后的结果):
看出差别了吧。
Afterthrowing增强处理
package AfterThrowing; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Aspect; @Aspect public class RepairAspect { @AfterThrowing(throwing="ex",pointcut="execution(* Before.*.*(..))") public void doRecoveryActions11(Throwable ex){ System.out.println("目标方法抛出的异常"+ex); System.out.println("模拟advice对异常的修复...."); } }
该写一下前面的helloimpl类
package Before; import org.springframework.stereotype.Component; @Component("hello") public class HelloImpl implements Hello { @Override public void foo() { System.out.println("执行hello主键的foo方法"); } @Override public int addUser(String name,String pass) { System.out.println("执行hello组键的adduser组键"+name); if(name.length()<=3||name.length()>=10){ throw new IllegalArgumentException("name的参数必须大于3小于10"); } return 20; } }
在xml文件中加入切面类所在的包,结果如下
可以看出,增强处理起作用了。
时间问题,after增强处理就不讲了,很简单,跟before差不多,只不过一个在目标方法之前,一个在后。
Around增强处理
贴代码,两点多了,有点困了,
package Around; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; @Aspect public class TxAspect{ @Around("execution(* Before.*.*(..))") public Object processTx (ProceedingJoinPoint jp) throws Throwable{ System.out.println("执行目标方法之前,模拟开始事务....."); //获取目方法原始的调用参数 Object [] args=jp.getArgs(); if(args!=null&&args.length>1){ //修改目标方法调用参数的第一个参数 args[0] ="【增加的前缀】"+args[0]; } //以改变后的参数去执行目标方法,并保存目标方法返回的执行值 Object rvt=jp.proceed(args); System.out.println("模拟事务结束........"); if(rvt!=null&&rvt instanceof Integer){ rvt=(Integer)rvt*(Integer)rvt; } return rvt; } }
额,这个相对有点复杂,该类的方法processTx有个参数,就是代表目标方法,执行第一个输出之后,必须重新调用这个目标方法让他执行完再执第二个输出。
配置xml,后执行测试类
看到结果。和程序中描述的一样。
注: execution(* Before..(..)) && args(pass,name)
第一个*表示目标方法的返回值任意。
第二个 第三个表示 任意类的任意方法
&&后面的表示对连接点的参数类型进行限制,可以过滤目标方法。
ok ,这只能说是AOP的皮毛,真正的AOP可以是一本书啊,这只是AOP框架在spring中的利用。减少不必要的编码。写的不具体,但至少能懂吧。具体还需要进一步学习。晚安,am2:18。
____jeker_chen
相关文章推荐
- 手把手教你整合最优雅SSM框架:SpringMVC + Spring + MyBatis
- 开山篇
- JAVA、OC的内存管理机制的本质
- JAVA集合框架Collection
- [Java] 继承中,父类被覆盖的成员变量、方法的可访问性
- Java File类的介绍
- Java动态编程之javassist
- java 高并发
- java 设计模式 之 桥接
- 深度剖析JDK动态代理机制
- Spring Boot实现跨域访问实现代码
- eclipse配置汉字乱码
- eclipse配置PHP开发环境
- Java静态代理和jdk动态代理、Cglib动态代理
- java web session management
- Maven插件:maven-javadoc-plugin
- NIO(一):Java NIO概述
- Java中堆内存和栈内存详解
- Java垃圾回收机制
- java 成神之路 (一)