問題描述:
在使用springaop對目標對象增強時,若切點的條件過於寬泛就會出現以下異常!
如:
@Before("execution(* *(..))")
@Before("args(..)")
@Before("within(org..*)")
...
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.boot.autoconfigure.AutoConfigurationPackages': Initialization of bean failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class org.springframework.boot.autoconfigure.AutoConfigurationPackages$BasePackages]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class org.springframework.boot.autoconfigure.AutoConfigurationPackages$BasePackages at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:564) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:120) at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) ... 26 common frames omitted Caused by: org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class org.springframework.boot.autoconfigure.AutoConfigurationPackages$BasePackages]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class org.springframework.boot.autoconfigure.AutoConfigurationPackages$BasePackages at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:211) at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:109) at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:466) at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:349) at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:298) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:423) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1634) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555) ... 40 common frames omitted Caused by: java.lang.IllegalArgumentException: Cannot subclass final class org.springframework.boot.autoconfigure.AutoConfigurationPackages$BasePackages at org.springframework.cglib.proxy.Enhancer.generateClass(Enhancer.java:565) at org.springframework.cglib.transform.TransformingClassGenerator.generateClass(TransformingClassGenerator.java:33) at org.springframework.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25) at org.springframework.aop.framework.CglibAopProxy$ClassLoaderAwareUndeclaredThrowableStrategy.generate(CglibAopProxy.java:999) at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:329) at org.springframework.cglib.proxy.Enhancer.generate(Enhancer.java:492) at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:93) at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:91) at org.springframework.cglib.core.internal.LoadingCache$2.call(LoadingCache.java:54) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at org.springframework.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:61) at org.springframework.cglib.core.internal.LoadingCache.get(LoadingCache.java:34) at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:116) at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:291) at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:480) at org.springframework.cglib.proxy.Enhancer.createClass(Enhancer.java:337) at org.springframework.aop.framework.ObjenesisCglibAopProxy.createProxyClassAndInstance(ObjenesisCglibAopProxy.java:55) at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:201) ... 47 common frames omitted
問題分析:
通過異常信息可以看出,當spring通過cglib給目標對象org.springframework.boot.autoconfigure.AutoConfigurationPackages$BasePackages進行增強時,發生了異常。
原因:
1)cglib增強技術,是通過繼承原對象后動態創建子類來實現的。
2)通過查看BasePackages類源代碼,發現該類被final修飾。
static final class BasePackages { ... }
3)java不允許繼承被final所修飾的類。
解決方法:
以上問題出現的原因為aop定義的切點條件中,包含了被final所修飾的類。
1)通過修改類的訪問修飾符解決。
2)通過調整切點條件,過濾final修飾的類。