Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Aspect不适用于带有外部jar的Spring引导应用程序_Java_Spring_Aop_Aspectj - Fatal编程技术网

Java Aspect不适用于带有外部jar的Spring引导应用程序

Java Aspect不适用于带有外部jar的Spring引导应用程序,java,spring,aop,aspectj,Java,Spring,Aop,Aspectj,我试图创建一个计时器方面来测量方法的运行时间 我创建了一个名为@Timer的注释: @Retention(RetentionPolicy.RUNTIME) @Target(value = {ElementType.METHOD, ElementType.TYPE}) public @interface Timer { String value(); } 然后我创建了如下方面: @Aspect public class MetricAspect { @Autowired

我试图创建一个计时器方面来测量方法的运行时间

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

@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.METHOD, ElementType.TYPE})
public @interface Timer {
    String value();
}
然后我创建了如下方面:

@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;
    }
@Configuration
@EnableAspectJAutoProxy
public class MetricsConfiguration {

    @Bean
    public MetricAspect notifyAspect() {
        return new MetricAspect();
    }
}
@Service
public class MyService {
    ...

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

    ...
}
在此之前的所有内容都是在打包的jar中定义的,我在spring引导应用程序中将其作为依赖项使用

在我的spring boot应用程序中,我导入了
MetricsConfiguration
,并调试了代码,发现创建了
MetricAspect
bean

我在代码中使用它,如下所示:

@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;
    }
@Configuration
@EnableAspectJAutoProxy
public class MetricsConfiguration {

    @Bean
    public MetricAspect notifyAspect() {
        return new MetricAspect();
    }
}
@Service
public class MyService {
    ...

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

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

为了完成图片,我在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>

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

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

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

编辑:

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


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

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

@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;
    }
@Configuration
@EnableAspectJAutoProxy
public class MetricsConfiguration {

    @Bean
    public MetricAspect notifyAspect() {
        return new MetricAspect();
    }
}
@Service
public class MyService {
    ...

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

    ...
}
@Import(MetricsConfiguration.class)
@SpringBoot应用程序
公共类应用程序{
//@Bean定义在这里//
公共静态void main(字符串[]args)引发InterruptedException{
ApplicationContext ctx=
SpringApplication.run(Application.class,args);
getBean(MyService.class).doWork();
}
}

我遇到了一个类似的问题,方面构建在jar库中,而spring启动应用程序则在其他地方。原来spring启动应用程序和jar库的包是不同的。因此,Spring没有查看库的包以自动连接到应用程序上下文中

因此,必须在application.java中包含
@ComponentScan({“base.package.application.*”,“base.package.library.*})

  • 如果外部jar是Spring boot starter,则可以在自动配置中配置方面bean:
  • (一)

    (二)

    (3) spring.factories中的配置

    org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
    a.b.c.MyAutoConfiguration
    
  • 如果外部jar不是springbootstarter,只需将方面作为bean加载,就可以使用@ComponentScan

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

    @ComponentScan("package.of.aspect")
    @Configuration
    @EnableAspectJAutoProxy
    @Import(MetricsConfiguration.class)
    @PropertySource("classpath:application.properties")
    public class ApplicationConfiguration {
    
    }
    
    根据解释,您必须将如下构建设置添加到实现方面接口的所有类中

    <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>
    
    
    org.codehaus.mojo
    aspectj maven插件
    1.11
    1.8
    **/*.爪哇
    **/*.aj
    src/main/aspect
    src/测试/方面
    真的
    真的
    您的aspect groupId
    你的方面人工智能
    使用_aspectj编译_
    编译
    用aspectj测试编译
    测试编译
    org.aspectj
    aspectjtools
    ${aspectj.runtime.version}
    您的aspect groupId
    youar aspect artifactId
    1.0.0-SNAPSHOT
    
    在切入点本身出现问题时调试spring boot Aspectj特性即使有详细的日志记录也不容易:

    不幸的是,带注释的spring boot+spring aop没有很多方法来调试方面,并且为什么一些类,特别是非spring组件jar类,没有被扫描,例如jar类或静态final方法,需要正确的切入点来覆盖所有类/实现,即使它们是组件扫描的

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

    要使用调试/详细日志调试所有方面/类,以查看未扫描某些类的原因,请执行以下操作:

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


    或者,只需使用LTW aop,请参见,

    您是否也有spring方面的依赖关系?我尝试添加它,但效果不好:/n为什么要使用反射来获取注释?您可以简单地将它添加到around advice方法的参数中,并直接访问它。@kriegaex-事实上,我在过去多次创建过这种代码,并且成功了。主要区别在于我提到的spring boot的使用:/is
    timerPointcut()
    方法被调用了吗?关于如何在spring BootJ中使用AspectJ的官方示例感谢您的回答。但这不是
    @组件的问题。我试图了解它的要点,但我还是在
    MetricsConfiguration
    中创建了bean。这不是问题所在。我怀疑这是因为方面和bean在一个外部jar中,我使用的是spring boot。添加@Component注释解决了这个问题,而且它也有意义,因为方面可能需要在运行时注入,有什么想法吗?谢谢你的全面回答。我仍然找不到我的代码和你的代码之间的差异。我猜