【发布时间】:2016-06-14 09:14:10
【问题描述】:
我尝试了所有可能性,试图让我的项目在 Tomcat 上运行,并使用 AspectJ Load Time Weaver 对模型(getter)进行切入和编织。 基本上,我遵循了 Spring 文档http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html#aop-atconfigurable 中的所有步骤。我也遵循Lazy/Eager loading/fetching in Neo4j/Spring-Data 提到的相同方法。 我的项目分为两个主要项目: - 核心:spring-data-neo4j(存储库和配置),专用包中的域模型,LoggingAspect 和 LazyLoadingAspect。 p.s.我没有在 XML 文件中使用任何配置。我纯粹使用注释。 - 内容:依赖于核心项目的Tomcat上运行的Web应用程序,当我在域项目中调用getter方法时我想编织。
运行核心本身我设法使用 maven 插件运行它并添加 aspectj 的依赖项。但是当我搬到Tomcat时,一切都开始了。我尝试了所有可能性,例如使用 -javaagent、创建自定义 context.xml、将 spring-instrument 放入 tomcat/lib 文件夹等。我收到以下异常:
java.lang.IllegalStateException:后处理器试图用 [org.springframework.beans.factory.aspectj.$ 类型的(代理)对象替换 [com.test.server.graph.domain.model.Sequence] 类型的 bean 实例Proxy96] - 不支持方面配置的类! 在 org.springframework.beans.factory.wiring.BeanConfigurerSupport.checkExposedObject(BeanConfigurerSupport.java:173) 在 org.springframework.beans.factory.wiring.BeanConfigurerSupport.configureBean(BeanConfigurerSupport.java:143) 在 org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect.configureBean(AnnotationBeanConfigurerAspect.aj:63) 在 org.springframework.beans.factory.aspectj.AbstractDependencyInjectionAspect.ajc$afterReturning$org_springframework_beans_factory_aspectj_AbstractDependencyInjectionAspect$2$1ea6722c(AbstractDependencyInjectionAspect.aj:88) 在 com.test.server.graph.domain.model.Sequence.(Sequence.java:29) 在 sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 在 sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) 在 sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 在 java.lang.reflect.Constructor.newInstance(Constructor.java:422) 在 org.neo4j.ogm.annotations.EntityFactory.instantiate(EntityFactory.java:135) 在 org.neo4j.ogm.annotations.EntityFactory.instantiateObjectFromTaxa(EntityFactory.java:110) 在 org.neo4j.ogm.annotations.EntityFactory.newObject(EntityFactory.java:61) 在 org.neo4j.ogm.context.GraphEntityMapper.mapNodes(GraphEntityMapper.java:147) 在 org.neo4j.ogm.context.GraphEntityMapper.mapEntities(GraphEntityMapper.java:132) 在 org.neo4j.ogm.context.GraphEntityMapper.map(GraphEntityMapper.java:107) 在 org.neo4j.ogm.context.GraphEntityMapper.map(GraphEntityMapper.java:102) 在 org.neo4j.ogm.context.RestModelMapper.mapEntity(RestModelMapper.java:157) 在 org.neo4j.ogm.context.RestModelMapper.map(RestModelMapper.java:76) 在 org.neo4j.ogm.session.delegates.ExecuteQueriesDelegate.query(ExecuteQueriesDelegate.java:94) 在 org.neo4j.ogm.session.delegates.ExecuteQueriesDelegate.query(ExecuteQueriesDelegate.java:73) 在 org.neo4j.ogm.session.Neo4jSession.query(Neo4jSession.java:313) 在 org.springframework.data.neo4j.template.Neo4jTemplate.query(Neo4jTemplate.java:217) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在 java.lang.reflect.Method.invoke(Method.java:497) 在 org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:302) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) 在 org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 在 org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208) 在 com.sun.proxy.$Proxy58.query(未知来源)pom.xml (core.project)
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-neo4j</artifactId>
<version>${sdn.version}</version>
</dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-ogm-core</artifactId>
<version>2.0.3-SNAPSHOT</version>
</dependency>
我的配置类(核心项目)
@org.springframework.context.annotation.Configuration
@ComponentScan(basePackages = "org.test.server.graph")
@EnableNeo4jRepositories(basePackages = "org.test.server.graph.repository")
@EnableAspectJAutoProxy
@EnableSpringConfigured
public class Neo4jConfig extends Neo4jConfiguration {
@Bean
public Configuration getConfiguration() {
Configuration config = new Configuration();
config.driverConfiguration().setDriverClassName("org.neo4j.ogm.drivers.http.driver.HttpDriver")
.setURI(System.getProperty("neo4j.host")).setCredentials(System.getProperty("neo4j.user"),System.getProperty("neo4j.password"));
return config;
}
@Bean
public SessionFactory getSessionFactory() {
return new SessionFactory(getConfiguration(), "org.test.server.graph.domain" );
}
@Bean
@Scope(value = "prototype")
public Session getSession() throws Exception {
return super.getSession();
}
}
领域模型类
按照 Spring 文档的建议,我在域模型中注释了类
@可配置
mvc-dispatcher-servlet(webapp 项目)
<context:spring-configured />
<context:load-time-weaver aspectj-weaving="on" weaver-class="org.springframework.instrument.classloading.tomcat.TomcatLoadTimeWeaver" />
我尝试使用 tomcat-maven-plugin 和 tomcat 独立安装(v7 和 v8)运行。
-- 更新--
Sequence.java
@NodeEntity
@Configurable
public class Sequence extends DatabaseObject {
@Relationship(type = "hasModifiedResidue", direction = Relationship.OUTGOING)
private List<AbstractModifiedResidue> hasModifiedResidue;
@Relationship(type = "referenceEntity", direction = Relationship.OUTGOING)
private ReferenceSequence referenceEntity;
public Sequence() {}
//getter and setters
}
DatabaseObject.java
@NodeEntity
@Configurable(
preConstruction = false
)
public abstract class DatabaseObject implements Serializable, Comparable<DatabaseObject> {
@GraphId
private Long id;
// other common attributes + getter and setters, no more annotation
LazyLoadingAspect
@Aspect
@Component
public class LazyFetchAspect {
@Autowired
private Neo4jOperations neo4jTemplate;
@Around("modelGetter()")
public Object autoFetch(ProceedingJoinPoint pjp) throws Throwable {
System.out.println(" Testing Aspect ");
return pjp.proceed();
}
@Pointcut("execution(public * com.test.server.graph.domain.model.*.get*(..))")
public void modelGetter() {
}
}
【问题讨论】:
-
我的猜测是,当您在 Tomcat 下运行时,AspectJ 加载时编织不起作用。我认为您应该验证加载时编织确实生效并修复您的配置,直到它生效。您还可以考虑使用编译时编织(您可以使用 maven 来完成,也可以让 Eclipse 使用 AspectJ 编译器)。我使用
@Configurable和编译时编织取得了巨大的成功。尝试使用-javaagentvm 参数运行 Tomcat JVM。 -
另外,您应该为 AspectJ 加载时编织器启用调试日志记录,这样您就可以实际看到它在做什么。有关如何执行此操作的详细信息,请参阅我的answer 关于一个无关问题的详细信息。
-
@NándorElődFekete。核心项目本身正在运行,执行时我可以看到输出“Testing Aspect”。您需要考虑两件事,我正在运行 IntelliJ,这应该不是问题,并且我正在使用 -javaagent 运行 tomcat。我将启用调试日志记录并提出更新。干杯。
-
我猜您在不在 Tomcat 下运行项目时会看到“Testing Aspect”消息。这很好,但这并不意味着 LTW 在 Tomcat 下工作。也许尝试从
<context:load-time-weaver>配置标签中删除weaver-class="org.springframework.instrument.classloading.tomcat.TomcatLoadTimeWeaver"属性。 -
@NándorElődFekete。这就是我在这里发布后尝试的!希望它现在正在工作。我会想出一个更干净的版本并在这里发布解决方案。
标签: tomcat lazy-loading aspectj spring-data-neo4j