【问题标题】:Issue with Spring AOP and Final class throwing "Could not generate CGLIB subclass"Spring AOP 和 Final 类抛出“无法生成 CGLIB 子类”的问题
【发布时间】:2018-10-15 07:47:02
【问题描述】:

1) 下面是我想要使用 SpringAOP 进行日志记录的小项目。使用 spring-aop-4.1.6.RELEASE.jar 及以下是 LoggingAspect.java,有一些切入点。

package com.myprj.aop.aspect;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect {
    private final Log log = LogFactory.getLog(getClass());

    @Before("logForAllMethods()") // after advice with name pointcut that declared as name logForAllMethods()
    public void beforeAdviceForAllMethods(JoinPoint jp) throws Throwable {
        Object clazz = jp.getTarget().getClass().getName();
        String methodName = jp.getSignature().getName();
        log.info("Before Entering to Class " + clazz + " With Method Name " + methodName);
        // getting method parameter name
        Object[] obj = jp.getArgs();
        for (Object o : obj) {
            if (o != null) {
                log.info("Parameter Name..." + o.toString());
            } else {
                log.info("");
            }
        }

    }

    @After("logForAllMethods()") // after advice with name pointcut that declared as name logForAllMethods()
    public void afterAdviceForAllMethods(JoinPoint jp) throws Throwable {
        Object clazz = jp.getTarget().getClass().getName();
        String methodName = jp.getSignature().getName();
        log.info("After Entring to Method " + methodName + " in Calss " + clazz);
    }

    @Pointcut("execution(public * *(..))")      // enable for all public methods
    public void logForAllMethods() {
    }
}

下面还有我的示例 Service 和 ServiceImpl 类

package com.myprj.aop.service;

public interface TransferService {

    void transfer(String accountA, String accountB, Long amount);

    Double checkBalance(String account);

    Long withdrawal(String account, Long amount);

    void diposite(String account, Long amount);
}


package com.myprj.aop.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

@Service
public class TransferServiceImpl implements TransferService {

    @Autowired
    @Qualifier("finalClass")
    FinalClass finalClass;

    @Override
    public void transfer(String accountA, String accountB, Long amount) {
        System.out.println(amount + " Amount has been tranfered from " + accountA + " to " + accountB);
    }

    @Override
    public Double checkBalance(String account) {
        System.out.println("Available balance: 50000");
        finalClass.toString();
        return new Double(50000);
    }

    @Override
    public Long withdrawal(String account, Long amount) {
        System.out.println("Withdrawal amount: " + amount);
        finalClass.toString();
        return amount;
    }

    @Override
    public void diposite(String account, Long amount) {
        System.out.println(amount + " Amount has been diposited to " + account);
        finalClass.toString();
    }

}

另外,我有一个 Singleton 类,其中需要调用的方法很少,如下所示。

package com.myprj.aop.service;

public class FinalClass {

    private String constructorParam;

    private FinalClass(String param) {
        constructorParam = param;
    }

    @Override
    public String toString() {
        System.out.println(constructorParam);
        return constructorParam;
    }
}

下面是applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/util
        http://www.springframework.org/schema/util/spring-util.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
    <context:component-scan base-package="com.myprj.aop.*" />       
    <bean id="finalClass" class="com.myprj.aop.service.FinalClass">
        <constructor-arg value="constructorArg"></constructor-arg>
    </bean>
    <aop:aspectj-autoproxy/>    
</beans>

主类:

package com.myprj.aop.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.myprj.aop.config.AppConfig;
import com.myprj.aop.service.TransferService;


public class Main {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // ConfigurableApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        TransferService transferService = applicationContext.getBean(TransferService.class);
        transferService.transfer("accountA", "accountB", 50000l);
        transferService.checkBalance("accountA");
        transferService.diposite("accountA", 50000l);
        transferService.withdrawal("accountB", 40000l);
        //applicationContext.close();
    }

}

得到以下错误

WARNING: Exception encountered during context initialization - cancelling refresh attempt
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transferServiceImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.myprj.aop.service.FinalClass com.myprj.aop.service.TransferServiceImpl.finalClass; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'finalClass' defined in class path resource [applicationContext.xml]: Initialization of bean failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.myprj.aop.service.FinalClass]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: No visible constructors in class com.myprj.aop.service.FinalClass
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1210)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:755)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
    at com.myprj.aop.test.Main.main(Main.java:19)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.myprj.aop.service.FinalClass com.myprj.aop.service.TransferServiceImpl.finalClass; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'finalClass' defined in class path resource [applicationContext.xml]: Initialization of bean failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.myprj.aop.service.FinalClass]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: No visible constructors in class com.myprj.aop.service.FinalClass
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:561)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
    ... 13 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'finalClass' defined in class path resource [applicationContext.xml]: Initialization of bean failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.myprj.aop.service.FinalClass]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: No visible constructors in class com.myprj.aop.service.FinalClass
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:547)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1120)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1044)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:942)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:533)
    ... 15 more
