Kotlin之SpringBoot2.0 Aop使用注意事项

牧云@^-^@ 提交于 2020-12-13 19:33:26

遇到的问题 what

新公司的项目使用Kotlin+SpringBoot作为后台架构,开发中出现了AOP日志切面不生效的问题

为什么会这样 why

  1. @Aspect注解的切面类没有初始化到IOC容器中,即没有声明为组件
  2. SpringBoot2.0的AOP代理有三种策略,启动时的AutoConfig配置类是使用CGLIB进行代理,即matchIfMissing=true,spring.aop.proxy-target-class配置项缺失时
  3. Kotlin生成的类和方法如果前缀没有open关键字,编译成字节码文件时会带上final关键字即类不可继承、方法不可重写
  4. CGLIB使用ASM字节码技术进行字节码植入,运行时生成目标类的子类来实现代理,所有如果目标类不可继承、方法不可重写、就无法被cglib代理
有3种,前提均开启spring.aop.auto=true; 
1. jdk动态代理:当spring.aop.proxy-target-class=false, 引入了aspectjweaver依赖时生效
2. cglib代理:当spring.aop.proxy-target-class=true, 引入了aspectjweaver依赖时生效
3. 基础代理:当spring.aop.proxy-target-class=true, 若没有aspectjweaver依赖时生效,只作用于框架内部的advisors

@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {

	@Configuration(proxyBeanMethods = false)
	@ConditionalOnClass(Advice.class)
	static class AspectJAutoProxyingConfiguration {

		@Configuration(proxyBeanMethods = false)
		@EnableAspectJAutoProxy(proxyTargetClass = false)
		@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false",
				matchIfMissing = false)
		static class JdkDynamicAutoProxyConfiguration {

		}

		@Configuration(proxyBeanMethods = false)
		@EnableAspectJAutoProxy(proxyTargetClass = true)
		@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
				matchIfMissing = true)
		static class CglibAutoProxyConfiguration {

		}

	}

	@Configuration(proxyBeanMethods = false)
	@ConditionalOnMissingClass("org.aspectj.weaver.Advice")
	@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
			matchIfMissing = true)
	static class ClassProxyingConfiguration {

		ClassProxyingConfiguration(BeanFactory beanFactory) {
			if (beanFactory instanceof BeanDefinitionRegistry) {
				BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
				AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
				AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
			}
		}

	}
}

解决办法 how

  1. 切面类声明为组件,启动时被扫描进IOC容器。或者在Configuration配置类中使用@Bean生成切面类实例
  2. 在默认使用cglib代理的情况下,被AOP横切的类及方法需要加上open关键字
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!