Spring AOP(面向切面示例)

什么是AOP?
基本概念
切面(aspect):横切关注点被模块化的特殊对象。
通知(advice):切面必须要完成的工作。切面中的每个方向称之为通知。通知是在切面对象中的。
目标(target):被通知的对象。
代理(proxy):向目标对象应用通知后创建的对象。

连接点(joinpoint):目标对象的程序执行的某个特定位置。如某个方法调用前,调用后的位置。包括两个信息:1.目标程序的哪个方法?2.方法执行 
前还是执行后?
切点(pointcut):每个类会有多个连接点,AOP通过切点定位到特定的边接点。
类比,连接点相当于数所成方圆 中的记录,而切点相当于查询条件。一个切点匹配多个连接点。

使用XML配置的方法:

1.导入 spring包和aspectj的两个jar包

2.目标对象(要切入的对象)

首先为了不违反开闭原则和更好的可扩展性,目标对象实际上是实现了已定义好的某个接口

接口:

package com.itnba.test;

public interface IHuman {
    public void chifan();
    public void shuijiao();

}

实现接口的两个类:

package com.itnba.test;

import org.springframework.stereotype.Component;

public class Chinese implements IHuman {

    @Override
    public void chifan() {
        // TODO 自动生成的方法存根
        System.out.println("中国人吃饭");

    }

    @Override
    public void shuijiao() {
        // TODO 自动生成的方法存根
        System.out.println("中国人睡觉");
    }

}
package com.itnba.test;

import org.springframework.stereotype.Component;

public class American implements IHuman {

    @Override
    public void chifan() {
        // TODO 自动生成的方法存根
        System.out.println("美国人吃饭");

    }

    @Override
    public void shuijiao() {
        // TODO 自动生成的方法存根
        System.out.println("美国人睡觉");
    }

}

3.定义一个切面类

package com.itnba.test;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
public class Qiemian {

    public void chifanqian(){
        System.out.println("洗手");
    }
    public void chifanhou(){
        System.out.println("漱口");
    }
    public void shuijiaoqian(){
        System.out.println("洗澡");

    }

}

4.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: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-4.3.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-4.3.xsd"
        default-autowire="byName"
        >
         <!-- 首相要实例化目标对象类和切面类 -->
        <bean id="chinese" class="com.itnba.test.Chinese"></bean>
        <bean id="american" class="com.itnba.test.American"></bean>
        <bean id="qiemian" class="com.itnba.test.Qiemian"></bean>

        <aop:config>
        <!-- 要切入的对象 -->
        <aop:pointcut expression="execution(* com.itnba.test.*.chifan(..))" id="chifan"/>
        <aop:pointcut expression="execution(* com.itnba.test.*.shijiao(..))" id="shijiao"/>
        <!-- 切入点 -->
        <aop:aspect id="ha" ref="qiemian"><!-- 切面类  -->
            <!--  <aop:之前before、之后after... method="切面类中的方法" pointcut-ref="上面的切入的对象"/>  -->
            <aop:before method="chifanqian()" pointcut-ref="chifan"/><!-- 之前通知 -->
            <aop:after method="chifanhou()()" pointcut-ref="chifan"/><!-- 之后通知 -->
            <aop:before method="shuijiaoqian()" pointcut-ref="shijiao"/>
        </aop:aspect>
    </aop:config>
</beans>

5.运行

package com.itnba.test;

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

public class Test {

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        //要用接口接收
        IHuman c= (IHuman)context.getBean("chinese");
        c.chifan();
        c.shuijiao();
        System.out.println("*********************************");
        //要用接口接收
        IHuman a= (IHuman) context.getBean("american");
        a.chifan();
        a.shuijiao();

    }

}

结果:

使用注解的方法:

1.导如 spring包和aspectj的两个jar包

2.配置文件中加入aop命名空间

<?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"
    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-4.3.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-4.3.xsd" >

        <!-- 自动扫描包下的类,并将其实例化。多个包之间用,隔开 -->
        <context:component-scan base-package="com.itnba.test"></context:component-scan>
        <!-- 配置文件中启动AspectJ的注解功能 ,默认是false,要将其改为true -->
        <aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
</beans>

3.目标对象(要切入的对象)

首先为了不违反开闭原则和更好的可扩展性,目标对象实际上是实现了已定义好的某个接口

接口:

package com.itnba.test;

