java Aspect 不适用于带有外部 jar 的 Spring boot 应用程序

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/38943134/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 03:54:47  来源:igfitidea点击:

Aspect does not work with Spring boot application with external jar

javaspringaopaspectj

提问by Avi

I am trying to create a timer aspect for measuring methods run time.

我正在尝试创建一个计时器方面来测量方法运行时间。

I created an annotation named @Timer:

我创建了一个名为的注释@Timer

@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.METHOD, ElementType.TYPE})
public @interface Timer {
    String value();
}

And then I created the aspect as follows:

然后我按如下方式创建了方面:

@Aspect
public class MetricAspect {

    @Autowired
    private MetricsFactory metricsFactory;

    @Pointcut("@annotation(my.package.Timer)")
    public void timerPointcut() {}

    @Around("timerPointcut() ")
    public Object measure(ProceedingJoinPoint joinPoint) throws Throwable {
       /* Aspect logic here */
    }

    private Timer getClassAnnotation(MethodSignature methodSignature) {
        Timer annotation;
        Class<?> clazz = methodSignature.getDeclaringType();
        annotation = clazz.getAnnotation(Timer.class);
        return annotation;
    }

I have a configuration class as follows:

我有一个配置类如下:

@Configuration
@EnableAspectJAutoProxy
public class MetricsConfiguration {

    @Bean
    public MetricAspect notifyAspect() {
        return new MetricAspect();
    }
}

Everything up until here is defined in a packaged jar which I use as a dependency in my spring boot application

到这里为止的所有内容都定义在一个打包的 jar 中,我将其用作 Spring Boot 应用程序中的依赖项

In my spring boot application I import the MetricsConfigurationand I debugged the code and saw that the MetricAspectbean is created.

在我的 Spring Boot 应用程序中,我导入MetricsConfiguration并调试了代码并看到MetricAspectbean 已创建。

I use it in code as follows:

我在代码中使用它如下:

@Service
public class MyService {
    ...

    @Timer("mymetric")
    public void foo() {
       // Some code here...
    }

    ...
}

But my code doesn't reach to the measuremethod. Not sure what I'm missing.

但是我的代码没有到达该measure方法。不知道我错过了什么。

For completing the picture, I have these dependencies in my pom file added:

为了完成图片,我在我的 pom 文件中添加了这些依赖项:

<dependencies>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.7.4</version>
    </dependency>

    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjrt</artifactId>
        <version>1.7.4</version>
    </dependency>
</dependencies>

That's the @Configurationclass that imports MetricsConfiguration:

@Configuration是导入的类MetricsConfiguration

@Configuration
@EnableAspectJAutoProxy
@Import(MetricsConfiguration.class)
@PropertySource("classpath:application.properties")
public class ApplicationConfiguration {

}

It's loaded with Spring's automagically configuration loading.

它加载了 Spring 的自动配置加载。

回答by ka yu Lai

can @Componentor @Configurablesolve your issue?

可以@Component@Configurable解决您的问题吗?

@Aspect
@Component
public class yourAspect {
 ...
}

Enable Spring AOP or AspectJ

启用 Spring AOP 或 AspectJ

EDIT:

编辑:

I created a project to simulate your issue, seems no problem after all. Is it affected by other issue?

我创建了一个项目来模拟您的问题,毕竟似乎没有问题。是否受到其他问题的影响?

https://github.com/zerg000000/spring-aspectj-test

https://github.com/zerg000000/spring-aspectj-test

回答by vsminkov

I was unable to reproduce your problem using aspectJ 1.8.8and spring 4.2.5. Hereis my maven multi-module approach with aspect in separate jar.

我无法使用aspectJ 1.8.8spring 4.2.5重现您的问题。是我的 maven 多模块方法,在单独的 jar 中具有方面。

I modified your code slightly but did not change any annotations. The only thing that might be differ is that I've added org.springframework:spring-aopdependency and defined my entrypoint as follows:

我稍微修改了您的代码,但没有更改任何注释。唯一可能不同的是我添加了org.springframework:spring-aop依赖项并如下定义了我的入口点:

@Import(MetricsConfiguration.class)
@SpringBootApplication
public class Application {
    // @Bean definitions here //

    public static void main(String[] args) throws InterruptedException {
        ApplicationContext ctx = 
            SpringApplication.run(Application.class, args);
        ctx.getBean(MyService.class).doWork();
    }
}

回答by FMirza

I had a similar problem where the aspect was built in a jar library, and the spring-boot application was else where. Turns out that the packages for the spring-boot application and the jar library were different. Due to which Spring was not looking into the package of the library to autowire into the application context.

我有一个类似的问题,其中方面是在 jar 库中构建的,而 spring-boot 应用程序在其他地方。事实证明,spring-boot 应用程序和 jar 库的包是不同的。因此,Spring 没有查看库的包以自动装配到应用程序上下文中。

So, had to include @ComponentScan({"base.package.application.*", "base.package.library.*"})in the Application.java

所以,不得不@ComponentScan({"base.package.application.*", "base.package.library.*"})在Application.java中包含

回答by u10892964

