一.AOP开发中的相关术语。

  ——JoinPoint(连接点):指那些可以被拦截到的点。比如增删改查方法都可以增强,这些方法就可以被称为是连接点。

  ——PointCut:切入点,真正被拦截的点,指对哪些连接点进行拦截的定义。JoinPoint是指方法可以增强,而切入点就是实际哪个方法进行增强或修改,这样的方法被称为切入点。

  ——Advice(增强/通知):方法层面的增强。指拦截到了方法后需要做的事情,也就是增强的功能部分被称为通知。分为前置(方法主体之前)、后置、环绕通知。 

  ——Introduction(引介):是一种特殊的通知,再不修改类代码的前提下进行类层面的增强。

  ——Target:代理的目标对象,在AOP中也可以说是被增强的对象,如对UserDao增强,那么UserDao就是目标对象。

  ——Weaving(织入):指将通知(Advice)应用到目标(Target)的过程。 也就是将增强应用到目标对象来创建新的代理对象的过程。Spring采用动态织入的方式。

  ——Proxy(代理):一个类被AOP织入增强后,就产生一个结果代理类。

  ——Aspect(切面):是多个切入点和多个通知(引介)的结合。在代理中可能有切面。

二、Spring使用AspectJ进行AOP开发(XML方式)

  A.创建动态web项目,引入jar包。

    spring核心开发包。

    Spring的AOP开发包。spring-aop-4.2.4.RELEASE.jar         com.springsource.org.aopalliance-1.0.0.jar

    aspectJ的开发包:com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar           spring-aspects-4.2.4.RELEASE.jar

    

  B.配置文件(现在开发AOP,所以要引入AOP的xml规范)

  这些xml规范不用记,在spring-framework-4.2.4.RELEASE-dist\docs\spring-framework-reference\html\xsd-configuration.html中就可以找到各种约束。

<?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:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- bean definitions here --> </beans>

  C.创建目标类进行配置  


  public interface OrderDao {

    void findAll();

    void remove();

    void save();

    void update();
  }


  public class OrderDaoImpl implements OrderDao {

    @Override
    public void findAll() {
      System.out.println("查找所有订单......");
    }

    @Override
    public void remove() {
      System.out.println("移除订单......");
    }

    @Override
    public void save() {
      System.out.println("保存客户订单......");
    }

    @Override
    public void update() {
      System.out.println("修改订单信息......");
    }

}

 
<!-- 对目标类进行代理,交给spring管理 -->
<bean id="orderDao" class="cn.xxx.spring4.demo1.OrderDaoImpl"></bean>

 D.编写测试类。

  

//Spring与Junit整合的jar,用来单元测试,在别的地方也可以用到,但是其他地方需要开启spring注解才能用,contextConfiguration是用来加载配置文件
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:/config/applicationContext1.xml")
public class demo1 { // 为属性设置值
@Resource(name="orderDao")
private OrderDao orderDao; @Test
public void test1() {
orderDao.findAll();
}
}

测试结果:

18:04:16,743  INFO DefaultTestContextBootstrapper:259 - Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener]
18:04:16,747 INFO DefaultTestContextBootstrapper:207 - Could not instantiate TestExecutionListener [org.springframework.test.context.transaction.TransactionalTestExecutionListener]. Specify custom listener classes or make the default listener classes (and their required dependencies) available. Offending class: [org/springframework/transaction/interceptor/TransactionAttributeSource]
18:04:16,749 INFO DefaultTestContextBootstrapper:207 - Could not instantiate TestExecutionListener [org.springframework.test.context.web.ServletTestExecutionListener]. Specify custom listener classes or make the default listener classes (and their required dependencies) available. Offending class: [org/springframework/web/context/request/RequestAttributes]
18:04:16,750 INFO DefaultTestContextBootstrapper:207 - Could not instantiate TestExecutionListener [org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener]. Specify custom listener classes or make the default listener classes (and their required dependencies) available. Offending class: [org/springframework/transaction/interceptor/TransactionAttribute]
18:04:16,751 INFO DefaultTestContextBootstrapper:185 - Using TestExecutionListeners: [org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener@13c78c0b, org.springframework.test.context.support.DependencyInjectionTestExecutionListener@12843fce, org.springframework.test.context.support.DirtiesContextTestExecutionListener@3dd3bcd]
18:04:16,814 INFO XmlBeanDefinitionReader:317 - Loading XML bean definitions from class path resource [config/applicationContext1.xml]
18:04:16,881 INFO GenericApplicationContext:578 - Refreshing org.springframework.context.support.GenericApplicationContext@59fa1d9b: startup date [Fri May 10 18:04:16 CST 2019]; root of context hierarchy
查找所有订单......
18:04:16,940 INFO GenericApplicationContext:960 - Closing org.springframework.context.support.GenericApplicationContext@59fa1d9b: startup date [Fri May 10 18:04:16 CST 2019]; root of context hierarchy

