简体   繁体   English

Spring AOP方面在单独的模块中使用

[英]Spring AOP aspect used in a separate module

I have an aspect com.x.NiceAspect in one maven project module, and a class com.x.NiceClass in a separate maven module. 我在一个maven项目模块中有一个方面com.x.NiceAspect,在一个单独的maven模块中有一个类com.x.NiceClass。 Those modules have the same POM parent, together creating one project. 这些模块具有相同的POM父级,一起创建一个项目。

The thing I am trying to achieve is to have a universal aspect that I can include in all my maven modules in this project. 我要实现的目的是拥有一个通用的方面,可以将其包含在该项目的所有Maven模块中。

Now the pointcut in the NiceAspect is ie execution(* com.x.. .set (..)) meaning all setter methods in mine package. 现在在NiceAspect的切入点,即执行(* com.x .. .SET(..)),这意味着在我的包中的所有setter方法。

I want this aspect to run with the second module, especially to join NiceClass 我希望此方面与第二个模块一起运行,尤其是加入NiceClass

How can I achieve this? 我该如何实现?

Moreover suppose that the Aspect wants an argument of a class that's defined in that second module, then I end up with a circular dependency.. 此外,假设Aspect想要一个在第二个模块中定义的类的参数,那么我最终得到一个循环依赖。

Any help appreciated 任何帮助表示赞赏

Kind regards, 亲切的问候,

x. X。

In Spring Boot: 在Spring Boot中:

Suppose in module 'A' we implement our aspect classes. 假设在模块“ A”中我们实现了方面类。 Then we need to make them visible to Spring (Boot): 然后,我们需要使它们对Spring(引导)可见:

@Configuration
@ComponentScan(basePackages = "root.package.containing.the.defined.aspecs")
public class AspectsModuleConfiguration {
  //...
}

In module B which has a (Maven) dependency to A, we import the above configuration class. 在对A具有(Maven)依赖性的模块B中,我们导入上述配置类。

@SpringBootApplication
@Import(AspectsModuleConfiguration.class)
public class ModuleBApplicationClass {
//...
}

If you have all your projects declared as sub projects in the main pom the one containing the aspect (and thus the aspect itself) will be available to the other two, and basically any of the subprojects will have as dependency the other subprojects. 如果您在主pom中将所有项目都声明为子项目,则包含该方面的一个项目(以及该方面本身)将对其他两个项目可用,并且基本上任何子项目都将其他子项目作为依赖项。

You will not have a circular dependency due to packaging: 由于打包,您将没有循环依赖项:

  • if you package any of your prject as an executable jar, then in order for it to run you need to add the other two subbrojects' jars to the first one's classpath when u run it 如果您将任何项目打包为可执行jar,则为了使其运行,您需要在运行它时将其他两个子对象的jar添加到第一个子类的jar中

  • if you package any of your subprojects as a war (and the other two as jars) then when packaging with maven the other two subproject's jars will be added to the war's lib folder effectively making them available to the war's classpath at runtime. 如果您将任何子项目打包为war(另两个子项目打包为jar),则在与maven打包时,其他两个子项目的jar将添加到war的lib文件夹中,从而在运行时有效地将其提供给war的类路径。

  • I want this aspect to run with the second module, especially to join NiceClass 我希望此方面与第二个模块一起运行,尤其是加入NiceClass

    If the pointcut matches a method from "another" module, the aspect will apply. 如果切入点与“另一个”模块中的方法匹配,则该方面将适用。 You need to do nothing special, besides setting your dependencies correctly. 除了正确设置依赖项之外,您无需执行其他任何特殊操作。 eg have your AOP configuration globally imported. 例如,将您的AOP配置全局导入。

  • Moreover suppose that the Aspect wants an argument of a class that's defined in that second module, then I end up with a circular dependency.. 此外,假设Aspect想要一个在第二个模块中定义的类的参数,那么我最终得到一个循环依赖。

    The aspect dependency on the class argument should not result in circular dependency, since you have a parent POM that connects the two, and at runtime both of the modules are in a classpath. 对类参数的方面依赖关系不应导致循环依赖关系,因为您具有将两者连接的父POM,并且在运行时,两个模块都位于类路径中。

In general, it is recommended to follow Aspect structure as described by Spring documentation => create an overall SystemArchitecture aspect, and then add more narrowed scope aspects as needed: 通常,建议遵循Spring 文档中描述的Aspect结构=>创建整体SystemArchitecture方面,然后根据需要添加更多缩小范围的方面:

@Aspect
public class SystemArchitecture {

  /**
   * A join point is in the web layer if the method is defined
   * in a type in the com.xyz.someapp.web package or any sub-package
   * under that.
   */
  @Pointcut("within(com.xyz.someapp.web..*)")
  public void inWebLayer() {}

  /**
   * A join point is in the service layer if the method is defined
   * in a type in the com.xyz.someapp.service package or any sub-package
   * under that.
   */
  @Pointcut("within(com.xyz.someapp.service..*)")
  public void inServiceLayer() {}

  /**
   * A join point is in the data access layer if the method is defined
   * in a type in the com.xyz.someapp.dao package or any sub-package
   * under that.
   */
  @Pointcut("within(com.xyz.someapp.dao..*)")
  public void inDataAccessLayer() {}

  /**
   * A business service is the execution of any method defined on a service
   * interface. This definition assumes that interfaces are placed in the
   * "service" package, and that implementation types are in sub-packages.
   * 
   * If you group service interfaces by functional area (for example, 
   * in packages com.xyz.someapp.abc.service and com.xyz.def.service) then
   * the pointcut expression "execution(* com.xyz.someapp..service.*.*(..))"
   * could be used instead.
   *
   * Alternatively, you can write the expression using the 'bean'
   * PCD, like so "bean(*Service)". (This assumes that you have
   * named your Spring service beans in a consistent fashion.)
   */
  @Pointcut("execution(* com.xyz.someapp.service.*.*(..))")
  public void businessService() {}

  /**
   * A data access operation is the execution of any method defined on a 
   * dao interface. This definition assumes that interfaces are placed in the
   * "dao" package, and that implementation types are in sub-packages.
   */
  @Pointcut("execution(* com.xyz.someapp.dao.*.*(..))")
  public void dataAccessOperation() {}

}

This way any future aspects you may need, can reuse the over all System Architecture approach as well as live together with the actual module they are applied to. 这样,您将来可能需要的任何方面都可以重用整个系统体系结构方法,并与应用它们的实际模块一起使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM