Нет доступного бина типа 'Concert.PerformanceImp' - PullRequest
0 голосов
/ 12 мая 2018

Я все еще новичок в Spring Framework, поэтому я попытался написать программу о «введении» в Spring AOP, но при компиляции я столкнулся с ошибкой. Пожалуйста, найдите ниже классы в пакете concert:

PerformanceImp.java

package concert;

import org.springframework.stereotype.Component;

@Component
public class PerformanceImp implements Performance {
    public void perform() {
        System.out.println("This is the performance function");
    }
}

Performance.java

package concert;

public interface Performance {
    public void perform();
}

Encoreable.java

package concert;

public interface Encoreable {
    void performEncore();
}

DefaultEncoreable.java

package concert;

import org.springframework.stereotype.Component;

@Component
public class DefaultEncoreable implements Encoreable {
    public void performEncore() {
        System.out.println("This is the performEncore function");
    }
}

EncoreableIntroducer.java

package concert;
import org.aspectj.lang.annotation.Aspect;

import org.aspectj.lang.annotation.DeclareParents;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class EncoreableIntroducer {
    @DeclareParents(value="concert.Performance+",
            defaultImpl=DefaultEncoreable.class)
    public static Encoreable encoreable;
}

ConcertConfig.java

package concert;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;

@Configuration
@EnableAspectJAutoProxy
@ComponentScan("concert")
public class ConcertConfig {

}

И основной класс:

Main.java

package concert;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;


public class Main {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(ConcertConfig.class);
        PerformanceImp pi = (PerformanceImp) context.getBean(PerformanceImp.class);
        ((Encoreable) pi).performEncore();
        pi.perform();
    }
}

Я получаю ошибку:

Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'concert.PerformanceImp' available

Любая помощь, пожалуйста?

Ответы [ 2 ]

0 голосов
/ 12 мая 2018

Вы не можете получить доступ к реализации (PerformanceImp) по умолчанию, потому что вы включили AOP, который устанавливает целевые интерфейсы вместо реализации. Если вы удалите EnableAspectJAutoProxy, вы увидите, что код будет работать нормально.

Чтобы узнать немного больше о том, как работает AOP таргетинг, взгляните на эту Spring Documentation

Spring AOP также может использовать прокси CGLIB. Это необходимо для прокси классы, а не интерфейсы. CGLIB используется по умолчанию, если бизнес Объект не реализует интерфейс. Как это хорошая практика программировать на интерфейсы, а не на классы; бизнес-классы обычно будет реализовывать один или несколько бизнес-интерфейсов. Можно принудительно использовать CGLIB в тех (надеюсь, редких) случаях, когда вам нужно посоветовать метод, который не объявлен на интерфейсе, или где вы необходимо передать объект прокси в метод как конкретный тип.

Итак, у вас есть два варианта:

  1. Возьмите интерфейс при попытке получить бин от ApplicationContext.
  2. Вместо этого включите AOP для конкретных классов.

Для этого # 2 измените аннотацию следующим образом:

@EnableAspectJAutoProxy(proxyTargetClass = true)
0 голосов
/ 12 мая 2018

Попробуйте:

Performance pi = context.getBean("performanceImp", Performance.class);

вместо:

PerformanceImp pi = (PerformanceImp) context.getBean(PerformanceImp.class);
...