【问题标题】:Spring : Interception without AspectJSpring:没有 AspectJ 的拦截
【发布时间】:2019-03-02 03:58:40
【问题描述】:

在我的 Spring 4 应用程序中,我有一个这样的类:

class Address {

   public getAdress(){
      ...
      List<Town> towns = getTowns();
      ...
   }

   @CustomAnnotation
   private List<Town> getTowns(){

   }
}

使用 AspectJ,我可以轻松拦截 getAdress() 调用。 问题在于未被拦截的getTowns()

有诸如 Load-Time Weaving 之类的解决方案,但很难调整,而且我不打算重新配置我的应用程序。

如何在没有 AspectJ 的情况下捕获对带有 CustomAnnotation 注释的任何方法的任何调用?

问候

PS:我知道there is a workaround with self-reference,但我觉得它不是很“干净”。

【问题讨论】:

  • getAdress提取一些接口,用ProxyFactoryBean创建代理。然后使用代理而不是bean
  • @Eugene 谢谢你的评论。你能通过一段代码来说明你的想法吗?您的方法是“无 xml”吗,因为我的应用程序没有 XML 配置文件,我想尽可能避免使用 XML。
  • 你根本不能这是基于代理的 AOP 的限制,唯一的解决方法是你不想要的自我调用(这基本上是唯一的解决方案)。因此,除了加载时间或编译时间编织之外,没有其他解决方案。
  • IMO 如果一个方法值得被作为一个方面实现的横切关注点拦截,它要么足够重要以使其公开,要么你的类设计被破坏并且被拦截的注释在错误的位置.修复您的设计,不要寻找电动工具来避免这种情况。这是来自 AspectJ 的忠实粉丝 BTW。所以我不反对使用 AJ。但是 AOP 既不是糟糕设计的借口,也不是修补糟糕代码的工具。

标签: java spring spring-mvc aop aspectj


【解决方案1】:

提取界面:

interface TempIfc{
    public getAdress();
}

class Address implements TempIfc{

   @Override
   public getAdress(){
      ...
      List<Town> towns = getTowns();
      ...
   }

   @CustomAnnotation
   private List<Town> getTowns(){

   }
}

添加配置:

<bean id="tgt" class="Address">
    <!-- your bean properties here -->
</bean>

<bean id="proxified" class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="proxyInterfaces" value="TempIfc"/>
    <property name="target" ref="tgt"/>
    <property name="interceptorNames">
        <list>
            <value>myInterceptor</value>
        </list>
    </property>
</bean> 

<bean id="myInterceptor" class="MyMethodInterceptor"/>

<!-- Example of usage with some service -->
<bean id="someYourService" class="Service">
     <property name="adress" ref="proxified" />
</bean>

最后是拦截器:

public class MyMethodInterceptor implements  org.aopalliance.intercept.MethodInterceptor{

    public Object invoke(org.aopalliance.intercept.MethodInvocation invocation){

        System.out.println("Before calling any TempIfc method ");

        // Actionally, you may use getMethod, getArguments here to explore details, or modify arguments

        Object result = invocation.proceed(); //also it is not obligatory to call real method

        System.out.println("After calling any TempIfc method ");
        //you may modify result of invocation here

        return result;
    }
}

这里是关于 ProxyFactoryBean 的 docsjavadocs

【讨论】:

  • 那仍然行不通。它仍然是一个代理,除非您进行自我调用,否则它仍然不会拦截内部方法调用。
【解决方案2】:

我认为我们可以使用 Spring 提供的 ControlFlowPointcut。

ControlFlowPointcut 仅在堆栈跟踪中找到特定方法时才会查看堆栈跟踪并匹配切入点。本质上,只有在特定上下文中调用方法时才会匹配切入点。

在这种情况下,我们可以创建一个类似的切入点

ControlFlowPointcut cf = new ControlFlowPointcut(MyClass.class, "method1");

现在,使用 ProxyFactory 在 MyClass 实例上创建一个代理并调用 method1()。

在上述情况下,只会建议method2(),因为它是从method1()调用的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-11
    相关资源
    最近更新 更多