Caused by: org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.myprj.aop.service.FinalClass]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: No visible constructors in class com.myprj.aop.service.FinalClass
    at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:212)
    at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:109)
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:447)
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:333)
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:293)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:422)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1579)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
    ... 24 more
Caused by: java.lang.IllegalArgumentException: No visible constructors in class com.myprj.aop.service.FinalClass
    at org.springframework.cglib.proxy.Enhancer.filterConstructors(Enhancer.java:531)
    at org.springframework.cglib.proxy.Enhancer.generateClass(Enhancer.java:448)
    at org.springframework.cglib.transform.TransformingClassGenerator.generateClass(TransformingClassGenerator.java:33)
    at org.springframework.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
    at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216)
    at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)
    at org.springframework.cglib.proxy.Enhancer.createClass(Enhancer.java:317)
    at org.springframework.aop.framework.ObjenesisCglibAopProxy.createProxyClassAndInstance(ObjenesisCglibAopProxy.java:57)
    at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:202)
    ... 31 more

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transferServiceImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.myprj.aop.service.FinalClass com.myprj.aop.service.TransferServiceImpl.finalClass; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'finalClass' defined in class path resource [applicationContext.xml]: Initialization of bean failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.myprj.aop.service.FinalClass]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: No visible constructors in class com.myprj.aop.service.FinalClass
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1210)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:755)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
    at com.myprj.aop.test.Main.main(Main.java:19)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.myprj.aop.service.FinalClass com.myprj.aop.service.TransferServiceImpl.finalClass; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'finalClass' defined in class path resource [applicationContext.xml]: Initialization of bean failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.myprj.aop.service.FinalClass]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: No visible constructors in class com.myprj.aop.service.FinalClass
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:561)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
    ... 13 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'finalClass' defined in class path resource [applicationContext.xml]: Initialization of bean failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.myprj.aop.service.FinalClass]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: No visible constructors in class com.myprj.aop.service.FinalClass
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:547)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1120)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1044)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:942)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:533)
    ... 15 more
Caused by: org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.myprj.aop.service.FinalClass]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: No visible constructors in class com.myprj.aop.service.FinalClass
    at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:212)
    at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:109)
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:447)
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:333)
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:293)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:422)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1579)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
    ... 24 more
Caused by: java.lang.IllegalArgumentException: No visible constructors in class com.myprj.aop.service.FinalClass
    at org.springframework.cglib.proxy.Enhancer.filterConstructors(Enhancer.java:531)
    at org.springframework.cglib.proxy.Enhancer.generateClass(Enhancer.java:448)
    at org.springframework.cglib.transform.TransformingClassGenerator.generateClass(TransformingClassGenerator.java:33)
    at org.springframework.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
    at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216)
    at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)
    at org.springframework.cglib.proxy.Enhancer.createClass(Enhancer.java:317)
    at org.springframework.aop.framework.ObjenesisCglibAopProxy.createProxyClassAndInstance(ObjenesisCglibAopProxy.java:57)
    at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:202)
    ... 31 more

inject 注入失败。谷歌搜索后,许多人建议使用基于 setter 的注入。但是当创建单例类时,更多的操作是在实际代码中完成的。同样根据下面的链接,这已在Spring 4.0 中修复。我的代码有什么问题?

【问题讨论】:

  • 我给你一个提示:IllegalArgumentException: No visible constructors in class com.myprj.aop.service.FinalClass*private* FinalClass(String param) {
  • 嗨@zapl,谢谢,我的要求是单例 FinalClass 类不会有公共构造函数。所以要注入它,在 applicationContext.xml 中创建 bean,并且需要在所有其他地方使用该合格的 bean。如果我添加一个公共构造函数,那么它将无法满足单例的目的。对吗?
  • 构造函数的可见性在没有其他人使用时是无关紧要的。 Spring 只会使用一次,因此在整个应用程序中提供一个实例。你也可以使用protected 构造函数,因为stackoverflow.com/questions/3952815/… 会发生
  • 请阅读Under what circumstances may I add “urgent” or other similar phrases to my question, in order to obtain faster answers? - 总结是,这不是解决志愿者的理想方式,并且可能会适得其反。请不要将此添加到您的问题中。
  • @zapl,我找到了另一种解决方法来解决这个问题,我使用 && !within(Singleton class) 被注入并编织到我的 LoggingAspect.java 中。因此,我将在该文件中进行显式登录。感谢您的建议。

标签: java spring spring-aop spring-bean


【解决方案1】:

正如你的例外所说的那样

No visible constructors in class com.myprj.aop.service.FinalClass

将您的私有构造函数更改为公共。

【讨论】:

    【解决方案2】:

    它会告诉您问题所在:No visible constructors in class com.myprj.aop.service.FinalClass

    spring 无法“猜测”调用哪个静态 getInstance() 方法来实例化单例。
    您必须为它提供一个公共的空 c'tor。

    如果您在应用程序中使用 spring,您可以使用 @Scope 属性将 FinalClass 定义为单例。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-09
      • 2015-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多