---恢复内容开始---

1、AOP的主要作用及概念简介

  AOP最大的用处在于事务处理上,业务层在项目中主要负责以下的操作:

    ·调用数据层进行处理;

    ·进行事务的处理;

    ·关闭数据库的连接操作;

  但在实际操作中,往往还要进行日志处理,事务提交等等辅助性操作,此时aop就派上用场。一个优秀的代理模式是将不同的切入点代码单独定义,而后组织在一个程序网上。AOP就在spring中充当了这样一个角色。

  AOP有以下几个概念:

    ·切入点:可以理解为所有要操作的方法定义。要求业务层的方法必须统一风格。

    ·分离点:将那些不可再分的组件单独提取出去定义为单独的操作功能;

    ·横切关注点:将所有与开发无关的程序组成类单独提取而后组织运行;

    ·植入:将所有的切入点、关注点的代码组成在一张完整的程序结构中。

  在Spring中采用通知的形式完成,即当触发到了某些操作之后自然地进行一些固定的操作。在整个SpringAOP中包含有以下几类通知形式:

    ·前置通知:在某一操作执行之前处理。

    ·后置通知:在某一操作执行之后处理,但后置通知有以下几种子通知:

      |-后置返回通知:负责处理返回结果的时候进行拦截;

      |-后置异常通知:当出现异常后进行拦截;

      |-后置最终通知:执行到最后无论如何都会进行拦截;

    ·环绕通知:具有以上通知到特点。(功能最强大)

2、AOP的简单练习

  (1) 简单地构建Spring环境

    1⃣️、定义IMemberService.java:

 package cn.ckw.IService;

 import cn.ckw.vo.Member;

 public interface IMemberService {
boolean insert(Member vo);
}

IMemberService.java

    2⃣️、定义Membe.java

 package cn.ckw.vo;

 public class Member {
private String name;
private String id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Override
public String toString() {
return "Member [name=" + name + ", id=" + id + "]";
} }

Member

    3⃣️、定义MemberServiceImpl.java

 package cn.ckw.serviceImpl;

 import org.springframework.stereotype.Service;

 import cn.ckw.IService.IMemberService;
import cn.ckw.vo.Member;
@Service
public class MemberServiceImpl implements IMemberService{
@Override
public boolean insert(Member vo) {
//throw new NullPointerException("this is a exception");
System.out.println("这是业务层的调用");
return true;
} }

MemberServiceImpl

    以上模拟了业务实现,随后要加入的辅助性操作,都是通过Spring容器的配置完成。

    首先要在application.xml.文件中加入annotation支持,加入时不要忘记检查命名空间是否已经被引入:

 <?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"
4 xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
8 http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
12 <context:annotation-config />
13 <context:component-scan base-package="cn.ckw" />
</beans>

    然后要在3⃣️中类名的上一行加入注解@service,接着建立测试类:

 package cn.ckw.test;

 import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import cn.ckw.IService.IMemberService;
import cn.ckw.vo.Member; public class Test {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext(
"applicationContext.xml");
IMemberService ser=ctx.getBean("memberServiceImpl",IMemberService.class);
Member vo=new Member();
vo.setId("001");
vo.setName("ckw");
System.out.println(ser.insert(vo));
}
}

Test

   (2) 在(1)的基础上加入切面

    4⃣️、定义切面方法类ServiceAspect.java:

 package cn.ckw.aspect;

 import org.springframework.stereotype.Component;

 @Component
public class ServiceAspect {
public void serviceBefore(){
System.out.println("在操作之前调用");
}
public void serviceBefore2(Object arg){
System.out.println("在操作之前调用,传入的参数是:"+arg);
}
public void serviceAfterReturning(Object arg){
System.out.println("在操作之后调用,返回值是:"+arg);
}
public void serviceAfter(){
System.out.println("在操作之后调用");
}
}

ServiceAspect.java

    之后要在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..*.*(..))"
