AOP的简单练习
来源:互联网 发布:模拟考试软件下载 编辑:程序博客网 时间:2024/05/19 17:59
---恢复内容开始---
1、AOP的主要作用及概念简介
AOP最大的用处在于事务处理上,业务层在项目中主要负责以下的操作:
·调用数据层进行处理;
·进行事务的处理;
·关闭数据库的连接操作;
但在实际操作中,往往还要进行日志处理,事务提交等等辅助性操作,此时aop就派上用场。一个优秀的代理模式是将不同的切入点代码单独定义,而后组织在一个程序网上。AOP就在spring中充当了这样一个角色。
AOP有以下几个概念:
·切入点:可以理解为所有要操作的方法定义。要求业务层的方法必须统一风格。
·分离点:将那些不可再分的组件单独提取出去定义为单独的操作功能;
·横切关注点:将所有与开发无关的程序组成类单独提取而后组织运行;
·植入:将所有的切入点、关注点的代码组成在一张完整的程序结构中。
在Spring中采用通知的形式完成,即当触发到了某些操作之后自然地进行一些固定的操作。在整个SpringAOP中包含有以下几类通知形式:
·前置通知:在某一操作执行之前处理。
·后置通知:在某一操作执行之后处理,但后置通知有以下几种子通知:
|-后置返回通知:负责处理返回结果的时候进行拦截;
|-后置异常通知:当出现异常后进行拦截;
|-后置最终通知:执行到最后无论如何都会进行拦截;
·环绕通知:具有以上通知到特点。(功能最强大)
2、AOP的简单练习
(1) 简单地构建Spring环境
1⃣️、定义IMemberService.java:
1 package cn.ckw.IService;2 3 import cn.ckw.vo.Member;4 5 public interface IMemberService {6 boolean insert(Member vo);7 }
2⃣️、定义Membe.java
1 package cn.ckw.vo; 2 3 public class Member { 4 private String name; 5 private String id; 6 public String getName() { 7 return name; 8 } 9 public void setName(String name) {10 this.name = name;11 }12 public String getId() {13 return id;14 }15 public void setId(String id) {16 this.id = id;17 }18 @Override19 public String toString() {20 return "Member [name=" + name + ", ]";21 }22 23 }
3⃣️、定义MemberServiceImpl.java
1 package cn.ckw.serviceImpl; 2 3 import org.springframework.stereotype.Service; 4 5 import cn.ckw.IService.IMemberService; 6 import cn.ckw.vo.Member; 7 @Service 8 public class MemberServiceImpl implements IMemberService{ 9 @Override10 public boolean insert(Member vo) {11 //throw new NullPointerException("this is a exception");12 System.out.println("这是业务层的调用");13 return true;14 }15 16 }
以上模拟了业务实现,随后要加入的辅助性操作,都是通过Spring容器的配置完成。
首先要在application.xml.文件中加入annotation支持,加入时不要忘记检查命名空间是否已经被引入:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" 4 xmlns:context="http://www.springframework.org/schema/context" 6 xsi:schemaLocation="http://www.springframework.org/schema/beans 7 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 8 http://www.springframework.org/schema/context 9 http://www.springframework.org/schema/context/spring-context-2.5.xsd">12 <context:annotation-config />13 <context:component-scan base-package="cn.ckw" />25 </beans>
然后要在3⃣️中类名的上一行加入注解@service,接着建立测试类:
1 package cn.ckw.test; 2 3 import org.springframework.context.ApplicationContext; 4 import org.springframework.context.support.ClassPathXmlApplicationContext; 5 6 import cn.ckw.IService.IMemberService; 7 import cn.ckw.vo.Member; 8 9 public class Test {10 public static void main(String[] args) {11 ApplicationContext ctx = new ClassPathXmlApplicationContext(12 "applicationContext.xml");13 IMemberService ser=ctx.getBean("memberServiceImpl",IMemberService.class);14 Member vo=new Member();15 vo.setId("001");16 vo.setName("ckw");17 System.out.println(ser.insert(vo));18 }19 }
(2) 在(1)的基础上加入切面
4⃣️、定义切面方法类ServiceAspect.java:
1 package cn.ckw.aspect; 2 3 import org.springframework.stereotype.Component; 4 5 @Component 6 public class ServiceAspect { 7 public void serviceBefore(){ 8 System.out.println("在操作之前调用"); 9 }10 public void serviceBefore2(Object arg){11 System.out.println("在操作之前调用,传入的参数是:"+arg);12 }13 public void serviceAfterReturning(Object arg){14 System.out.println("在操作之后调用,返回值是:"+arg);15 }16 public void serviceAfter(){17 System.out.println("在操作之后调用");18 }19 }
之后要在application.xml中加入配置,黄色为引用的命名空间,红色部分为定义的切入点,表达式为AspectJ包所定义的表达式(可以深入时再去探索)。蓝色部分必须相同,表示切面函数关联到哪个切入点,可以是引用已经定义的pointcut(切入点),也可以重新定义新的切入点:
<?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:p="http://www.springframework.org/schema/p" 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-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd"> <context:annotation-config /> <context:component-scan base-package="cn.ckw" /> <aop:config> <!--首先定义程序的切入点--> <aop:pointcut expression="execution(* cn.ckw..*.*(..))" color: #3366ff">pointcut" /> <!--指定切入点的切入函数--> <aop:aspect ref="serviceAspect"> <aop:before method="serviceBefore" pointcut-ref="pointcut"/> <aop:after method="serviceAfter" pointcut="execution(* cn.ckw..*.*(..))" /> </aop:aspect> </aop:config> </beans>
(3) 加入可传参数的切面函数
在4⃣️类中加入以下方法的定义:
1 public void serviceBefore2(Object arg){2 System.out.println("在操作之前调用,传入的参数是:"+arg);3 }
在xml中定义此方法,红色标记点为与(2)比较的改变的地方:
<?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:p="http://www.springframework.org/schema/p" 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-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd"> <context:annotation-config /> <context:component-scan base-package="cn.ckw" /> <aop:config> <aop:pointcut expression="execution(* cn.ckw..*.*(..)) and args(vo)" /> <aop:aspect ref="serviceAspect"> <aop:before method="serviceBefore" pointcut-ref="pointcut" arg-names="vo" /> <aop:after method="serviceAfter" pointcut="execution(* cn.ckw..*.*(..))" /> </aop:aspect> </aop:config></beans>
(4)加入可返回的切面函数
在4⃣️类中加入以下方法的定义,其中arg为返回值:
public void serviceAfterReturning(Object arg){ System.out.println("在操作之后调用,返回值是:"+arg); }
在xml配置文件中的<aop:config>下添加,其中returning属性和arg-names属性只是起到标示作用,但两个要相同:
<aop:after-returning method="serviceAfterReturning" pointcut="execution(* cn.ckw..*.*(..))" returning="ret" arg-names="ret" />
(5)异常拦截处理
在业务层中抛一个异常出来,比如在3⃣️类中的insert函数中抛出一个异常:
1 public boolean insert(Member vo) {2 thrownew NullPointerException("throw exception");3 }
在类4⃣️中加入以下方法:
public void serviceAfterThrowing(Exception exp){ System.out.println(exp); }
在xml中写入如下配置:
<aop:after-throwing method="serviceAfterThrowing" pointcut="execution(* cn.ckw..*.*(..))" arg-names="abc" throwing="abc"/>
(6)环绕拦截
在4⃣️类中加入以下方法,环绕不仅可以拦截,甚至可以对传入参数和返回结果进行控制:
1 public Object serviceAround(ProceedingJoinPoint point) throws Throwable {2 System.out.println("方法调用之前,返回值是:"+Arrays.toString(point.getArgs()));3 Member vo=new Member();4 vo.setId("002");5 vo.setName("ckw2");6 Object retVal=point.proceed(new Object[]{vo});//执行业务代码7 System.out.println("在操作之后调用,返回值是--:"+retVal);8 return true;//真正的返回值9 }
同样的,要在xml中配置内容后,执行测试代码:
<aop:around method="serviceAround" pointcut="execution(* cn.ckw..*.*(..))"/>
学习AOP的读者,建议先将代理设计模式理解透彻。
(7)利用Annotation配置AOP
在xml之中加入AOP的annotation支持:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" 4 xmlns:context="http://www.springframework.org/schema/context" 5 xmlns:aop="http://www.springframework.org/schema/aop" 6 xsi:schemaLocation="http://www.springframework.org/schema/beans 7 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 8 http://www.springframework.org/schema/context 9 http://www.springframework.org/schema/context/spring-context-2.5.xsd 10 http://www.springframework.org/schema/aop 11 http://www.springframework.org/schema/aop/spring-aop-4.1.xsd">12 <context:annotation-config />13 <context:component-scan base-package="cn.ckw" />14 <!--<aop:config>15 <aop:pointcut expression="execution(* cn.ckw..*.*(..)) and args(vo)"16 />17 <aop:aspect ref="serviceAspect">18 <aop:before method="serviceBefore2" pointcut-ref="pointcut"19 arg-names="vo" />20 <aop:after method="serviceAfter" pointcut="execution(* cn.ckw..*.*(..))" />21 <aop:after-returning method="serviceAfterReturning"22 pointcut="execution(* cn.ckw..*.*(..))" returning="ret" arg-names="ret" /> 23 <aop:around method="serviceAround" pointcut="execution(* cn.ckw..*.*(..))"/>24 </aop:aspect>25 </aop:config>-->26 <aop:aspectj-autoproxy/>27 </beans>
修改ServiceAspect类:
1 package cn.ckw.aspect; 2 3 import java.util.Arrays; 4 5 import org.aspectj.lang.ProceedingJoinPoint; 6 import org.aspectj.lang.annotation.AfterReturning; 7 import org.aspectj.lang.annotation.Around; 8 import org.aspectj.lang.annotation.Aspect; 9 import org.aspectj.lang.annotation.Before;10 import org.springframework.stereotype.Component;11 12 import cn.ckw.vo.Member;13 14 @Component15 @Aspect16 public class ServiceAspect {17 @Before(value="execution(* cn.ckw..*.*(..))")18 public void serviceBefore(){19 System.out.println("在操作之前调用");20 }21 @Before(value="execution(* cn.ckw..*.*(..)) and args(vo)")22 public void serviceBefore2(Object arg){23 System.out.println("在操作之前调用,传入的参数是:"+arg);24 }25 @AfterReturning(value="execution(* cn.ckw..*.*(..))", argNames="ret" ,returning="ret")26 public void serviceAfterReturning(Object arg){27 System.out.println("在操作之后调用,返回值是:"+arg);28 }29 @Around(value="execution(* cn.ckw..*.*(..))")30 public Object serviceAround(ProceedingJoinPoint point) throws Throwable {31 System.out.println("方法调用之前,返回值是:"+Arrays.toString(point.getArgs()));32 Member vo=new Member();33 vo.setId("002");34 vo.setName("ckw2");35 Object retVal=point.proceed(new Object[]{vo});//执行业务代码36 System.out.println("在操作之后调用,返回值是--:"+retVal);37 return true;//真正的返回值38 }39 public void serviceAfter(){40 System.out.println("在操作之后调用");41 }42 }
-------转载请说明出处----------
---恢复内容结束---
- AOP的简单练习
- AOP的简单练习
- AOP的简单练习
- AOP的简单练习
- AOP的简单练习
- AOP的简单练习
- AOP的简单练习
- AOP的简单应用
- AOP的简单实现
- AOP的简单示例
- AOP的简单认识
- AOP 的简单入门
- AOP的简单应用
- 一个简单的AOP框架
- 一个简单的AOP原理
- 一个简单的Spring AOP
- 一个简单的AOP框架
- spring aop的简单实例
- [Azure]使用Azure Powershell输出ARM模式下某个账号中所有订阅下的虚拟网络拓扑
- qt学习之路九(QString、string和char*之间的转换)
- 回文素数
- 设计模式
- 比__autoload 更灵活的 spl_autoload_register 用法
- AOP的简单练习
- Android Butterknife Zelezny插件在Android Studio中的基本使用
- EasyPlayer实现直播抓拍
- Android的基本权限大全
- 前端技能联系:CSS sprites
- Meshlab简介
- 35个jQuery小技巧
- dataTable 发送数据使用springMVC接收自动封装失败的解决办法
- openstack-install-ubuntu-single说明