面向切面编程的术语:

切面(Aspect): 横切关注点(跨越应用程序多个模块的功能)被模块化的特殊对象

通知(Advice): 切面必须要完成的工作

目标(Target): 被通知的对象

代理(Proxy): 向目标对象应用通知之后创建的对象

连接点(Joinpoint):程序执行的某个特定位置:如类某个方法调用前、调用后、方法抛出异常后等,连接点是程序类中客观存在的事务

切点(pointcut):每个类都拥有多个连接点,例如 ArithmethicCalculator类中 的所有方法实际上都是连接点,AOP 通过切点定位到特定的连接点

实现过程:

  要在 Spring 中声明 AspectJ 切面, 只需要在 IOC 容器中将切面声明为 Bean 实例. 当在 Spring IOC 容器中初始化 AspectJ 切面之后, Spring IOC 容器就会为那些与 AspectJ 切面相匹配的 Bean 创建代理.

  在 AspectJ 注解中, 切面只是一个带有 @Aspect 注解的 Java 类.

  AspectJ 是基于注解的,支持 5 种类型的通知注解:

@Before: 前置通知, 在方法执行之前执行

@After: 后置通知, 在方法执行之后执行

@AfterRunning: 返回通知, 在方法返回结果之后执行

@AfterThrowing: 异常通知, 在方法抛出异常之后

@Around: 环绕通知, 围绕着方法执行

导入spring编程的架包多个:。。。。

-------------------------------------------------------------------------------

  建立一个接口类:ArithmeticCalculator,其是抽象类,不能实例化

package com.atguigu.spring.aop.impl;

public interface ArithmeticCalculator {
//创建一个接口,其是抽象的类,不能实例化
int add(int i,int j);
int sub(int i,int j); int mul(int i,int j);
int div(int i,int j);
}

  创建一个类:ArithmeticCalculatorImpl 继承于接口 ArithmeticCalculator,为该类添加注解@Component("arithmeticCalculator"),并赋标识,

package com.atguigu.spring.aop.impl;

import org.springframework.stereotype.Component;

//@Component基本注解, 标识了一个受 Spring 管理的组件
@Component("arithmeticCalculator")
public class ArithmeticCalculatorImpl implements ArithmeticCalculator { @Override
public int add(int i, int j) {
int result=i+j;
return result;
} @Override
public int sub(int i, int j) {
int result=i-j;
return result;
} @Override
public int mul(int i, int j) {
int result=i*j;
return result;
} @Override
public int div(int i, int j) {
int result=i/j;
return result;
} }

  建立一个类:ArithmeticCalculatorLoggingProxy,为该类添加注解:@Order(2),指定切面的优先级,值越小,优先级越大,@Aspect:为切面注解,面向切面编程,必须加;@Component:指是在IOC容器中的,为类中的方法添加不同的注解,前置通知,后置通知.....

