Spring AOP两种使用方式以及如何使用解析

AOP是一种面向切面编程思想,也是面向对象设计(OOP)的一种延伸。

在Spring实现AOP有两种实现方式,一种是采用JDK动态代理实现,另外一种就是采用CGLIB代理实现,Spring是如何实现的在上篇已经讲到了Spring Bean的生命周期以及IOC源码解析

AOP可以做日志记录,或者事务回滚,在Spring的事务使用就是通过AOP进行事务的回滚的

JDK动态代理

这个是属于JDK提供的一种代理方式,需提供接口才能使用,主要用的类有两个:1、Proxy:这个主要是生成接口代理对象;2、InvocationHandler:反射射包下的一个接口,Proxy生成的代理接口对象,调用接口方法就会走InvocationHandler实现类的invoke() 方法

 使用示例:

//创建一个接口
public class UserDao {String getUserInfo();
}
//实现一个InvocationHandler接口的实现类
public class MyInvocationHandler implements InvocationHandler {//需实现的方法//proxy 代表当前对象自己,建议不要使用,如果使用的话会反复的调用自己,而调用自己会反复走当前invoke方法,容易出现栈溢出;//method 指调用的方法Method;//args 调用方法的参数;@Overridepublic Object invoke(Object proxy, Method method, Object[] args){//....return null;}//获取接口代理对象public <T> T getProxy(CLass<T> cls){//第一个参数为类加载器,这个可以默认使用当前的AppClassLoader,即使用getClassLoader()方法接口//需创建代理对象的接口class数组,//invocationHandler的实现类对象,这里调用的是当前对象,调用的时候就会走当前对象的invoke方法return (E) Proxy.newProxyInstance(cls.getClassLoader(), new Class<?>[] {cls},this);}}public static void main(Stirng[] args){UserDao dao = new MyInvocationHandler().getProxy(UserDao.class);//这样就能获取到了UserDao接口的代理对象了
}

在Spring当中是采用 JdkDynamicAopProxy 这个类实现的,可以去源码里看一下这个类继承了InvocationHandler

CGLIB代理

这个代理就比较厉害了,是通过ASM修改 .class字节码进行实现的,并且不需要接口,具体的组成结构可以去看一下大佬写的这篇CGLIB(Code Generation Library)

使用示例:

        /*** CGLIB 代理*/Enhancer enhancer = new Enhancer();enhancer.setSuperclass(SpringTest06Service.class);enhancer.setCallback(new MethodInterceptor() {public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {System.out.println(Thread.currentThread().getName()+"run start...");Object result = arg3.invokeSuper(arg0, arg2);System.out.println(Thread.currentThread().getName()+"result:"+result);System.out.println(Thread.currentThread().getName()+"run end...");return result;}});service = (SpringTest06Service) enhancer.create();System.out.println(service);String testAop = service.testAop("aaaaaaaa", "bbbbbbbbbbb");System.out.println(testAop);

在Spring里面实现的类是 ObjenesisCglibAopProxy 

上面就是两种代理的实现方式,但是在Spring里面是怎么使用的呢

Spring使用AOP

需引入Spring相关的AOP的包

		<dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>5.1.12.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>5.1.12.RELEASE</version></dependency>

在配置类上需开启AOP进行方法拦截,@EnableAspectJAutoProxy 启动AOP代理,这个注解有两个参数

1、proxyTargetClass:这个是指定使用JDK动态代理拦截(false)还是使用CGLIB进行拦截(true),默认为false,

2、exposeProxy:表示是否能够让AopContext访问,默认为false就是不能访问。

源码是怎么解析可以自己去看,这个注解通过使用@Import注入了一个SmartInstantiationAwareBeanPostProcessor的实现类,可以自己调试查看,这里就不具体讲了,有空就在聊聊吧

最后配置相对应的切面拦截类

