son*_*rin 1 spring spring-mvc shiro spring-data
几天来我一直试图找到这个问题的答案,我希望有人能指出我正确的方向。我有一个使用 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
Run Code Online (Sandbox Code Playgroud)
这是我目前的设置:
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>
...
</>
Run Code Online (Sandbox Code Playgroud)
我使用这个网络配置:
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, "/*" );
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的主要配置类:
@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;
}
}
Run Code Online (Sandbox Code Playgroud)
这是另一个 Configuration 类。这是导致代理问题的添加。
@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;
}
}
Run Code Online (Sandbox Code Playgroud)
违规类只是一个 spring jparepository:
public interface MenuRepository extends CrudRepository<Menu, Long>, JpaSpecificationExecutor<Menu> {
...}
Run Code Online (Sandbox Code Playgroud)
我添加了@EnableTransactionManagement(proxyTargetClass=false),我认为它可以解决代理问题,但显然不是。
感谢您花时间阅读所有这些。
Caused by: java.lang.IllegalArgumentException: Cannot subclass final class class com.sun.proxy.$Proxy69
Run Code Online (Sandbox Code Playgroud)
此异常表示,由于某些错误配置或应用 AOP 的多种方式,正在生成代理的代理。现在对于 JDK 动态代理,这不是问题,但是对于基于类的代理来说却是问题。因为 cglib 使类成为最终的(如堆栈跟踪所示)。
您的配置有多种生成代理的方式,已@EnableTransactionManagement触发注册AutoProxyCreator。接下来,您将添加另一个。
这种情况下的解决方案是删除 ,DefaultAdvisorAutoProxyCreator因为已经为您注册了一个实例。这将禁用代理代理。
| 归档时间: |
|
| 查看次数: |
7745 次 |
| 最近记录: |