id="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⃣️类中加入以下方法的定义:

public void serviceBefore2(Object arg){ System.out.println("在操作之前调用,传入的参数是:"+arg); }

    在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)"
id="pointcut" />
<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函数中抛出一个异常:

public boolean insert(Member vo) { throw new NullPointerException("throw exception"); }

    在类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⃣️类中加入以下方法,环绕不仅可以拦截,甚至可以对传入参数和返回结果进行控制:

     public Object serviceAround(ProceedingJoinPoint point) throws Throwable {
System.out.println("方法调用之前,返回值是:"+Arrays.toString(point.getArgs()));
Member vo=new Member();
vo.setId("002");
vo.setName("ckw2");
Object retVal=point.proceed(new Object[]{vo});//执行业务代码
System.out.println("在操作之后调用,返回值是--:"+retVal);
return true;//真正的返回值
}

    同样的,要在xml中配置内容后,执行测试代码:

<aop:around method="serviceAround" pointcut="execution(* cn.ckw..*.*(..))"/>

  学习AOP的读者,建议先将代理设计模式理解透彻。

  (7)利用Annotation配置AOP

    在xml之中加入AOP的annotation支持:

 <?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)"
id="pointcut" />
<aop:aspect ref="serviceAspect">
<aop:before method="serviceBefore2" pointcut-ref="pointcut"
arg-names="vo" />
<aop:after method="serviceAfter" pointcut="execution(* cn.ckw..*.*(..))" />
<aop:after-returning method="serviceAfterReturning"
pointcut="execution(* cn.ckw..*.*(..))" returning="ret" arg-names="ret" />
<aop:around method="serviceAround" pointcut="execution(* cn.ckw..*.*(..))"/>
</aop:aspect>
</aop:config>-->
<aop:aspectj-autoproxy/>
</beans>

    修改ServiceAspect类:

 package cn.ckw.aspect;

 import java.util.Arrays;

 import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component; import cn.ckw.vo.Member; @Component
@Aspect
public class ServiceAspect {
@Before(value="execution(* cn.ckw..*.*(..))")
public void serviceBefore(){
System.out.println("在操作之前调用");
}
@Before(value="execution(* cn.ckw..*.*(..)) and args(vo)")
public void serviceBefore2(Object arg){
System.out.println("在操作之前调用,传入的参数是:"+arg);
}
@AfterReturning(value="execution(* cn.ckw..*.*(..))", argNames="ret" ,returning="ret")
public void serviceAfterReturning(Object arg){
System.out.println("在操作之后调用,返回值是:"+arg);
}
@Around(value="execution(* cn.ckw..*.*(..))")
public Object serviceAround(ProceedingJoinPoint point) throws Throwable {
System.out.println("方法调用之前,返回值是:"+Arrays.toString(point.getArgs()));
Member vo=new Member();
vo.setId("002");
vo.setName("ckw2");
Object retVal=point.proceed(new Object[]{vo});//执行业务代码
System.out.println("在操作之后调用,返回值是--:"+retVal);
return true;//真正的返回值
}
public void serviceAfter(){
System.out.println("在操作之后调用");
}
}

-------转载请说明出处----------

---恢复内容结束---