package com.atguigu.spring.aop.impl;
import java.util.Arrays;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component; /*
* 面向切面编程:Spring AOP(其 是基于注解的spring的bean配置):
* @Component:指是在IOC容器中的
* @Aspect:为切面注解,面向切面编程,必须加;
* 可以使用 @Order 注解指定切面的优先级, 值越小优先级越高
*/
@Order(2)
@Aspect
@Component
public class ArithmeticCalculatorLoggingProxy { /*
* @Before:为在执行该方法之前的---前置通知
* execution(public int com.atguigu.spring.aop.impl.ArithmeticCalculator.*(..)):
* 是指,前置通知放在继承这个 接口(全类名为:com.atguigu.spring.aop.impl.ArithmeticCalculator)
* 的类下的所有方法;
* Joinpoint joinpoint:为连接点,获取连接细节信息
* */
@Before("execution(public int com.atguigu.spring.aop.impl.ArithmeticCalculator.*(..))")
public void beforeMethod(JoinPoint joinPoint){
//获取方法名,和参数值,参数值要多个,所以用数组集合的方法
String methodName=joinPoint.getSignature().getName();
Object[] args=joinPoint.getArgs(); System.out.println("The method "+methodName+" begains "+Arrays.asList(args));
} //后置通知:在方法执行之后,无论该方法出现异常,都执行
@After("execution(public int com.atguigu.spring.aop.impl.ArithmeticCalculator.*(..))")
public void afterMethod(JoinPoint joinPoint){
//获取方法名,和参数值
String methodName=joinPoint.getSignature().getName();
System.out.println("The method "+methodName+ " ends");
} //返回通知:是方法正常结束之后返回的代码,如果是非正常结束,抛出异常,如分母为0
//返回通知是可以访问到方法的返回值的,即是该方法的结果
@AfterReturning(value="execution(public int com.atguigu.spring.aop.impl.ArithmeticCalculator.*(..))"
, returning="result")
public void afterReturning(JoinPoint joinPoint,Object result){
//获取方法名,和参数值
String methodName=joinPoint.getSignature().getName();
System.out.println("The method "+methodName+ " *** ends :"+result);
} //@AfterThrowing:异常通知,在目标方法出现异常时会执行的代码;
//异常通知,可以访问到异常对象;且可以指定在出现特定异常时在执行通知代码
@AfterThrowing(value="execution(public int com.atguigu.spring.aop.impl.ArithmeticCalculator.*(..))"
, throwing="e")
public void afterThrowing(JoinPoint joinPoint, Exception e){
String methodName=joinPoint.getSignature().getName();
System.out.println("The method "+methodName+ " Exception :"+ e);
} //@Around:环绕通知;
//环绕通知需要携带 ProceedingJoinPoint 类型的参数.
//环绕通知类似于动态代理的全过程: ProceedingJoinPoint 类型的参数可以决定是否执行目标方法.
// 且环绕通知必须有返回值, 返回值即为目标方法的返回值
@Around("execution(public int com.atguigu.spring.aop.impl.ArithmeticCalculator.*(..))")
public Object aroundMethod(ProceedingJoinPoint pjp){
Object result=null;
//获取方法名
String methodName=pjp.getSignature().getName();
try {
//前置通知,Arrays.asList(pjp.getArgs())为该方法的参数个数,为数组集合
System.out.println("The method "+methodName+" begains "+Arrays.asList(pjp.getArgs())); //执行目标方法
result=pjp.proceed(); //返回通知
System.out.println("The method "+methodName+ " ends with :"+result); } catch (Throwable e) {
//异常通知
System.out.println("The method " +methodName+ " occurs exception "+ e);
e.printStackTrace();
}
//后置通知
System.out.println("The method " + methodName + " ends");
return result;
}
}

在上边的类中,定义一个方法,将方法上注解里面的"execution(public int com.atguigu.spring.aop.ArithmeticCalculator.*(..))"值,换成统一的"declareJointPointExpression()",即可以简化注解里重复的代码,这里使用到了@Pointcut注解

/**
* 定义一个方法, 用于声明切入点表达式. 一般地, 该方法中再不需要添入其他的代码.
* 使用 @Pointcut 来声明切入点表达式.
* 后面的其他通知直接使用方法名来引用当前的切入点表达式.
*/
@Pointcut("execution(public int com.atguigu.spring.aop.ArithmeticCalculator.*(..))")
public void declareJointPointExpression(){}

建立一个spring bean configuration file的xml文件:applicationContext.xml

<!-- 配置自动扫描的包 -->
<context:component-scan base-package="com.atguigu.spring.aop.impl"></context:component-scan> <!-- 配置自动为匹配aspectJ 的java类生成代理对象 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

建立类:Main,进行测试:注意该类中 ArithmeticCalculator,是上边接口类,注解的内容是继承该接口的类 ArithmeticCalculatorImpl  的注解内容

package com.atguigu.spring.aop.impl;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
//ArithmeticCalculator,是一个接口类,注解的是继承该接口的类
ArithmeticCalculator impl=(ArithmeticCalculator) ctx.getBean("arithmeticCalculator"); System.out.println(impl.getClass().getName()); int result=impl.add(12,2);
System.out.println(result); double result2=impl.div(12, 2);
System.out.println(result2);
}
}

