本文主要是介绍在spring中使用bytebuddy 对bean做Aop拦截,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
背景
拦截spring 中的某个bean拦截其方法的调用。在其前后做一些类似于aop的操作
拦截bean
- MyBeanDefinitionRegistryPostProcessor
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
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
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");}
}
- 测试
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'
- 总结
- 可以拦截其中的任意方法。在其前后做一些事情
这篇关于在spring中使用bytebuddy 对bean做Aop拦截的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!