在spring中使用bytebuddy 对bean做Aop拦截

devtools/2024/9/22 13:11:00/

背景

拦截spring 中的某个bean拦截其方法的调用。在其前后做一些类似于aop的操作

拦截bean

  • MyBeanDefinitionRegistryPostProcessor
java">import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.asm.Advice;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.returns;/*** @author wxl*/
@Slf4j
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {@Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {boolean userService = registry.containsBeanDefinition("userService");if (userService) {registry.removeBeanDefinition("userService");Class<? extends UserService> method02 = new ByteBuddy().subclass(UserService.class).method(named("method02").and(returns(String.class))).intercept(Advice.to(LoggerAdvisor.class)).make().load(getClass().getClassLoader()).getLoaded();BeanDefinition beanDefinitions = BeanDefinitionBuilder.rootBeanDefinition(method02).getBeanDefinition();beanDefinitions.setAutowireCandidate(true);registry.registerBeanDefinition("userService", beanDefinitions);}}}
  • LoggerAdvisor
java">import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.asm.Advice;import java.lang.reflect.Method;
import java.util.Arrays;/*** @author wxl*/
@Slf4j
public class LoggerAdvisor {@Advice.OnMethodEnterpublic static void onMethodEnter(@Advice.Origin Method method, @Advice.AllArguments Object[] arguments) {System.out.println("Enter " + method.getName() + " with arguments: " + Arrays.toString(arguments));}@Advice.OnMethodExitpublic static void onMethodExit(@Advice.Origin Method method, @Advice.AllArguments Object[] arguments, @Advice.Return Object ret) {System.out.println("Exit " + method.getName() + " with arguments: " + Arrays.toString(arguments) + " return: " + ret);}
}
  • BeanB
java">
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;/*** @author wxl*/
@Component
public class BeanB {@Autowiredprivate UserService userService;public void test() {System.out.println("beanB");userService.method02("ss");}
}
  • 测试
java">import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;/*** @author wxl*/
@Slf4j
@SpringBootApplication
public class SpringBytecodeDemoApplication {public static void main(String[] args) throws Exception {
//        ClassPool pool = ClassPool.getDefault();
//        CtClass cc = pool.get("cc.sofast.demo.springbytecodedemo.UserService");
//        cc.defrost();
//        CtMethod m = cc.getDeclaredMethod("say");
//        m.insertBefore("{ System.out.println(\"Hello.say():\"); }");
//        m.insertAfter("{ System.out.println(\"result: \"+$_); }");
//        cc.writeFile(".");
//        cc.toClass();
//        ByteBuddyAgent.install();
//
//        new ByteBuddy()
//                .redefine(UserService.class)
//                .method(named("method02").and(returns(String.class)))
//                .intercept(to(new OvUserService()))
//                .make()
//                .load(UserService.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent());ConfigurableApplicationContext context = SpringApplication.run(SpringBytecodeDemoApplication.class, args);BeanB bean = context.getBean(BeanB.class);bean.test();}@Beanpublic MyBeanDefinitionRegistryPostProcessor myBeanDefinitionRegistryPostProcessor() {return new MyBeanDefinitionRegistryPostProcessor();}}
  • build.gradle
    implementation 'org.javassist:javassist:3.30.2-GA'implementation 'net.bytebuddy:byte-buddy:1.14.14'implementation 'net.bytebuddy:byte-buddy-agent:1.14.14'
  • 总结
    • 可以拦截其中的任意方法。在其前后做一些事情

http://www.ppmy.cn/devtools/39167.html

相关文章

题目----力扣--移除链表元素

题目 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,6,3,4,5,6], val 6 输出&#xff1a;[1,2,3,4,5]示例 2&#xff1a; 输入&…

【动态规划】子序列问题

最长上升子序列 题目描述&#xff1a; 解题思路&#xff1a; 核心思路&#xff1a; 用f[i]:表示以第i个数结尾的最大子序列&#xff0c;只需要找到比第i个小的最大子序列再加上1 即可&#xff1b; ----> f[i]max(f[j]1,f[i]); 定义 f[i] 表示以第 i 个元素结尾的最长上升子…

QT:QT窗口(二)

文章目录 浮动窗口浮动窗口的构建设置停靠的位置设置窗口只能停靠在上下 对话框对话框介绍通过一个按钮来创建一个对话框 自定义对话框纯代码实现图形化界面实现 对话框分类模态对话框 QT内置对话框QMessageBox 文件对话框 浮动窗口 在QT中&#xff0c;浮动窗口也叫做是铆接部…

华大基因CEPO-尹烨说学习与生活

怎么去面对生活和事业中的不确定性&#xff1f; 尹烨说&#xff0c;人类能够对抗不确定性的唯一的办法是&#xff0c;去让自己充电。 主持人问他&#xff0c;“和你同年的也有很多人&#xff0c;他们也可能也在学习&#xff0c;你怎么就能够脱颖而出呢&#xff1f;” 他说&am…

【数据库原理及应用】期末复习汇总高校期末真题试卷08

试卷 一、选择题(每题 2 分&#xff0c;共 30 分)    1. ___ ____是长期存储在计算机内的有组织,可共享的数据集合. A.数据库管理系统 B.数据库系统 C.数据库 D.文件组织 2. 数据库类型是按照 来划分…

IF:23.2|从实验室到田间,微生物干预提高植物抗逆

期刊&#xff1a;Nature Food 影响因子&#xff1a;23.2 发表时间&#xff1a;2023年10月 本研究介绍了一种名为SynCom的微生物组合&#xff0c;该组合Rhodococcus erythropolis和Pseudomonas aeruginosa两种微生物组成。这两种微生物能够帮助水稻抵抗铝毒害和磷缺乏&…

我们应该如何做参与式观察

记得多年以前&#xff0c;有个朋友问我&#xff1a;对于做观察&#xff0c;有人通过教授绘画技巧来教人如何做观察。你们研究员又不会画画&#xff0c;你们如何让人相信你们更会观察呢&#xff1f;坦率说&#xff0c;当时我被问住了&#xff0c;因为我从来没有进行过这样的对比…

15:00面试,15:06就出来了,问的问题有点变态。。。

从小厂出来&#xff0c;没想到在另一家公司又寄了。 到这家公司开始上班&#xff0c;加班是每天必不可少的&#xff0c;看在钱给的比较多的份上&#xff0c;就不太计较了。没想到3月一纸通知&#xff0c;所有人不准加班&#xff0c;加班费不仅没有了&#xff0c;薪资还要降40%…