SpringMVC 代理问题 [英] SpringMVC Proxy issue

查看:56
本文介绍了SpringMVC 代理问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have been trying to find an answer to this problem for days, and I hope someone can point me in the right direction. I have a SpringMVC app that uses Java Configuration and I was doing fine until I tried to integrate Apache-Shiro into it. I am able to build and run my tests. But my deploy fails because of Proxy/CGLIB issues.

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

Here is the exception I get on deploy/restart:

 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;
    }
}

这是另一个配置类.正是添加这一点导致了代理问题.

And here is the other Configuration class. It is the addition of this that causes the proxy issues.

@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:

the offending class is just a spring jparepository:

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

...}

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

I have added the @EnableTransactionManagement(proxyTargetClass=false) which I thought would address the Proxy issue but apparently isn't.

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

Thank you for your time in reading all this.

推荐答案

Caused by: java.lang.IllegalArgumentException: Cannot subclass final class class com.sun.proxy.$Proxy69

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

This exception indicates that, due to some misconfiguration or multiple ways of applying AOP, a proxy of a proxy is being generated. Now with JDK Dynamic Proxies this isn't a problem however with class based proxies it is. Because cglib makes the classes final (as indicated by the stacktrace).

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

Your configuration has multiple ways of generation proxies, @EnableTransactionManagement triggers the registration of an AutoProxyCreator already. Next you are adding another one.

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

The solution in this case is to remove the DefaultAdvisorAutoProxyCreator as there is already an instance registered for you. This will disable proxying a proxy.

这篇关于SpringMVC 代理问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