@Aspect
@Component
public class AopConfig {private static final Log log = LogFactory.getLog(AopConfig.class);//切点,需指定到具体修饰符,具体方法名以及具体参数类型,这里表示所有修饰符,com.test.SpringCoreTest.test06.service这个包下的所有类的所有方法并且参数为两个的类型为String的方法进行拦截@Pointcut("execution(* com.test.SpringCoreTest.test06.service.*.*(String,String))")public void pointCut() {}//执行前,位于Around环绕方法前的后面执行@Before(value = "pointCut()")public void before() {System.out.println("方法执行前 @Before ....");}//执行后,位于Around环绕方法后的后面执行@After(value = "pointCut()")public void after() {System.out.println("方法执行后 @After ....");}//即将返回执行@AfterReturning(value = "pointCut()")public void afterReturning() {System.out.println("方法执行后返回  @AfterReturning ....");}//抛出异常执行@AfterThrowing(value="pointCut()",throwing="e")public void afterThrowing(Exception e) {System.out.println("方法执行异常后返回  @AfterThrowing ....");System.out.println(e);}//环绕方法,能够拦截执行参数,并且能够修改@Around(value = "pointCut()")public Object around(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println("around方法执行前@Around ....");Object obj = joinPoint.proceed();System.out.println("around方法执行后@Around ....");return obj;}}

配置好后,调用拦截的方法就可以触发AOP拦截了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/537139.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何用python生成可执行程序必须经过_python怎么生成可执行文件

.py文件&#xff1a;对于开源项目或62616964757a686964616fe58685e5aeb931333363393664者源码没那么重要的&#xff0c;直接提供源码&#xff0c;需要使用者自行安装Python并且安装依赖的各种库。(Python官方的各种安装包就是这样做的).pyc文件&#xff1a;有些公司或个人因为机…

Jmeter 老司机带你一小时学会Jmeter

Jmeter的安装 官网下载地址&#xff1a;http://jmeter.apache.org/download_jmeter.cgi 作为Java应用&#xff0c;是需要JDK环境的&#xff0c;因此需要下载安装JAVA&#xff0c;并且作必要的的环境变量配置。 一、bin目录 examples:    目录中有CSV样例 jmeter.bat/jmeter…

MongoDB位运算基本使用以及位运算应用场景

最近在公司业务上用到了二进制匹配数据&#xff0c;但是MongoDB进行二进制运算&#xff08;Bitwise&#xff09;没用过&#xff0c;网上博客文章少&#xff0c;所以就上官网看API&#xff0c;因此记录一下&#xff0c;顺便在普及一下使用二进制位运算的一些应用。 在MongoDB的…

好用的下拉第三方——nicespinner

1.简介 GitHub地址&#xff1a;https://github.com/arcadefire/nice-spinner Gradle中添加&#xff1a; allprojects {repositories {...maven { url "https://jitpack.io" }} }dependencies {implementation com.github.arcadefire:nice-spinner:1.3.7 }2.使用 xml文…

Mybatis配置文件参数定义

官网有时候进不去&#xff0c;所以就记录一下Mybatis的配置文件的各项参数定义&#xff0c;大家也可以上官网查询&#xff0c;官方文档&#xff0c;进不进的去看各自的缘分了 properties 定义配置&#xff0c;在这里配置的属性可以在整个配置文件使用&#xff1b;可以加载指定…

python和java后期发展_Python与java的发展前景谁最大

Python和Java是目前IT行业内两大编程语言&#xff0c;很多人都喜欢拿来比较&#xff0c;一个是后起之秀&#xff0c;潜力无限&#xff1b;一个是行业经典&#xff0c;成熟稳定。对于许多想从事IT行业的同学来说&#xff0c;这两门语言真的很难抉择。那么&#xff0c;Python和Ja…

JDK源码学习笔记——Enum枚举使用及原理

一、为什么使用枚举 什么时候应该使用枚举呢&#xff1f;每当需要一组固定的常量的时候&#xff0c;如一周的天数、一年四季等。或者是在我们编译前就知道其包含的所有值的集合。 利用 public final static 完全可以实现的功能&#xff0c;为什么要使用枚举&#xff1f; public…

Mybatis源码日志模块分析

看源码需要先下载源码&#xff0c;可以去Mybatis的github上的仓库进行下载&#xff0c;Mybatis 这次就先整理一下日志这一块的源码分析&#xff0c;这块相对来说比较简单而且这个模块是Mybatis的基础模块。 之前的文章有谈到过Java的日志实现&#xff0c;大家也可以参考一下&…

python手机端给电脑端发送数据_期货交易软件有哪些比较好用?分手机端和电脑端...

一、电脑端交易软件期货电脑端交易软件目前市场上用的最多的是文华财经和博易大师&#xff0c;这两个软件都是免费交易使用的。从投资者使用角度来看&#xff0c;目前电脑端文华财经的评价比博易大师高一些。当然每个投资者有自己的使用习惯&#xff0c;博易大师也有自己优点&a…

Find the Difference(leetcode389)

2019独角兽企业重金招聘Python工程师标准>>> Given two strings s and t which consist of only lowercase letters. String t is generated by random shuffling string s and then add one more letter at a random position. Find the letter that was added in …

Mybatis源码之数据源模块分析

先来看看java纯jdbc查询数据的示例&#xff1a; try {//加载对应的驱动类Class.forName("com.mysql.cj.jdbc.Driver");//创建连接Connection connection DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test?serverTimezoneUTC", "roo…

reactnative 获取定位_[RN] React Native 获取地理位置

import React, {Component} from react;import {StyleSheet, Text, View}from react-native;exportdefault classTestGeo extends Component {state{longitude:,//经度latitude: ,//纬度city: ,district:,street:,position:,//位置名称};componentWillMount () >{this.getPo…

第二冲刺阶段第三天

查阅资料&#xff0c;修改控件界面转载于:https://www.cnblogs.com/gyy0/p/10066452.html

Mybatis源码之缓存模块分析

缓存这个东西在很多应用中都能看到它们的身影&#xff0c;这次就讲讲在Mybatis中的缓存是怎么应用的&#xff0c;虽然说吧Mybatis中的缓存基本不怎么用&#xff0c;用的更多是第三方组件redis、MongoDB、MemCache等等。 Mybatis的缓存是基于Map实现的&#xff0c;从缓存中读写…

Mybatis源码之核心流程分析

终于谈到了Mybatis最核心的东西了&#xff0c;最核心的就是通过配置XML文件或注解中的SQL&#xff0c;直接调用接口就能执行配置好的SQL语句并封装成对应的返回类型的数据。 先看一下Mybatis使用示例&#xff1a; //创建Builder对象 SqlSessionFactoryBuilder builder new S…

mimakatz用法_两步完成利用procdump64+mimikatz获取win用户密码

使用procdump64mimikatz可实现从内存中获取明文密码工具链接&#xff1a;https://pan.baidu.com/s/1gNc9qLcNSNBohIVrAiqShw 密码&#xff1a;fc38首先得先获取到内存文件lsass.exe进程, 它用于本地安全和登陆策略,一般在进程管理器中能看到, 比如这样1.导出lsass.exeprocdump6…

ios app提交之前需要哪几个证书

1、遇到的问题 一款App在别人的机器上开发和发布&#xff0c;现在迭代更新和开发需要在一台新mac机上开发和发布。&#xff08;使用同一个开发者账号&#xff09;问题&#xff1a; 1.在新mac机器上开发并导入真机测试&#xff0c;是不是需要从别人的机器上面导处开发者证书、开…

Mybatis源码之与Spring集成包

这次讲讲Mybatis与Spring的整合&#xff0c;作为两款优秀的开源框架&#xff0c;被大众广泛使用&#xff0c;自然是需要强强联合的。 使用示例 先看一下怎么使用&#xff0c;首先需要引用这两款框架的jar包&#xff1a; <dependency>//spring-webmvc会自动去引入其他S…

hadoop主节点切换_hadoop2.0 HA的主备自动切换

在《hadoop2.0 QJM方式的HA的配置》一文中介绍了HA的配置&#xff0c;是通过手工进行主备切换的。本文在这基础上&#xff0c;继续介绍HA的主备自动切换(automatic failover)的配置。自动切换是通过配置zookeeper来实现的&#xff0c;关于zookeeper的安装和配置&#xff0c;在这…

Mybatis源码之插件模块分析

总结完这个Mybatis的整体主要功能基本上就差不多完&#xff0c;还有一些细节的部分&#xff0c;后续都会记录补充。 插件这个东西一般用的比较少&#xff0c;就算用的多的插件也算是PageHelper分页插件&#xff1b; PageHelper官网&#xff1a;https://github.com/pagehelper…