关闭

Spring基于xml的方式开发我们的aop程序

190人阅读 评论(0) 收藏 举报
分类:

什么是AOP: AOP是面向切面的编程

在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

AOP的作用:在不影响我们正常的业务逻辑执行的前提下,加上一下我们程序必要的功能,比如下面这些:

  • 日志的记录
  • 权限的校验
  • 事务的管理
  • 性能的检测

AOP的底层实现机制: Jdk的动态代理:必须对有接口的实现类进行增强
Cglib的动态代理:没有任何要求,可以对我们没有实现接口的java类进行增强(关于动态代理我之前有一篇博客做了介绍,传送门:http://blog.csdn.net/likemebee/article/details/78074305

Spring当中AOP的一些专业术语的介绍及图解

1、 目标类target:就是我们需要增强的那个类,target
2、 代理类proxy:就是我们自定义的那个代理的对象proxy
3、 连接点joinPoint:连接点说白了就是我们的目标类里面所有的方法。
4、 切入点pointCut:切入点说白了就是那些在目标类中我们实际上增强的方法。
5、 织入weave:说白了就是将我们的代理类中需要增强的方法放入到目标类中去执行的过程,就叫织入
6、 引介Introduction:是对我们的类中的方法或者属性进行一些创建的过程
7、 通知advice:说白了就是将我们代理对象中的方法应用到目标类的过程中产生的结果。实际上可以理解成就是删除之后的权限校验方法
8、 切面aspect:说白了就是我们的所有的切入点和代理对象的方法组成在一起 构成了我们的切面

这里写图片描述

Spring基于xml的方式开发我们的aop程序:
首先配置我们的接口与实现类OrderService与OrderServiceImpl

package com.yida.spring.demo01;

public interface OrderService {

    public void add();

    public int delete();

    public void update();

    public void find();

    public void batch();
}
package com.yida.spring.demo01;

public class OrderServiceImpl implements OrderService {

    @Override
    public void add() {
        System.out.println("add method invoke");

    }

    @Override
    public int delete() {
        System.out.println("delete method invoke");
        return 10;
    }

    @Override
    public void update() {
        System.out.println("update method invoke");

    }

    @Override
    public void find() {
        System.out.println("find method invoke");
        System.out.println(1/0);

    }

    @Override
    public void batch() {
        System.out.println("batch method invoke");
        System.out.println(1/0);

    }
}

创建我们的代理类OrderProxy

package com.yida.spring.demo01;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

public class OrderProxy {
    /**
     * 前置通知执行的方法
     */
    public void checkPrivilege(){
        System.out.println("权限的校验,我应该再add方法执行之前执行");
    }

    /**
     * 后置通知执行的方法
     */
    public void afterMethod(JoinPoint joinpoint,Object object){
        System.out.println("我是后置通知,我需要在目标方法执行之后再执行");
        System.out.println(object);
    }


    /**
     * ProceedingJoinPoint 如果是环绕通知,我们必须配置一下这个参数,通过执行proceed()方法,才会执行我们目标列当中的目标方法
     * @param joinPoint
     * @throws Throwable
     */
    public void aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable{
        // 第一步:目标方法执行之前执行的逻辑
        System.out.println("我是环绕通知,我会在目标方法执行之前进行执行");
        // 第二步:执行我们的目标方法
        Object proceed = joinPoint.proceed();
        // 第三步:执行目标方法之后的逻辑
        System.out.println("我是环绕通知,我会在目标方法执行之后进行执行");
    }


    /**
     * 实现我们的最终通知
     */
    public void finalMethod(JoinPoint joinPoint){
        System.out.println(joinPoint.getSignature().getDeclaringType());;
        System.out.println(joinPoint.getSignature().getDeclaringTypeName());
        System.out.println("我是最终通知,就算程序抛出异常我也会执行");
    }


    /**
     * 实现我们的异常通知
     */
    public void exceptMethod(Throwable throwable){
        System.out.println(throwable.getMessage());
        System.out.println("我是异常通知,只有在程序抛出异常的时候,我才会执行");
    }
}

然后在我们的配置文件applicationContext.xml里配置相关信息如下:

<?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:c="http://www.springframework.org/schema/c"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">


<!-- 初始化我们的目标类和我们的代理类 -->
  <bean id="orderServiceImpl" class="com.yida.spring.demo01.OrderServiceImpl"></bean>
  <bean id="OrderProxy" class="com.yida.spring.demo01.OrderProxy"></bean>

<aop:config>
<!-- expression是我们的切入点表达式 -->
<!-- 指明我们的切入点 -->
<aop:pointcut expression="execution(* *.add*(..))" id="pointCut1"/>
<aop:pointcut expression="execution(* *.delete*(..))" id="pointCut2"/>
<!-- 环绕通知 -->
<aop:pointcut expression="execution(* *.update*(..))" id="pointCut3"/>
<!-- 最终通知 -->
<aop:pointcut expression="execution(* *.find*(..))" id="pointCut4"/>
<!-- 异常通知 -->
<aop:pointcut expression="execution(* *.batch*(..))" id="pointCut5"/>



<!-- 配置我们的切面类 -->
<aop:aspect ref="OrderProxy">
    <!-- aop:before表示在我们目标方法执行之前进行增强 -->
    <!-- 指明我们的增强的方法,作用在哪个目标方法上 -->
    <aop:before method="checkPrivilege" pointcut-ref="pointCut1"/>
    <!-- 后置通知使用的是我们的after-returning -->
    <aop:after-returning method="afterMethod" pointcut-ref="pointCut2" returning="object"/>

    <!-- 配置我们的环绕通知 -->
    <aop:around method="aroundMethod" pointcut-ref="pointCut3" />

    <!-- 配置我们的最终通知 -->
    <aop:after-throwing method="finalMethod" pointcut-ref="pointCut4"/>

    <!-- 配置实现我们的异常通知 -->
    <aop:after-throwing method="exceptMethod" pointcut-ref="pointCut5" throwing="throwable"/>
</aop:aspect>
</aop:config>
</beans>

注意spring当中切入点表达式的写法,有三个参数:1、方法的修饰符 2、方法的返回值 /3、方法的路径
基本用法如下:
execution(public * *(..)) :任何以public修饰的方法都可以被增强
execution(* set*(..)):以set开头的方法都可以被增强
execution(* com.xyz.service.AccountService.*(..)) :AccountService这个类下面的所有的方法都可以被增强
execution(* com.xyz.service..(..)) com.xyz.service这个包下面的所有的类,以及所有的方法都可以被增强
execution(* com.xyz.service...(..)) 表示com.xyz.service 这个包,以及这个包下面的所有的子包,所有类所有的方法都可以被增强
代理类OrderProxy:

package com.yida.spring.demo01;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

public class OrderProxy {
    /**
     * 前置通知执行的方法
     */
    public void checkPrivilege(){
        System.out.println("权限的校验,我应该再add方法执行之前执行");
    }

    /**
     * 后置通知执行的方法
     */
    public void afterMethod(JoinPoint joinpoint,Object object){
        System.out.println("我是后置通知,我需要在目标方法执行之后再执行");
        System.out.println(object);
    }


    /**
     * ProceedingJoinPoint 如果是环绕通知,我们必须配置一下这个参数,通过执行proceed()方法,才会执行我们目标列当中的目标方法
     * @param joinPoint
     * @throws Throwable
     */
    public void aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable{
        // 第一步:目标方法执行之前执行的逻辑
        System.out.println("我是环绕通知,我会在目标方法执行之前进行执行");
        // 第二步:执行我们的目标方法
        Object proceed = joinPoint.proceed();
        // 第三步:执行目标方法之后的逻辑
        System.out.println("我是环绕通知,我会在目标方法执行之后进行执行");
    }


    /**
     * 实现我们的最终通知
     */
    public void finalMethod(JoinPoint joinPoint){
        System.out.println(joinPoint.getSignature().getDeclaringType());;
        System.out.println(joinPoint.getSignature().getDeclaringTypeName());
        System.out.println("我是最终通知,就算程序抛出异常我也会执行");
    }


    /**
     * 实现我们的异常通知
     */
    public void exceptMethod(Throwable throwable){
        System.out.println(throwable.getMessage());
        System.out.println("我是异常通知,只有在程序抛出异常的时候,我才会执行");
    }
}

最后测试类TestSpring:

package com.yida.spring;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.yida.spring.demo01.OrderService;

public class TestSpring {

    @Test
    public void testAOP(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        OrderService bean = (OrderService) context.getBean("orderServiceImpl");
        //bean.add();
        //bean.delete();
        //bean.update();
        //bean.find();
        bean.batch();
    }
}
0
0
查看评论

重温Spring之旅6——基于XML配置方式进行AOP开发

要进行AOP编程,首先我们要在spring的配置文件中引入aop命名空间: <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001...
  • btt2013
  • btt2013
  • 2017-02-02 22:01
  • 268

Spring的AOP基于xml常用的几种配置

一般spring的AOP实现方式有二中 1、spring-aop自己实现与IOC结合使用,也是我们最常用的方式 2、使用AspectJ,即注解的方式 个人觉得,spring中使用配置文件还是比较简洁的。 spring中要想使用aop这种方式,需要以下jar包:  首先,如果要在工程...
  • u011955252
  • u011955252
  • 2016-10-27 14:10
  • 681

spring -- aop基于xml的简单实现

1、引入jar包 :aopalliance.jar,aspecjweaver.jar 2、创建一个针对于某个关注点的切面类:如关注日志,就做LogAspect public class LogAspect { public void logStart(){ Logger.info(&qu...
  • u014527912
  • u014527912
  • 2016-05-08 19:14
  • 264

Spring AOP之AspectJ的XML方式使用

(1)jar包 l AOP联盟规范:com.springsource.org.aopalliance-1.0.0.jar  spring aop实现:spring-aop-3.2.0.RELEASE.jar aspectJ 框架的jar(实现、规范):com.sp...
  • u010889616
  • u010889616
  • 2016-09-04 21:54
  • 912

SSM框架项目搭建系列(六)—Spring AOP之基于XML的声明式AspectJ

AOP通过“横切”技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,将其命名为Aspect,即切面。切面就是将那些与业务无关(例如:权限认证、日志、事务处理),确为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性...
  • YEN_CSDN
  • YEN_CSDN
  • 2016-11-02 22:19
  • 1319

spring之aop编程——基于注解、xml配置文件方式

AOP(Aspect Oriented Programming),是面向切面编程的技术。AOP基于IoC基础,是对OOP的有益补充。spring中AOP的配置方式有2种方式:xml配置和AspectJ注解方式。 一、xml配置的方式: 1、service接口和服务类: package cn.e...
  • liuxiao723846
  • liuxiao723846
  • 2015-08-04 16:03
  • 2009

AOP实现方式1——经典的基于代理的AOP实现

1.定义接口Perform package com.show; /** * Created by kenneth on 2017/4/6. */ public interface Perform { void sing(); } 2.定义接口Perform的实现类Boy pack...
  • csdn_kenneth
  • csdn_kenneth
  • 2017-04-06 15:24
  • 405

Spring Xml文件配置实现AOP通知

在前一篇文章,我们讲述了注解实现AOP的通知,这一片,我们看一下,xml文件
  • yezis
  • yezis
  • 2014-04-26 01:45
  • 1392

Spring中的AOP(六)——基于XML配置文件方式的AOP

除了前面介绍的基于JDK1.5的注解方式来定义切面,切入点和增强处理外,Spring AOP也允许直接使用XML配置文件来管理它们。在JDK1.5之前,只能使用配置文件的方式来管理,在Spring2.X后提供了一个新的aop命名空间来定义切面、切入点和增强处理。   ...
  • caomiao2006
  • caomiao2006
  • 2016-04-30 17:41
  • 2846

Spring AOP四种实现方式Demo详解与相关知识探究

一、前言 在网络上看到一篇博客Spring实现AOP的4种方式,博主写的很通俗易懂,但排版实在抓狂,对于我这么一个对排版、代码格式有强迫症的人来说,实在是不能忍受~~~~(>_ 我亲手实现了一遍,重新整理,加上了一些不易关注到的细节、漏掉的知识,以及自己对AOP的一些理解,写成这篇博客。 ...
  • zhangliangzi
  • zhangliangzi
  • 2016-08-27 18:19
  • 9215
    个人资料
    • 访问:2802次
    • 积分:197
    • 等级:
    • 排名:千里之外
    • 原创:17篇
    • 转载:0篇
    • 译文:0篇
    • 评论:3条
    最新评论