【问题标题】:SpringMVC Proxy issueSpringMVC 代理问题
【发布时间】:2013-12-02 12:29:00
【问题描述】:

我这几天一直在寻找这个问题的答案,我希望有人能指出我正确的方向。我有一个使用 Java 配置的 SpringMVC 应用程序,在我尝试将 Apache-Shiro 集成到其中之前我做得很好。我能够构建和运行我的测试。但是由于代理/CGLIB 问题,我的部署失败了。

这是我在部署/重启时遇到的异常:

 Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'menuRepository': Post-processing of the FactoryBean's object failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.sun.proxy.$Proxy69]: 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 class com.sun.proxy.$Proxy69
        at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:165)
        at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:102)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1454)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:306)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:198)
        at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:442)
        at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:416)
        at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:550)
        at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:150)
        at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
        at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:303)
        ... 55 more
        Caused by: org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.sun.proxy.$Proxy69]: 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 class com.sun.proxy.$Proxy69
            at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:217)
            at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:111)
            at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:477)
            at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:362)
            at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:322)
            at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:409)
            at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.postProcessObjectFromFactoryBean(AbstractAutowireCapableBeanFactory.java:1625)
            at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:162)
            ... 65 more
        Caused by: java.lang.IllegalArgumentException: Cannot subclass final class class com.sun.proxy.$Proxy69
            at org.springframework.cglib.proxy.Enhancer.generateClass(Enhancer.java:446)
            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.create(Enhancer.java:285)
            at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:205)
            ... 72 more

这是我目前的设置:

pom.xml

<org.springframework.version>3.2.3.RELEASE</org.springframework.version>
<shiro.version>1.2.2</shiro.version>
<org.hibernate.version>4.1.7.Final</org.hibernate.version>

<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>3.2.3.RELEASE</version>
            <exclusions>
                <exclusion>
                    <artifactId>commons-logging</artifactId>
                    <groupId>commons-logging</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>3.2.3.RELEASE</version>
            <exclusions>
                <!-- Exclude Commons Logging in favor of SLF4j -->
                <exclusion>
                    <groupId>commons-logging</groupId>
                    <artifactId>commons-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>3.2.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>$3.2.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>3.2.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>3.2.3.RELEASE</version>
        </dependency>
          <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>2.2</version>
        </dependency>
 <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>${shiro.version}</version>
        </dependency>

        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-web</artifactId>
            <version>${shiro.version}</version>
        </dependency>
        <!--<dependency>-->
            <!--<groupId>org.apache.shiro</groupId>-->
            <!--<artifactId>shiro-aspectj</artifactId>-->
            <!--<version>${shiro.version}</version>-->
        <!--</dependency>-->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.6.11</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.6.12</version>
        </dependency>

        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-ehcache</artifactId>
            <version>${shiro.version}</version>
        </dependency>

        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>${shiro.version}</version>
            </dependency>
<dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-jpa</artifactId>
            <version>1.0.3.RELEASE</version>
        </dependency>
<dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>${org.hibernate.version}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>${org.hibernate.version}</version>
        </dependency>
        <!-- Hibernate metamodel annotation processor -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-jpamodelgen</artifactId>
            <version>1.1.1.Final</version>
        </dependency>
...
</>

我使用这个网络配置:

public class EdmWebInitializer implements WebApplicationInitializer {

    private static final String DISPATCHER_SERVLET_NAME = "dispatcher";
    private static final String DISPATCHER_SERVLET_MAPPING = "/*";

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {

        // Create the 'root' Spring application context
        AnnotationConfigWebApplicationContext rootContext = new 
AnnotationConfigWebApplicationContext();

       //I have two @Configuration classes:
       rootContext.register( EdmConfiguration.class, SecurityConfig.class );

        // Manage the lifecycle of the root application context
        servletContext.addListener( new ContextLoaderListener( rootContext ) );


        // Create the dispatcher servlet's Spring application context
        AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext();
        dispatcherContext.setServletContext( servletContext );
        dispatcherContext.setParent( rootContext );

        // it seems I have to register the Configuration classes again or I can't @Autowire
         dispatcherContext.register( EdmConfiguration.class, SecurityConfig.class );



        // Register and map the dispatcher servlet
        ServletRegistration.Dynamic dispatcher = servletContext.addServlet( "dispatcher", new DispatcherServlet( dispatcherContext ) );
        dispatcher.setLoadOnStartup( 1 );
        dispatcher.addMapping( "/" );


        servletContext.addFilter( "shiroFilter", new DelegatingFilterProxy( "shiroFilter", dispatcherContext ) )
                .addMappingForUrlPatterns( null, false, "/*" );
    }  
}

这是我的主要配置类:

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = { "com.company.product.service", "com.company.product.utility",
        "com.company.product.controller", "com.company.product.utility.startup",
        "com.company.product.security", "com.company.product.repository.people" })
@EnableTransactionManagement(proxyTargetClass=false)
@ImportResource({ "classpath:applicationContext.xml" })
@PropertySource({ "classpath:application.properties", "classpath:mail.properties" })
public class EdmConfiguration extends WebMvcConfigurationSupport {

    @Resource
    private Environment environment;

    @Autowired
    private org.apache.shiro.web.mgt.WebSecurityManager securityManager;