  1. If the external jar is Spring boot starter, you can config Aspect bean in AutoConfiguration:
  1. 如果外部 jar 是 Spring boot starter,则可以在 AutoConfiguration 中配置 Aspect bean:

(1)

(1)

@Aspect
public class MyAspect {
  //....
}

(2)

(2)

package a.b.c

@Configuration
public class MyAutoConfiguration {
    @Bean
    MyAspect myAspect() {
        return new MyAspect();
    }   
}

(3)config in spring.factories

(3)spring.factories中的配置

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
a.b.c.MyAutoConfiguration
  1. If the external jar is not a Spring boot starter, just load Aspect as a bean, you can use @ComponentScan
  1. 如果外部 jar 不是 Spring boot starter,只需将 Aspect 作为 bean 加载,就可以使用 @ComponentScan

回答by Asaf Maoz

Add this componentScan to resolve the issue.

添加此组件扫描以解决问题。

@ComponentScan("package.of.aspect")
@Configuration
@EnableAspectJAutoProxy
@Import(MetricsConfiguration.class)
@PropertySource("classpath:application.properties")
public class ApplicationConfiguration {

}

回答by kisna

Debugging spring-boot Aspectj aspects when pointcut itself has problems is not easy even with detailed logging: How to debug Spring AOP

即使有详细的日志记录,当切入点本身有问题时调试 spring-boot Aspectj 方面也并不容易:如何调试 Spring AOP

Unfortunately, spring boot + spring-aop with annotations don't have many ways to debug aspects and why some classes, especially non-spring compoment jar classes, are not scanned, such as jar classes whose methods are in abstract classesor static final methods need the right pointcuts to work covering all classes/implementations even if they are component scanned.

不幸的是,带有注解的spring boot + spring-aop 调试aspect 的方法并不多,以及为什么有些类,尤其是非spring 组件jar 类没有被扫描,例如jar 类的方法在抽象类或静态final 方法中需要正确的切入点来覆盖所有类/实现,即使它们是组件扫描的。

The best way to debug an Asepct (or use core AOP and avoid spring-aop) is to enable aop.xml with configuration control using org/aspectj/aop.xml or META-INF/aop.xml, using the LTW aspectj weaver -Daj.weaving.verbose=true -javaagent:~/.m2/repository/org/aspectj/aspectjweaver/1.9.5/aspectjweaver-1.9.5.jar

调试 Asepct(或使用核心 AOP 并避免 spring-aop)的最佳方法是使用 org/aspectj/aop.xml 或 META-INF/aop.xml 启用带有配置控制的 aop.xml,使用 LTW aspectj weaver - Daj.weaving.verbose=true -javaagent:~/.m2/repository/org/aspectj/aspectjweaver/1.9.5/aspectjweaver-1.9.5.jar

To debug all aspects/classes with Debug/Verbose logs to see why some classes are not being scanned: ...

使用 Debug/Verbose 日志调试所有方面/类以查看某些类未被扫描的原因:...

this almost always helps figuring out the problem with the pointcut or class not getting picked.

这几乎总是有助于找出切入点或类未被选中的问题。

Or, just use LTW aop, see, https://github.com/dsyer/spring-boot-aspectj

或者,只使用 LTW aop,参见https://github.com/dsyer/spring-boot-aspectj

回答by Rujal Shrestha

according to mojohausexplaination, you have to add build settings like below to Wovenyour aspect into all classes implementing your aspect interface.

根据mojohaus 的解释,您必须添加如下构建设置以将您的方面编织到实现方面接口的所有类中。

<build>
    <plugins>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>aspectj-maven-plugin</artifactId>
            <version>1.11</version>
            <configuration>
                <complianceLevel>1.8</complianceLevel>
                <includes>
                    <include>**/*.java</include>
                    <include>**/*.aj</include>
                </includes>
                <aspectDirectory>src/main/aspect</aspectDirectory>
                <testAspectDirectory>src/test/aspect</testAspectDirectory>
                <XaddSerialVersionUID>true</XaddSerialVersionUID>
                <showWeaveInfo>true</showWeaveInfo>
                <aspectLibraries>
                    <aspectLibrary>
                        <groupId>your aspect groupId</groupId>
                        <artifactId>your aspect artifactId</artifactId>
                    </aspectLibrary>
                </aspectLibraries>
            </configuration>
            <executions>
                <execution>
                    <id>compile_with_aspectj</id>
                    <goals>
                        <goal>compile</goal>
                    </goals>
                </execution>
                <execution>
                    <id>test-compile_with_aspectj</id>
                    <goals>
                        <goal>test-compile</goal>
                    </goals>
                </execution>
            </executions>
            <dependencies>
                <dependency>
                    <groupId>org.aspectj</groupId>
                    <artifactId>aspectjtools</artifactId>
                    <version>${aspectj.runtime.version}</version>
                </dependency>
                <dependency>
                    <groupId>your aspect groupId</groupId>
                    <artifactId>youar aspect artifactId</artifactId>
                    <version>1.0.0-SNAPSHOT</version>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>
</build>