E.通知类型。

  前置通知 :在目标方法执行之前执行.

  后置通知 :在目标方法执行之后执行

  环绕通知 :在目标方法执行前和执行后执行

  异常抛出通知:在目标方法执行出现异常的时候执行

  最终通知 :无论目标方法是否出现异常最终通知都会执行.相当于final

演示:创建一个切面类(指的是该类可以横向切入一个连接点),比如权限校验方法。在创建之前我们先了解一下切入点表达式,所谓切入点表达式通过一些特点的表达式,Spring底层通过反射来将切入的点(具体要增强的方法)的全路径+方法名与表达式一一对应、

  切入点表达式:execution(表达式) 

    表达式意义:      []代表可以省略 ,由于方法参数一般不知道,所以用..表示  execution代表执行

    [方法访问修饰符] 方法返回值 包名.类名.方法名(方法的参数) 

    public * cn.itcast.spring.dao.*.*(..)   * 代表任意的意思,这里代表方法返回值为所有,类名和方法名任意,也就是找cn.itcast.spring.dao包下面的所有类中的方法,都被增强
  * cn.itcast.spring.dao.*.*(..) 
  * cn.itcast.spring.dao.UserDao+.*(..) 当前UserDao类及其子类的所有方法
  * cn.itcast.spring.dao..*.*(..) 当前包及其子包下的类的所有方法

切面类:


public class MyAspect {
  public void validate() {
    System.out.println("权限校验");
  }

  public void logWrite(Object result) {
    System.out.println("日志记录");
  }
}

 

前置通知 

<!--配置 -->
<!-- 对目标类进行代理,交给spring管理 -->
<bean id="orderDao" class="cn.xxx.spring4.demo1.OrderDaoImpl"></bean>
<bean id="myAspect" class="cn.xxx.spring4.demo1.MyAspect"></bean> <aop:config>
<aop:pointcut expression="execution (* cn.xxx.spring4.demo1.OrderDaoImpl.findAll(..))" id="pointcut1"/>
<aop:aspect ref="myAspect">
       <!-- 前置通知 -->
<aop:before method="validate" pointcut-ref="pointcut1"/>
</aop:aspect>
</aop:config>

运行结果:

权限校验
查找所有订单......

后置通知

<aop:pointcut expression="execution(* cn.xxx.spring4.demo1.OrderDaoImpl.remove(..))" id="pointcut2"/>

    <!-- 后置通知,这里面returning的返回值和切面类中的切入点方法里面的参数一致就行, -->
<aop:after-returning method="logWrite" pointcut-ref="pointcut2" returning="result"/>

运行结果:

移除订单......
日志记录

环绕通知

切面类方法:

public void check(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("开启性能监控");
// 执行切入点的目标程序,在方法前后插入,那么中间的原本方法一定要执行,这句话就是执行原有方法的代码
joinPoint.proceed();
System.out.println("结束性能监控");
}

配置:

<aop:pointcut expression="execution(* cn.xxx.spring4.demo1.OrderDaoImpl.update(..))" id="pointcut3"/>

<aop:aspect ref="myAspect">
<!-- 环绕通知 -->
<aop:around method="check" pointcut-ref="pointcut3"/>
</aop:aspect>

运行结果:

开启性能监控
修改订单信息......
结束性能监控

异常抛出通知

  切面类方法:

方法参数为Throwable ex,异常对象,和配置中保持一致
public void afterThrowing(Throwable ex) {
ex.printStackTrace();
     system.out.println("发生除0异常")
}

配置:

<!-- 异常抛出通知,注意这里的throwing属性的值一定和切面类方法里面的参数一致 -->
<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut4" throwing="ex"/>
</aop:aspect>

如果切入点方法里面出现异常,通知就会生效,就会执行通知的方法。

通知方法(切面类的方法)

public void afterThrowing(Throwable ex) {
ex.printStackTrace();
System.out.println("发生除0异常");
}

运行结果:

java.lang.ArithmeticException: / by zero
at cn.xxx.spring4.demo1.OrderDaoImpl.save(OrderDaoImpl.java:20)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:302)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:58)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208)
at com.sun.proxy.$Proxy13.save(Unknown Source)
at cn.xxx.test.demo1.testSave(demo1.java:41)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:254)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:89)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:193)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:89)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)
发生除0异常

最终通知:和上面类似就不演示了。