Spring AOP:面向切面编程,AspectJ,是基于注解的方法的更多相关文章

  1. 详细解读 Spring AOP 面向切面编程(二)

    本文是<详细解读 Spring AOP 面向切面编程(一)>的续集. 在上篇中,我们从写死代码,到使用代理:从编程式 Spring AOP 到声明式 Spring AOP.一切都朝着简单实 ...

  2. 【原创】Android AOP面向切面编程AspectJ

    一.背景: 在项目开发中,对 App 客户端重构后,发现用于统计用户行为的友盟统计代码和用户行为日志记录代码分散在各业务模块中,比如在视频模块,要想实现对用户对监控点的实时预览和远程回放行为进行统计, ...

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

    简介 我们都知道,Spring 框架作为后端主流框架之一,最有特点的三部分就是IOC控制反转.依赖注入.以及AOP切面.当然AOP作为一个Spring 的重要组成模块,当然IOC是不依赖于Spring ...

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

    一.面向切面编程简介: 在调用某些类的方法时,要在方法执行前或后进行预处理或后处理:预处理或后处理的操作被封装在另一个类中.如图中,UserService类在执行addUser()或updateUse ...

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

    前言 接上一篇文章,在上午中使用了切面做防重复控制,本文着重介绍切面AOP. 在开发中,有一些功能行为是通用的,比如.日志管理.安全和事务,它们有一个共同点就是分布于应用中的多处,这种功能被称为横切关 ...

  6. Spring AOP面向切面编程详解

    前言 AOP即面向切面编程,是一种编程思想,OOP的延续.在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等等.在阅读本文前希望您已经对Spring有一定的了解 注:在能对代码进行添 ...

  7. Spring Aop面向切面编程&&自动注入

    1.面向切面编程 在程序原有纵向执行流程中,针对某一个或某一些方法添加通知,形成横切面的过程叫做面向切面编程 2.常用概念 原有功能:切点,pointcut 前置通知:在切点之前执行的功能,befor ...

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

    之前<零基础带你看Spring源码--IOC控制反转>详细讲了Spring容器的初始化和加载的原理,后面<你真的完全了解Java动态代理吗?看这篇就够了>介绍了下JDK的动态代 ...

  9. Spring AOP 面向切面编程相关注解

    Aspect Oriented Programming 面向切面编程   在Spring中使用这些面向切面相关的注解可以结合使用aspectJ,aspectJ是专门搞动态代理技术的,所以比较专业.   ...

  10. Spring AOP 面向切面编程入门

    什么是AOP AOP(Aspect Oriented Programming),即面向切面编程.众所周知,OOP(面向对象编程)通过的是继承.封装和多态等概念来建立一种对象层次结构,用于模拟公共行为的 ...

随机推荐

  1. NLS_LANG参数说明

    NLS_LANG参数说明 格式:  NLS_LANG = language_territory.charset 它有三个组成部分(语言.地域和字符集),每个成分控制了NLS子集的特性.其中: Lang ...

  2. lcd 图片

    硬件平台:mini2440 软件环境:UCOS2 .ADS1.2 . LCD彩色图片转换工具BMP_to_H工具bmp2h LCD彩色图片转换工具BMP_to_H工具文件夹下的使用说明 在S3C241 ...

  3. Activity之间的数据传递

    最常用的Activity之间的数据传递. btnStartAty1.setOnClickListener(new View.OnClickListener() { @Override public v ...

  4. 20145207《Java程序设计》第6周学习总结

    教材学习内容总结 一.输入/输出 InputStream与Outputstream • 串流设计的概念 从应用程序角度看,将数据从来源取出,可以使用输入串流,将数据写入目的地,可以使用输出串流:在Ja ...

  5. Ubuntu 16.04 LTS Final Beta about JAVA

    我们知道Ubuntu里可能会事先安装了openjdk.但是我习惯于Oracle jdk. ## < 卸载 openjdk > successfully: ### Terminal comm ...

  6. extjs grid 单元格 多选

    new Ext.grid.CellSelectionModel({ last : false, // 上一次选中的单元格 selections : [], // 选择区缓存 handleMouseDo ...

  7. bzoj4216 Pig

    水题,题目难点大概就是空间限制上了,开longlong会爆,可以开个int数组求前缀和,然后一旦绝对值超过20亿,则将其取模,并记录下当前位置,这样询问时就可以二分这些超过的位置,将其乘以20亿后加上 ...

  8. bzoj3489 A simple rmq problem 可持久化树套树

    先预处理出两个个数组pre,next.pre[i]表示上一个与i位置数字相同的位置,若不存在则设为0:next[i]表示下一个与i位置数字相同的位置,若不存在则设为n+1.那么一个满足在区间[L,R] ...

  9. docker gitlab

    Alternatively, you can manually launch the gitlab container and the supporting postgresql and redis ...

  10. 数据可视化工具zeppelin安装

    介绍 zeppelin主要有以下功能 数据提取 数据发现 数据分析 数据可视化 目前版本(0.5-0.6)之前支持的数据搜索引擎有如下 安装 环境 centOS 6.6 编译准备工作 sudo yum ...