AOP的简单练习的更多相关文章

  1. 云笔记项目-AOP知识简单学习

    在云笔记项目的过程中,需要检查各个业务层的执行快慢,如登录.注册.展示笔记本列表,展示笔记列表等,如果在每个业务层方法里都写一段代码用来检查时间并打印,不仅仅显得代码重复,而且当项目很大的时候,将大大 ...

  2. Spring Boot 2.X(八):Spring AOP 实现简单的日志切面

    AOP 1.什么是 AOP ? AOP 的全称为 Aspect Oriented Programming,译为面向切面编程,是通过预编译方式和运行期动态代理实现核心业务逻辑之外的横切行为的统一维护的一 ...

  3. c# spring aop的简单例子

    刚刚完成了一个c#的spring aop简单例子,是在mac下用Xamarin Studio开发的.代码如下: 接口 using System; using System.Collections.Ge ...

  4. java代理课程测试 spring AOP代理简单测试

    jjava加强课程测试代码 反射. 代理 .泛型.beanUtils等 项目源码下载:http://download.csdn.net/detail/liangrui1988/6568169 热身运动 ...

  5. Spring 学习笔记(六)—— AOP的简单理解

    系统中的业务可以分为核心关注点和横切关注点. 核心关注点时业务处理的主要流程,而横切关注点是与核心业务无关但更为通用的业务. 各个横切关注点离散地穿插于核心业务之中,导致系统地每一个模块都与这些业务具 ...

  6. Spring AOP配置简单记录(注解及xml配置方式)

    在了解spring aop中的关键字(如:连接点(JoinPoint).切入点(PointCut).切面(Aspact).织入(Weaving).通知(Advice).目标(Target)等)后进行了 ...

  7. aop的简单使用(代码和配置记录)

    Spring aop 简单示例 简单的记录一下spring aop的一个示例 基于两种配置方式: 基于xml配置 基于注解配置 这个例子是模拟对数据库的更改操作添加事物 其实并没有添加,只是简单的输出 ...

  8. Spring IOC DI AOP 的简单理解及应用

    Spring两大特性:IOC 和AOP.IOC 控制反转,AOP 面向切面编程 spring 核心容器的主要组件时Bean工厂(BeanFactory) ,Bean 工厂使用控制反转模式来降低程序代码 ...

  9. spring aop expression简单说明

    <aop:config> <aop:pointcut id="userDAO" expression="execution(public * cn.da ...

随机推荐

  1. Vue.js使用前

    下载安装 node,npm,git 安装cnpm 淘宝cnpm镜像https://npm.taobao.org/,-g表示进行全局安装 npm install -g cnpm --registry=h ...

  2. Codeforces #317 C.Lengthening Sticks(数学)

    C. Lengthening Sticks time limit per test 1 second memory limit per test 256 megabytes input standar ...

  3. 用anaconda的pip安装第三方python包的日志

    用anaconda的pip安装第三方python包的日志 启动anaconda命令窗口: 开始> 所有程序> anaconda> anaconda prompt 会得到两行提示: D ...

  4. 如何用 Git 合并两个库,并保留提交历史

    转载自 https://segmentfault.com/a/1190000000678808 背景 一个中型规模项目,开始规划时就打算采用 C/S 架构,后端是单纯的 API 服务,前端在 Web ...

  5. DDD之:Repository仓储模式

    在DDD设计中大家都会使用Repository pattern来获取domain model所需要的数据. 1.什么事Repository? "A Repository mediates b ...

  6. javascript--正则表达式--更新中

    引用地址:http://www.iteye.com/topic/481228 和http://www.cnblogs.com/rubylouvre/archive/2010/03/09/1681222 ...

  7. BZOJ2698染色

    2698: 染色 Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 223  Solved: 150[Submit][Status][Discuss] De ...

  8. 译者序(Core Data 应用开发实践指南)

    Core Data 是数据管理框架. 该书用Grocery Dude 购物管理程序来贯穿整个学习过程. 本书共分三个部分: 前7章为基础篇.从基础知识.迁移方式及扩展方式来讲解托管对象模型.怎么用图形 ...

  9. Angular - - ngCsp、ngFocus、ngBlur、ngForm

    ngCsp 处理CSP(上下文安全策略)的支持. 当开发如google浏览器的扩展时候这个就必须使用. CSP禁止应用程序使用eval和Function(string)生成的函数.如果我们需要兼容,我 ...

  10. JS 上传文件 Uploadify 网址及 v3.2.1 参数说明

    http://www.uploadify.com/ 一.属性 属性名称 默认值 说明 auto true 设置为true当选择文件后就直接上传了,为false需要点击上传按钮才上传 . buttonC ...