使用Spring实现AOP(XML+注解)
一、Spring对AOP的支持
AOP并不是Spring框架特有的,Spring只是支持AOP编程的框架之一,每一个框架对AOP的支持各有特点,有些AOP能够对方法的参数进行拦截,有些AOP对方法进行拦截。而Spring AOP是一只基于方法拦截的AOP,换句话说Spring只能支持方法拦截的AOP。
在Spring中有4种方式去实现AOP的拦截功能:
1、使用ProxyFactoryBean和对应的接口实现AOP
2、使用XML配置AOP
3、使用@AspectJ注解驱动切面
4、使用Aspect注入切面
Spring AOP 的拦截方式中,真正常用的是用@AspectJ注解的方式实现的切面,有时候XML配置也有一定的辅助作用
spring AOP使用@AspectJ注解:https://www.cnblogs.com/weibanggang/p/10137217.html
二、面向切面编程的术语
1、切面(ASPECT)
切面就是一套规范的流程,可以理解为一个拦截器,能定义被拦截方法执行前后可以执行的操作。(即,它是一个类。)
2、通知(Advice)
通知就是切面中的方法,它根据在代理真实对象方法调用前、后的顺序和业务逻辑进行区分,Spring AOP中有四种通知:(即,它是类中的一个方法。)
- 前置通知(before):在动态代理反射原有对象方法或者执行环绕通知前执行的通知功能;
- 后置通知(after):在动态代理反射原有对象方法或者执行环绕通知后执行的通知功能,不管是否返回异常都会被执行;
- 返回通知(afterReturning):在动态代理反射原有对象方法或者执行环绕通知正常返回无异常时执行的通知功能;
- 异常通知(afterThrowing):在动态代理反射原有对象方法或者执行环绕通知产生异常时执行的通知功能;
- 环绕通知(around):在动态代理中,它可以取代当前被拦截对象的方法,提供回调原有被拦截对象的方法;
3、引入(Introduction)
引入允许我们在现有类里添加的自定义类或方法。比如我们要对一个被代理对象的逻辑进行优化,但是不能修改原方法时,可以使用引入来进行增强;
4、切点(Pointcut)
切点就是告诉Spring AOP什么时候启动拦截器并织入对应流程中。
5、连接点(join point)
连接点对应的是具体需要拦截的东西,比如通过切点的正则表达式去判断哪些方法是连接点,从而织入对应的通知;
6、织入(Weaving)
织入是一个生成代理对象,并且将切面内容放入到流程中的过程,它的实现方式就是动态代理
SpringAOP中,通过Advice定义横切逻辑,Spring中支持5种类型的Advice:
一、基于XML配置的Spring AOP
1、创建要被代理的Math类,代码如下
创建类:Math
- package com.wbg.springAOP.spring;
- public class Math {
- //加
- public int add(int n1,int n2){
- int result=n1+n2;
- System.out.println(n1+"+"+n2+"="+result);
- return result;
- }
- //减
- public int sub(int n1,int n2){
- int result=n1-n2;
- System.out.println(n1+"-"+n2+"="+result);
- return result;
- }
- //乘
- public int mut(int n1,int n2){
- int result=n1*n2;
- System.out.println(n1+"X"+n2+"="+result);
- return result;
- }
- //除
- public int div(int n1,int n2){
- int result=n1/n2;
- System.out.println(n1+"/"+n2+"="+result);
- return result;
- }
- }
2、编辑AOP中需要使用到的通知类Advices.java代码如下:
- package com.wbg.springAOP.spring;
- import org.aspectj.lang.JoinPoint;
- public class Advices {
- public void before(JoinPoint jp){
- System.out.println("----------前置通知----------");
- System.out.println(jp.getSignature().getName());
- }
- public void after(JoinPoint jp){
- System.out.println("----------最终通知----------");
- }
- }
3、配置容器初始化时需要的XML文件,aop01.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"
- 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 id="math" class="com.wbg.springAOP.spring.Math"/>
- <!--通知-->
- <bean id="advices" class="com.wbg.springAOP.spring.Advices"/>
- <!--aop配置-->
- <aop:config proxy-target-class="true">
- <!--切面-->
- <aop:aspect ref="advices">
- <!--切点-->
- <aop:pointcut id="pointcur1" expression="execution(* com.wbg.springAOP.spring.Math.*(..))"/>
- <!--连接通知方法与切点-->
- <aop:before method="before" pointcut-ref="pointcur1"/>
- <aop:after method="after" pointcut-ref="pointcur1"/>
- </aop:aspect>
- </aop:config>
- </beans>
4、测试:
- ApplicationContext context = new ClassPathXmlApplicationContext("aop01.xml");
- Math math = context.getBean("math",Math.class);
- int n=100;
- int m=5;
- math.add(n,m);
- math.sub(n,m);
- math.mut(n,m);
- math.div(n,m);
二、使用注解配置AOP
1、创建代理类:Math2 ,类上注解了@Service并命名bean为math2。
代码:
- package com.wbg.springAOP.spring.annotation;
- import org.springframework.stereotype.Component;
- import org.springframework.stereotype.Service;
- import java.util.Random;
- /**
- * 被代理的目标类
- */
- @Service("math2")
- public class Math2 {
- //加
- public int add(int n1,int n2){
- //开始时间
- long start = getTime();
- delay();
- int result=n1+n2;
- System.out.println(n1+"+"+n2+"="+result);
- System.out.println("共用时:" + (getTime() - start));
- return result;
- }
- //减
- public int sub(int n1,int n2){
- //开始时间
- long start = getTime();
- delay();
- int result=n1*n2;
- System.out.println(n1+"-"+n2+"="+result);
- System.out.println("共用时:" + (getTime() - start));
- return result;
- }
- //乘
- public int mut(int n1,int n2){
- //开始时间
- long start = getTime();
- delay();
- int result=n1*n2;
- System.out.println(n1+"X"+n2+"="+result);
- System.out.println("共用时:" + (getTime() - start));
- return result;
- }
- //除
- public int div(int n1,int n2){
- //开始时间
- long start = getTime();
- delay();
- int result=n1/n2;
- System.out.println(n1+"/"+n2+"="+result);
- System.out.println("共用时:" + (getTime() - start));
- return result;
- }
- public static long getTime() {
- return System.currentTimeMillis();
- }
- public static void delay(){
- try {
- int n = (int) new Random().nextInt(500);
- Thread.sleep(n);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
2、创建Advices2类
@Component表示该类的实例会被Spring IOC容器管理
@Aspect表示声明一个切面
@Before表示before为前置通知,通过参数execution声明一个切点
代码:
execution(<修饰符模式>?<返回类型模式><方法名模式>(<参数模式>)<异常模式>?)切点函数,可以满足多数需求。
- package com.wbg.springAOP.spring.annotation;
- import org.aspectj.lang.JoinPoint;
- import org.aspectj.lang.annotation.After;
- import org.aspectj.lang.annotation.Aspect;
- import org.aspectj.lang.annotation.Before;
- import org.springframework.stereotype.Component;
- @Component
- @Aspect
- public class Advices2 {
- @Before("execution(* com.wbg.springAOP.spring.annotation.Math2.*(..))")
- public void before(JoinPoint joinPoint){
- System.out.println("----------前置通知----------");
- System.out.println(joinPoint.getSignature().getName());
- }
- @After("execution(* com.wbg.springAOP.spring.annotation.Math2.*(..))")
- public void after(JoinPoint joinPoint){
- System.out.println("----------最终通知----------");
- }
- }
3、创建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: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.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">
- <context:component-scan base-package="com.wbg.springAOP.spring.annotation"/>
- <!--
- 在配置IOC的基础上增加了aop:aspectj-autoproxy节点
- Spring框架会自动为与AspectJ切面配置的Bean创建代理
- proxy-target-class="true"属性表示被代理的目标对象是一个类
- 而非实现了接口的类,主要是为了选择不同的代理方式
- -->
- <aop:aspectj-autoproxy proxy-target-class="true"/>
- </beans>
4、测试
- ApplicationContext context = new ClassPathXmlApplicationContext("aop2.xml");
- Math2 math = context.getBean("math2",Math2.class);
- int n=100;
- int m=5;
- math.add(n,m);
- math.sub(n,m);
- math.mut(n,m);
- math.div(n,m);
使用Spring实现AOP(XML+注解)的更多相关文章
- Spring 中aop切面注解实现
spring中aop的注解实现方式简单实例 上篇中我们讲到spring的xml实现,这里我们讲讲使用注解如何实现aop呢.前面已经讲过aop的简单理解了,这里就不在赘述了. 注解方式实现aop我们 ...
- [Spring框架]Spring开发实例: XML+注解.
前言: 本文为自己学习Spring记录所用, 文章内容包括Spring的概述已经简单开发, 主要涉及IOC相关知识, 希望能够对新入门Spring的同学有帮助, 也希望大家一起讨论相关的知识. 一. ...
- spring中aop的注解实现方式简单实例
上篇中我们讲到spring的xml实现,这里我们讲讲使用注解如何实现aop呢.前面已经讲过aop的简单理解了,这里就不在赘述了. 注解方式实现aop我们主要分为如下几个步骤(自己整理的,有更好的方法的 ...
- spring框架aop用注解形式注入Aspect切面无效的问题解决
由于到最后我的项目还是有个邪门的错没解决,所以先把文章大概内容告知: 1.spring框架aop注解扫描默认是关闭的,得手动开启. 2.关于Con't call commit when autocom ...
- Spring 使用AOP——xml配置
目录 AOP介绍 Spring进行2种实现AOP的方式 导入jar包 基于schema-based方式实现AOP 创建前置通知 创建后置通知 修改Spring配置文件 基于schema-based方式 ...
- redis分布式锁-spring boot aop+自定义注解实现分布式锁
接这这一篇redis分布式锁-java实现末尾,实现aop+自定义注解 实现分布式锁 1.为什么需要 声明式的分布式锁 编程式分布式锁每次实现都要单独实现,但业务量大功能复杂时,使用编程式分布式锁无疑 ...
- 黑马Spring学习 AOP XML和注解配置 5种通知 切点切面通知织入
业务类 package cn.itcast.aop; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoin ...
- Spring 使用AOP——基于注解配置
首先,使用注解实现AOP是基于AspectJ方式的. 创建包含切点方法的类 package cn.ganlixin.test; import org.aspectj.lang.annotation.P ...
- 浅谈spring中AOP以及spring中AOP的注解方式
AOP(Aspect Oriented Programming):AOP的专业术语是"面向切面编程" 什么是面向切面编程,我的理解就是:在不修改源代码的情况下增强功能.好了,下面在 ...
随机推荐
- VirtualBox使用Centos7与主机共享文件夹
最近使用VitrtualBox安装Centos7学习,liunx脚本和一些命令,经过一些研究完成了虚拟机与 主机共享文件夹,虚拟机链接外部网络,主机与虚拟机互相通信.在其中遇到一些我解决的技术问题记录 ...
- JQuery的一些基础知识
JQuery的核心的一些方法 each(callback) '就像循环$("Element").length; ‘元素的个数,是个属性$("Element"). ...
- powerdesigner 将表中name列值复制到comment列 (保留原有comment)
/** * PowerDesigner里面将表中name列值复制到comment列 * @see --------------------------------------------------- ...
- iSCSI配置
iSCSI介绍 几种存储的架构: 直接存取 (direct-attached storage):例如本机上面的磁盘,就是直接存取设备: 透过储存局域网络 (SAN):来自网络内的其他储存设备提供的磁盘 ...
- JavaScript中实现DI的原理
什么是依赖注入 按照上面图的流程中我们可以知道我们需要实现这么几件事: 提供一个服务容器 为目标函数注册需要的依赖 获取目标函数注册的依赖项 通过依赖项来查询对应服务 将获取的依赖项传入目标函数 提供 ...
- 【创客+】偷心锁屏创始人Jerry创业心得分享
偷心锁屏创始人Jerry创业心得分享 作者:Jerry权泉,偷心锁屏创始人 我创业的起因非常偶然.08年在东京早稻田大学读博士期间,每周六都去社区活动中心跟日本人志愿者日语对话练习日语.有一次练习结束 ...
- Android Timer和TimerTask
以下内容根据 The JavaTM Tutorial 和相关API doc翻译整理,以供日后参考: 1.概览 Timer是一种定时器工具,用来在一个后台线程计划执行指定任务.它可以计划执行一个任务一次 ...
- 关于建立Android工程R文件丢失的问题
今天开始学习Android了,好久没打开eclipse,建立Android工程老是报错,于是手残的把appcompat-v7给删了,然后建立工程以后重新出来的appcompat-v7有个小叉号,百度了 ...
- webpack2-webpack.config.js配置
写在前面: 了解更多:https://github.com/miaowwwww/webpack-learn 贴一个webpack.ocnfig.js 的配置属性表 一.代码分割: 1.插件 Comm ...
- python爬虫系列:(一)、安装scrapy
1.安装python 下载好安装包,一路next安装即可 2.把python和pip加入环境变量. 我的电脑----->右键“属性”------>“高级系统设置”------->“环 ...