使用方面来劫持来自不同servlet的类的静态方法

时间:2014-08-08 09:25:45

标签: java spring servlets aspectj

背景

我尝试在Spring应用程序中使用LightAdmin。我遇到的根本问题是它只支持一些基本普通类型 - 我使用java.util.UUID例如,不支持(see here)。

由于这些是静态方法,并且没有任何POI来绑定自己的类型,我想到了使用方面。

问题

但这又解决了另一个问题 - 我不能让我的方面劫持这个静态调用。 LightAdmin作为一个单独的servlet工作,但在同一个应用程序中,我的方面加载到applicationContext.xml

TypeHandler.java(方面代码):

@Aspect
public class TypeHandler
{
    @Before("execution(static * org.lightadmin.core.persistence.metamodel.DomainTypeAttributeType.forType(..))")
    public void myBefore()
    {
        System.out.println("HIJACKED!");
    }
}

applicationContext.xml片段:

<aop:aspectj-autoproxy/>

<context:component-scan
    base-package="my.website.web.backend"
    use-default-filters="true"
>
    <context:include-filter type="annotation" expression="org.aspectj.lang.annotation.Aspect"/>
</context:component-scan>
<context:load-time-weaver/>

我使用 Tomcat7 org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader类加载器。

在日志中我可以看到:

...
11:02:55.198 [localhost-startStop-1] INFO  org.springframework.context.weaving.DefaultContextLoadTimeWeaver - Using a reflective load-time weaver for class loader: org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader
...
INFO: Initializing Spring FrameworkServlet 'backend'
11:03:11.677 [localhost-startStop-1] INFO  org.springframework.web.servlet.DispatcherServlet - FrameworkServlet 'backend': initialization started
11:03:11.687 [localhost-startStop-1] INFO  org.springframework.web.context.support.XmlWebApplicationContext - Refreshing WebApplicationContext for namespace 'backend-servlet': startup date [Fri Aug 08 11:03:11 CEST 2014]; parent: Root WebApplicationContext
11:03:11.689 [localhost-startStop-1] INFO  org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from ServletContext resource [/WEB-INF/backend-servlet.xml]
11:03:11.770 [localhost-startStop-1] INFO  org.springframework.web.servlet.DispatcherServlet - FrameworkServlet 'backend': initialization completed in 93 ms
sie 08, 2014 11:03:11 AM org.apache.catalina.core.ApplicationContext log
INFO: Initializing Spring FrameworkServlet 'lightadmin-dispatcher'
11:03:11.772 [localhost-startStop-1] INFO  org.springframework.web.servlet.DispatcherServlet - FrameworkServlet 'lightadmin-dispatcher': initialization started
11:03:11.773 [localhost-startStop-1] INFO  org.springframework.web.context.support.AnnotationConfigWebApplicationContext - Refreshing WebApplicationContext for namespace 'lightadmin-dispatcher-servlet': startup date [Fri Aug 08 11:03:11 CEST 2014]; parent: Root WebApplicationContext
...

/WEB-INF/backend-servlet.xml为空)

在我的UUID字段调用org.lightadmin.core.persistence.metamodel.DomainTypeAttributeType.forType()而没有被我的方面劫持后,应用程序失败。

我已经尝试添加@Component注释,在applicationContext.xml等手动注册bean - 没有效果。我认为这个方面本身是由bean工厂加载的,因为如果我配置了一个无效的切入点,我就会有一个例外。

问题

所以我的两个问题是:

  1. 还有其他方法可以使这项工作(没有LightAdmin源代码修改,我想不惜一切代价避免这种情况)?
  2. 如果不是,那么如何使这方面有效?

2 个答案:

答案 0 :(得分:2)

请使用最新的重新设计的LightAdmin版本以及一组扩展支持的类型( UUID Joda-Time )。它已升级到Spring 4.0.X,这是最新的Spring DATA / REST,包含一系列缺陷修复程序。

顺便说一句,您不再需要使用LightAdmin Nexus存储库进行发布。 它现在直接从Maven Central提供。

答案 1 :(得分:0)

Spring AOP不能用于静态方法。您必须使用完整的AspecJ才能使用。您可以在How to intercept static methods in Spring?中找到其他参考资料。

定义切入点时没有异常,因为它的语法在AspectJ中是有效的,只是Spring AOP无法处理它。