public interface IHuman {
    public void chifan();
    public void shuijiao();

}

实现接口的两个类:

package com.itnba.test;

import org.springframework.stereotype.Component;

@Component
public class Chinese implements IHuman {

    @Override
    public void chifan() {
        // TODO 自动生成的方法存根
        System.out.println("中国人吃饭");

    }

    @Override
    public void shuijiao() {
        // TODO 自动生成的方法存根
        System.out.println("中国人睡觉");
    }

}
package com.itnba.test;

import org.springframework.stereotype.Component;

@Component
public class American implements IHuman {

    @Override
    public void chifan() {
        // TODO 自动生成的方法存根
        System.out.println("美国人吃饭");

    }

    @Override
    public void shuijiao() {
        // TODO 自动生成的方法存根
        System.out.println("美国人睡觉");
    }

}

4.定义一个切面类,直接在里面注解

package com.itnba.test;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Aspect //声明该类是切面类
@Component//配置文件中启动自动扫描功能
public class Qiemian {

    @Before("execution(* com.itnba.test.*.chifan(..))")//在那个方法的之前通知    *代表全部..代表所有形参,不管有多少
    public void chifanqian(){
        System.out.println("洗手");
    }
    @After("execution(* com.itnba.test.*.chifan(..))")//在那个方法之后通知
    public void chifanhou(){
        System.out.println("漱口");
    }
    @Before("execution(* com.itnba.test.*.shuijiao(..))")
    public void shuijiaoqian(){
        System.out.println("洗澡");

    }

}

5.写好后用main函数来运行一下

package com.itnba.test;

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

public class Test {

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        Chinese c= context.getBean(Chinese.class);
        c.chifan();
        c.shuijiao();
        System.out.println("*********************************");
        American a= (American) context.getBean("american");
        a.chifan();
        a.shuijiao();

    }

}

结果:

这样,Spring的面向切面编程就简单介绍完了。

通知分类:
前置通知(@Before) -- 在目标方法执行前执行的通知。
后置通知(@After) -- 在目标方法执行后执行的通知。无论是否发生异常。后置通知中,无法读取目标方法返回的结果。
返回通知(@AfterReturnning) --在目标方法执行成功后执行的通知。在返回通知中可以访问目标返回结果的。 
@AfterReturnning(value="execution(* com.itnba..*(..))",returning="result")
public void afterRun(Object result){
System.out.println(result);
}

异常通知(@AfterThrowing) -- 在目标方法执行出错后执行的通知。
@AfterThrowing(value="execution(* com.itnba..*(..))",throwing="ex")
public void afterThrowing(Exception ex){
System.out.println(ex.getMessage());
}

环绕通知(@Around) -- 需要切面方法携带ProceedingJoinPoion参数,类似于一个完整的动态代理,环绕通知必须要有一个返回值,是目标方法的返 
回值。

@Around("execution(* com.itnba..*(..))")
public object aroundAdvice( ProceedingJoinPoint pjp){

object obj = null;
try{
//做前置通知
obj = pjp.proceed();
//做返回通知
}
catch(Exception ex){
//做异常通知
}
//做后置通知
return obj;
}

添加日志:

切面方法可以加入参数(JoinPoint) joinPost.getSignature().getXXX()获得相关方法信息
切面方法中可以加入Object参数,用来获得目标方法的返回值(只对返回通知起作用)

时间: 2024-10-13 19:11:02

Spring AOP(面向切面示例)的相关文章

深入探索spring技术内幕(七): 配置Spring AOP面向切面编程

一. AOP一些概念 Aspect( 切面 ): 指横切性关注点的抽象即为切面, 它与类相似, 只是两者的关注点不一样, 类是对物体特征的抽象, 而切面横切性关注点的抽象. joinpoint( 连接点 ): 指那些被拦截到的点. 在spring中, 这些点指的是方法, 因为spring只支持方法类型的连接点, 实际上joinpoint还可以是field或类构造器) Pointcut( 切入点 ): 指我们要对那些joinpoint进行拦截的定义. Advice( 通知 ): 指拦截到joinp

浅谈Spring AOP 面向切面编程 最通俗易懂的画图理解AOP、AOP通知执行顺序~

