最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

java - Why does enabling an AspectJ expression make the class that is supposed to work on disappear from the context - Stack Ove

programmeradmin1浏览0评论

I'm learning how to use AspectJ expressions using the book "Spring starts here" and after running the same program 5 times(It was ok) a change in the AspectJ expression made an exception that said

Exception in thread "main"
.springframework.beans.factory.NoSuchBeanDefinitionException:
  No qualifying bean of type
  'julian.gonzalezlopez.aop.Comment.CommentRepository'
  available

That error only happends if the AspectJ expression fits the criterea

Aspecto.java

import java.util.logging.Logger;
import .springframework.stereotype.Component;
import .aspectj.lang.annotation.Aspect;
import .aspectj.lang.ProceedingJoinPoint;
import .aspectj.lang.annotation.Around;

@Aspect
@Component
public class Aspecto {
    private static final Logger logger = Logger.getLogger(Aspect.class.getName());
    
    @Around("execution (* julian.*.*.Comment.*.*(..))")
    public void log(ProceedingJoinPoint joinPoint) {
        logger.info("Comenzó un metodo atrapado por el aspecto");
        try {
            joinPoint.proceed();
        }
        catch (Throwable e) {
            System.err.println(e);
        }
        logger.info("Terminó");
    }
}

CommentRepository.java

import julian.gonzalezlopez.aop.POJO.Comment;
import .springframework.stereotype.Service;

@Service
public class CommentRepository implements CommentRepositoryInterface {
    public void pie(Comment comment){
        System.out.println(comment.getText());
        System.out.println("Escrito por: " + comment.getOwner());
    }
}

Main.java

import julian.gonzalezlopez.aop.Comment.CommentRepository;
import julian.gonzalezlopez.aop.Comment.CommentRepositoryInterface;
import julian.gonzalezlopez.aop.POJO.Comment;
import .springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {
    public static void main(String[] args) {
        System.out.println("Hello World!");
        AnnotationConfigApplicationContext c = new AnnotationConfigApplicationContext(ProjectConfig.class);
        System.out.println(c);
        CommentRepositoryInterface commentRepository = c.getBean(CommentRepository.class);
        Comment comment = new Comment("hola","julian");
        commentRepository.pie(comment);
    }
}

I'm learning how to use AspectJ expressions using the book "Spring starts here" and after running the same program 5 times(It was ok) a change in the AspectJ expression made an exception that said

Exception in thread "main"
.springframework.beans.factory.NoSuchBeanDefinitionException:
  No qualifying bean of type
  'julian.gonzalezlopez.aop.Comment.CommentRepository'
  available

That error only happends if the AspectJ expression fits the criterea

Aspecto.java

import java.util.logging.Logger;
import .springframework.stereotype.Component;
import .aspectj.lang.annotation.Aspect;
import .aspectj.lang.ProceedingJoinPoint;
import .aspectj.lang.annotation.Around;

@Aspect
@Component
public class Aspecto {
    private static final Logger logger = Logger.getLogger(Aspect.class.getName());
    
    @Around("execution (* julian.*.*.Comment.*.*(..))")
    public void log(ProceedingJoinPoint joinPoint) {
        logger.info("Comenzó un metodo atrapado por el aspecto");
        try {
            joinPoint.proceed();
        }
        catch (Throwable e) {
            System.err.println(e);
        }
        logger.info("Terminó");
    }
}

CommentRepository.java

import julian.gonzalezlopez.aop.POJO.Comment;
import .springframework.stereotype.Service;

@Service
public class CommentRepository implements CommentRepositoryInterface {
    public void pie(Comment comment){
        System.out.println(comment.getText());
        System.out.println("Escrito por: " + comment.getOwner());
    }
}

Main.java

import julian.gonzalezlopez.aop.Comment.CommentRepository;
import julian.gonzalezlopez.aop.Comment.CommentRepositoryInterface;
import julian.gonzalezlopez.aop.POJO.Comment;
import .springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {
    public static void main(String[] args) {
        System.out.println("Hello World!");
        AnnotationConfigApplicationContext c = new AnnotationConfigApplicationContext(ProjectConfig.class);
        System.out.println(c);
        CommentRepositoryInterface commentRepository = c.getBean(CommentRepository.class);
        Comment comment = new Comment("hola","julian");
        commentRepository.pie(comment);
    }
}
Share Improve this question edited Feb 11 at 11:56 kriegaex 67.5k15 gold badges120 silver badges223 bronze badges asked Feb 10 at 15:46 Julian.gxnzalezJulian.gxnzalez 52 bronze badges 9
  • Your around aspect is broken. You must always return Object from the method and return the result of joinPoint.proceed(). If you don't return values of methods might suddenly disappear. As your aspect is quite broad it probably matches your ProjectConfig as well leading to @Bean methods to return null. – M. Deinum Commented Feb 10 at 18:27
  • @M.Deinum, I disagree in this specific case, even though your general advice is correct. The OP obviously wants to intercept a void method. Therefore, a void aspect advice is just fine. The error message also implies a different kind of problem. – kriegaex Commented Feb 11 at 11:58
  • Welcome to Stack Overflow. Please learn how to ask a question on SO and provide a minimal, complete, and verifiable example. Thank you. I am saying this, because there are misssing classes in your sample code, e.g. the interface class and also the Spring config class. But the latter is probably the problem here, see my upcoming answer. Reproducibility is kind, if you ever expect precise, helpful, spot-on answers to your questions here. – kriegaex Commented Feb 11 at 12:32
  • Well I had more trouble of not returning Object then try to make it work for void methods. However his pointcut will match methods returning values as well, which thus will break things that do return values. – M. Deinum Commented Feb 11 at 12:40
  • I know what you mean, which is why I said that your recommendation is generally correct. But it is simply a red herring here. I have described possible root causes of the problem at hand and how to fix them in my answer. – kriegaex Commented Feb 11 at 12:47
 |  Show 4 more comments

1 Answer 1

Reset to default 1

Before we proceed to your main problem, a few hints:

  • You ought to adhere to naming conventions, e.g. not use upper-case package names, because they are easily confused with class names.

  • Your logger uses class Aspect, but probably you want to use Aspecto. Besides, that is also a bad class name. You should use an aspect name describing what kind of aspect it is, such as LoggingAspect.

  • In your screenshot, I can see a class named CommentService, but in your sample code you use class CommentRepository with a @Service annotation. That is utterly confusing. Do you even remember yourself why you did that?

Now, how can you fix your problem? Probably, your config class looks somewhat like this:

@Configuration
@EnableAspectJAutoProxy
public class ProjectConfig {}

I.e., it is missing a @ComponentScan annotation.

Another possibility is that you actually did add that annotation, but still get the same exception. In that case, you can either fix your main class, searching for a bean of the interface class, ...

CommentRepositoryInterface commentRepository = c.getBean(CommentRepositoryInterface.class);

..., which is what I recommend. As an alternative, you can keep your bean instantiation as-is but modify the way Spring creates proxies:

@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
@ComponentScan
public class ProjectConfig {}

I warmly recommend to use the first option, because it is cleaner from a design point of view. You have the interface and its implementation already, which is a clean design. Utilise it, do not work around it.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论