    @Bean
    public DataSource dataSource() {
        BoneCPDataSource dataSource = new BoneCPDataSource();

        dataSource.setDriverClass( environment.getRequiredProperty( PROPERTY_NAME_DATABASE_DRIVER ) );
        dataSource.setJdbcUrl( environment.getRequiredProperty( PROPERTY_NAME_DATABASE_URL ) );
        dataSource.setUsername( environment.getRequiredProperty( PROPERTY_NAME_DATABASE_USERNAME ) );
        dataSource.setPassword( environment.getRequiredProperty( PROPERTY_NAME_DATABASE_PASSWORD ) );

        return dataSource;
    }

    @Bean
    public JpaTransactionManager transactionManager() throws ClassNotFoundException {
        JpaTransactionManager transactionManager = new JpaTransactionManager();

        transactionManager.setEntityManagerFactory( entityManagerFactoryBean().getObject() );

        return transactionManager;
    }

    @Bean
    public DelegatingFilterProxy springSecurityFilterChain() {
        return new DelegatingFilterProxy();
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() throws ClassNotFoundException {
        LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();

        entityManagerFactoryBean.setDataSource( dataSource() );
        entityManagerFactoryBean.setPackagesToScan( environment
                .getRequiredProperty( PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN ) );
        entityManagerFactoryBean.setPersistenceProviderClass( HibernatePersistence.class );

        Properties jpaProperties = new Properties();

        ...

        entityManagerFactoryBean.setJpaProperties( jpaProperties );

        return entityManagerFactoryBean;
    }

    @Bean
    public PersistenceExceptionTranslator exTranslator() {
        return new HibernateExceptionTranslator();
    }

    @Bean(initMethod = "init")
    public StartupListener startupListener() {
        return new StartupListener();
    }

    @Bean
    public StandardPasswordEncoder encoder() {
        return new org.springframework.security.crypto.password.StandardPasswordEncoder();
    }


    @Bean
    public ShiroFilterFactoryBean shiroFilter() {
        ShiroFilterFactoryBean shiroFilter = new org.apache.shiro.spring.web.ShiroFilterFactoryBean();
        shiroFilter.setSecurityManager( securityManager);
        shiroFilter.setLoginUrl( "/login" );
        shiroFilter.setUnauthorizedUrl( "/" );
        return shiroFilter;
    }



    @Bean
    @DependsOn(value = "lifecycleBeanPostProcessor")
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
        creator.setProxyTargetClass(true);
        return creator;
    }
}

这是另一个配置类。正是添加这个会导致代理问题。

@Configuration
public class SecurityConfig {

    @Bean
    public SaltAwareJdbcRealm saltAwareJdbcRealm() {
        return new SaltAwareJdbcRealm();
    }

    @Bean
    public WebSecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm( saltAwareJdbcRealm() );
        return securityManager;
    }

    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    @Bean
    public MethodInvokingFactoryBean methodInvokingFactoryBean() {
        MethodInvokingFactoryBean methodInvokingFactoryBean = new MethodInvokingFactoryBean();
        methodInvokingFactoryBean.setStaticMethod( "org.apache.shiro.SecurityUtils.setSecurityManager" );
        methodInvokingFactoryBean.setArguments( new Object[]{ securityManager() } );
        return methodInvokingFactoryBean;
    }

    @Bean
    @DependsOn(value = "lifecycleBeanPostProcessor")
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authori

zationAttributeSourceAdvisor.setSecurityManager( securityManager() );
            return authorizationAttributeSourceAdvisor;
        }       
    }

违规类只是一个spring jparepository:

public interface MenuRepository extends CrudRepository<Menu, Long>, JpaSpecificationExecutor<Menu> {

...}

我添加了 @EnableTransactionManagement(proxyTargetClass=false),我认为它可以解决代理问题,但显然不是。

感谢您花时间阅读所有内容。

【问题讨论】:

  • 请澄清,因为目前还不清楚问题是什么。你基本上说,它不起作用,转储大量代码并期望这里的人修复它。
  • 对不起,我会尽量澄清我原来的帖子。
  • 由于某种原因触发了为代理创建代理。从您的代码来看,您正在混合不同的代理策略,为什么需要额外的DefaultAdvisorAutoProxyCreator
  • @M. Deinum - 老实说,我不知道为什么我两者都有。我已经看到一些文档说我需要 DefaultAdvisorAutoProxyCreator 和一些我需要 proxyTargetClass=false)。并且更改它们似乎没有影响。
  • 您应该可以删除DefaultAdvisorAutoProxyCreator。如前所述,问题在于您现在有多种生成代理的方法(应用 AOP),这通常会导致代理使用 cglib 代理(基于类的代理)无法实现的代理。

标签: spring spring-mvc spring-data shiro


【解决方案1】:
Caused by: java.lang.IllegalArgumentException: Cannot subclass final class class com.sun.proxy.$Proxy69

此异常表明,由于某些错误配置或多种应用 AOP 的方式,正在生成代理的代理。现在使用 JDK 动态代理,这不是问题,但是基于类的代理却是这样。因为 cglib 使类成为最终类(如堆栈跟踪所示)。

您的配置有多种生成代理的方式,@EnableTransactionManagement 已经触发了AutoProxyCreator 的注册。接下来,您将添加另一个。

这种情况下的解决方案是删除DefaultAdvisorAutoProxyCreator,因为已经为您注册了一个实例。这将禁用代理代理。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-17
    • 2013-06-13
    • 2019-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多