简介 我们都知道,Spring 框架作为后端主流框架之一,最有特点的三部分就是IOC控制反转.依赖注入.以及AOP切面.当然AOP作为一个Spring 的重要组成模块,当然IOC是不依赖于Spring框架的,这就说明你有权选择是否要用AOP来完成一些业务. AOP面向切面编程,通过另一种思考的方式,来弥补面向对象编程OOP当中的不足,OOP当中最重要的单元是类,所以万物皆对象,万物皆是 对象类.而在AOP的模块单元中,最基础的单元是切面,切面对切点进行模块化的管理. 最后再提一句:Spring当

从源码入手,一文带你读懂Spring AOP面向切面编程

之前<零基础带你看Spring源码--IOC控制反转>详细讲了Spring容器的初始化和加载的原理,后面<你真的完全了解Java动态代理吗?看这篇就够了>介绍了下JDK的动态代理. 基于这两者的实现上,这次来探索下Spring的AOP原理.虽然AOP是基于Spring容器和动态代理,但不了解这两者原理也丝毫不影响理解AOP的原理实现,因为大家起码都会用. AOP,Aspect Oriented Programming,面向切面编程.在很多时候我们写一些功能的时候,不需要用到继承这么

Spring AOP 面向切面编程

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

spring AOP面向切面编程学习笔记

一.面向切面编程简介: 在调用某些类的方法时,要在方法执行前或后进行预处理或后处理:预处理或后处理的操作被封装在另一个类中.如图中,UserService类在执行addUser()或updateUser方法前开启事务,执行完后要提交事务:而几乎所有数据库操作都是如此,那么就可以将事务操作的方法提取出封装到一个类里.然后再利用代理类进行处理(目标类方法增强),返回代理类对象 二.AOP相关术语 Target:目标类,需要被增强的类. JoinPoint:连接点,目标类上需要被增强的方法.(这些方法

【spring-boot】spring aop 面向切面编程初接触

众所周知,spring最核心的两个功能是aop和ioc,即面向切面,控制反转.这里我们探讨一下如何使用spring aop. 1.何为aop aop全称Aspect Oriented Programming,面向切面,AOP主要实现的目的是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果.其与设计模式完成的任务差不多,是提供另一种角度来思考程序的结构,来弥补面向对象编程的不足. 通俗点讲就是提供一个为一个业务实现提供切面注入的

【Spring系列】Spring AOP面向切面编程

前言 接上一篇文章,在上午中使用了切面做防重复控制,本文着重介绍切面AOP. 在开发中,有一些功能行为是通用的,比如.日志管理.安全和事务,它们有一个共同点就是分布于应用中的多处,这种功能被称为横切关注点(cross-cutting concerns). DI(依赖注入)有助于应用对象之间的解耦,而AOP可以实现横切关注点与他们所影响的对象之间的解耦. 面向切面编程在Spring AOP中有4种类型的调用,方法调用的之前.后.异常增加其他方法,方法调用的前和后调用其他方法,将方法中的参数传递给其

十二.Spring AOP面向切面编程

什么是AOP? AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术. AOP的第一个案例 要求:使用AOP实现日志记录功能,核心模块和增强单独开发,运行时组装 1.创建接口HelloDao.HelloService. 创建接口类HelloDaoImpl.HelloServiceImpl并实现dao层接口 public interface IHolleDao { public void print

Spring AOP面向切面编程详解

前言 AOP即面向切面编程,是一种编程思想,OOP的延续.在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等等.在阅读本文前希望您已经对Spring有一定的了解 注:在能对代码进行添加注解方式实现AOP的话,并不推荐使用XML方式.换言之在XML方式配置更适用于不能对代码添加注解的情况下(注解配置方式推荐值>XML配置方式推荐值) AOP相关术语 1.通知(Advice):在切面的某个特定的连接点上执行的动作,即当程序到达一个执行点后会执行相对应的一段代码,也称为增强处理.通知

Spring AOP面向切面编程

出处:http://yangfei520.blog.51cto.com/1041581/1273069 前两天,在给新入职的同事做技术介绍时,讲到spring的AOP.使我又一次认识到,对于AOP,特别是spring AOP的理解,虽然大家都能说上来几句,但是许多人认识并不太全面,甚至可以说是一知半解----即使是对于那些已经有过几年开发经验的工程师也是如此.所以,回来之后,我干脆对这块东西做了个肤浅的小结,以便再有类似任务时,直接拿来给大家借鉴. AOP(Aspect-Oriented Pro