Spring框架学习——AOP的开发的更多相关文章

  1. spring框架学习(六)AOP

    AOP(Aspect-OrientedProgramming)面向方面编程,与OOP完全不同,使用AOP编程系统被分为方面或关注点,而不是OOP中的对象. AOP的引入 在OOP面向对象的使用中,无可 ...

  2. Spring框架学习一

    Spring框架学习,转自http://blog.csdn.net/lishuangzhe7047/article/details/20740209 Spring框架学习(一) 1.什么是Spring ...

  3. Spring框架学习总结(上)

    目录 1.Spring的概述 2.Spring的入门(IOC) 3.Spring的工厂类 4.Spring的配置 5.Spring的属性注入 6.Spring的分模块开发的配置 @ 1.Spring的 ...

  4. Spring框架学习笔记(1)

    Spring 框架学习笔记(1) 一.简介 Rod Johnson(spring之父) Spring是分层的Java SE/EE应用 full-stack(服务端的全栈)轻量级(跟EJB比)开源框架, ...

  5. Spring框架学习1

    AnonymouL 兴之所至,心之所安;尽其在我,顺其自然 新随笔 管理   Spring框架学习(一)   阅读目录 一. spring概述 核心容器: Spring 上下文: Spring AOP ...

  6. Spring框架的AOP技术(注解方式)

    1. 步骤一:创建JavaWEB项目,引入具体的开发的jar包 * 先引入Spring框架开发的基本开发包 * 再引入Spring框架的AOP的开发包 * spring的传统AOP的开发的包 * sp ...

  7. Spring框架学习之IOC(一)

    Spring框架学习之IOC(一) 先前粗浅地学过Spring框架,但当时忙于考试及后期实习未将其记录,于是趁着最近还有几天的空闲时间,将其稍微整理一下,以备后期查看. Spring相关知识 spri ...

  8. Spring 框架的 AOP 简介

    Spring 框架的 AOP Spring 框架的一个关键组件是面向方面的编程(AOP)(也称为面向切面编程)框架. 面向方面的编程需要把程序逻辑分解成不同的部分称为所谓的关注点. 跨一个应用程序的多 ...

  9. Spring框架之AOP源码完全解析

    Spring框架之AOP源码完全解析 Spring可以说是Java企业开发里最重要的技术.Spring两大核心IOC(Inversion of Control控制反转)和AOP(Aspect Orie ...

随机推荐

  1. 谈谈javaScript

    谈谈javaScript  (杰我学习) 一. 什么是JavaScript       人们通常所说的JavaScript,其正式名称为ECMAScript.这个标准由ECMA组织发展和维护.ECMA ...

  2. UVA-12293(组合游戏)

    题意: 有两个相同的盒子,一个盒子里面有n个球,另一个盒子里面有1个球,每次清空球较少的那个盒子,然后从另外的一个盒子里拿到空盒子里使得操作后两个盒子至少有一个球,判断是先手还是后者胜; 思路: 跟每 ...

  3. Java标准输入

    Java: import java.util.*; public class Main{ public static void main(String args[]){ Scanner cin = n ...

  4. js中实现子页面向父页面中赋值

    (方法一) 父页面: <input id="input1" type="text"/> <a href="javascript:wi ...

  5. JS获取元素的offsetTop,offsetLeft等相关属性

    1. obj.clientWidth //获取元素的宽度 obj.clientHeight //元素的高度 obj.offsetLeft //元素相对于父元素的left obj.offsetTop / ...

  6. const用在成员函数之后的情况

    常成员函数         使用const关键字进行说明的成员函数,称为常成员函数.只有常成员函数才有资格操作常量或常对象,没有使用const关键字说明的成员函数不能用来操作常对象.常成员函数说明格式 ...

  7. tetrahedron

    题意: 求解一个四面体的内切球. 解法: 首先假设内切球球心为$(x0,x1,x2)$,可以用$r = \frac{3V}{S_1+S_2+S_3+S_4}$得出半径, 这样对于四个平面列出三个方程, ...

  8. TypeScript完全解读(26课时)_18.Mixins混入

    本节的代码在mixin.ts文件内 同时在index.ts内引入 混入就是把两个对象或者类的内容混合到一起,从而实现一些功能复用. 对象混入 js中对象的混入 先来看一个js中对象的混入的例子 首先定 ...

  9. Jquery等待ajax执行完毕继续执行(断点调试正常,运行异常)

    以前写过一个程序,发现用断点调试的时候,一步步的运行,程序是可以的,但是去了断点程序就出现了问题. $(document).ready(function(){ var arra=new Array() ...

  10. mysql使用小结

    一.修改 mysql 的 root 密码 mysql> use mysql;  mysql> update user set password=password('123456') whe ...