我正在尝试实现一个简单的Spring AOP示例 .

Use case:

我有一个光盘(SgtPeppers)类,其中包含艺术家, Headers 等属性 . 它有一种播放特定曲目的方法 . 我创建了一个方面来计算播放曲目的次数 . 我有一个测试类来测试它 .

Problem:

光盘类与方面和测试类不同 . 使用spring java config方法配置Bean . 但是,自动装配似乎不适用于光盘类 . 它抛出BeanCreationException .

请找到下面的代码:光盘类(这里,它被配置为SgtPeppers)

package com.springinaction.soundsystem.autoconfig;

import java.util.List;


public class SgtPeppers implements CompactDisc {

private String title, artist;

    public SgtPeppers(String title, String artist) {
        super();
        this.title = title;
        this.artist = artist;
    }

    public SgtPeppers() {
        // TODO Auto-generated constructor stub
    }

    public String getTitle() {
        return title;
    }

    public String getArtist() {
        return artist;
    }

    @Override
    public void play() {
        System.out.println("Playing "+title+" by "+ artist);        
    }

    public void playTrack(int tracknumber) {
        System.out.println("Playing track "+ tracknumber);
    }

}

TrackCounter看点:

package com.springinaction.aspects.concert.trackCounter;

import java.util.HashMap;
import java.util.Map;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class TrackCounter {

    private Map<Integer,Integer> trackCounts = new HashMap<Integer, Integer>();

    @Pointcut("execution(** com.springinaction.aspects.concert.trackCounter.SgtPeppers.playTrack(int)) && args(trackNumber)")
    public void trackPlayed(int trackNumber){}

    @Before("trackPlayed(trackNumber)")
    public void countTrack(int trackNumber) {
        int trackCount = getTrackCount(trackNumber);
        trackCounts.put(trackNumber, trackCount+1);
    }

    public int getTrackCount(int trackNumber) {
        return trackCounts.containsKey(trackNumber) ? trackCounts.get(trackNumber) : 0;
    }

}

TrackCounterConfig:

package com.springinaction.aspects.concert.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

import com.springinaction.aspects.concert.trackCounter.SgtPeppers;
import com.springinaction.aspects.concert.trackCounter.TrackCounter;

@Configuration
@EnableAspectJAutoProxy
public class TrackCounterConfig {

    @Bean
    public SgtPeppers sgtPeppers() {
        SgtPeppers cd = new SgtPeppers("Sgt. Pepper's Lonely Hearts Club Band", "The Beatles");
        return cd;
    }

    @Bean
    public TrackCounter trackCounter() {
        return new TrackCounter();
    }
}

TrackCounterTest:

package com.springinaction.aspects.concert.trackCounter;

import static org.junit.Assert.assertEquals;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.springinaction.aspects.concert.config.TrackCounterConfig;
import com.springinaction.soundsystem.autoconfig.SgtPeppers;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=TrackCounterConfig.class)
public class TrackCounterTest {

    @Autowired
    private TrackCounter trackCounter;

    @Autowired
    private SgtPeppers sgtPeppers;

    @Test
    public void testTrackCounter() {
        sgtPeppers.playTrack(1);
        sgtPeppers.playTrack(1);
        sgtPeppers.playTrack(2);
        sgtPeppers.playTrack(2);
        sgtPeppers.playTrack(3);
        sgtPeppers.playTrack(3);
        sgtPeppers.playTrack(3);
        sgtPeppers.playTrack(3);
        sgtPeppers.playTrack(7);
        sgtPeppers.playTrack(7);

        assertEquals(2, trackCounter.getTrackCount(1));
        assertEquals(2, trackCounter.getTrackCount(2));
        assertEquals(4, trackCounter.getTrackCount(3));
        assertEquals(2, trackCounter.getTrackCount(7));
    }

}

这里,SgtPeppers类位于com.springinaction.soundsystem.autoconfig包中 . TrackCounter和TrackCounterconfig位于com.springinaction.aspects.concert.config包中 . 我得到以下异常:

org.springframework.beans.factory.BeanCreationException:创建名为'com.springinaction.aspects.concert.trackCounter.TrackCounterTest'的bean时出错:注入自动连接的依赖项失败;嵌套异常是org.springframework.beans.factory.BeanCreationException:无法自动装配字段:private com.springinaction.soundsystem.autoconfig.SgtPeppers com.springinaction.aspects.concert.trackCounter.TrackCounterTest.sgtPeppers;嵌套异常是org.springframework.beans.factory.NoSuchBeanDefinitionException:找不到[com.springinaction.soundsystem.autoconfig.SgtPeppers]类型的限定bean用于依赖:预期至少有1个bean可以作为此依赖项的autowire候选者 . 依赖注释:{org.springframework.beans.factory.annotation.Autowired(required = true)}位于org.springframework.beans的org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:293) . 在org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies上的org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:384)中的factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1186) DependencyInjectionTestExecutionListener.java:110)在org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75)在org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:331)在org.springframework .test.context.junit4.S pringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:213)org.springframework.test.context.junit4.SpringJUnit4ClassRunner $ 1.runReflectiveCall(SpringJUnit4ClassRunner.java:290)at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java) :12)在Org.springframework的org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:292)org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:233) . org.junit.runners.ParentRunner $ 1.schedule(ParentRunner.java:)中的org.junit.runners.ParentRunner $ 3.run(ParentRunner.java:238)中的test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:87) 63)org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)org.junit.runners.ParentRunner.access $ 000(ParentRunner.java:53)org.junit.runners.ParentRunner $ 2.evaluate(ParentRunner) .java:229)org.springframework.test.context.junit4.statements.RunB eforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)org.junit.runners.ParentRunner.run(ParentRunner.java:309)在org.eclipse.jdt的org.eclipse.jout上,org.eclipse.UNternal.unit.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)上的org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:176)位于org.eclipse.jdt.internal.junit的org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)的.internal.junit.runner.TestExecution.run(TestExecution.java:38) .runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)at atorg.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)at or.e.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)引起:org . springframework.beans.factory.BeanCreationException:无法自动装配字段:private com.springinaction.soundsystem.autoconfig.SgtPeppers com.springinaction.aspects.concert.trackCounter.TrackCounterTest.sgtPeppers;嵌套异常是org.springframework.beans.factory.NoSuchBeanDefinitionException:找不到[com.springinaction.soundsystem.autoconfig.SgtPeppers]类型的限定bean用于依赖:预期至少有1个bean可以作为此依赖项的autowire候选者 . 依赖注释:{org.springframework.beans.factory.annotation.Autowired(required = true)}在org.springframework的org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor $ AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:509) . beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:290)... 26更多引起:org.springframework.beans .factory.NoSuchBeanDefinitionException:找不到[com.springinaction.soundsystem.autoconfig.SgtPeppers]类型的限定bean用于依赖:预期至少有1个bean可以作为此依赖项的autowire候选者 . 依赖注释:{org.springframework.beans.factory.annotation.Autowired(required = true)}在org.springframework.beans的org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1118) . or.s.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:862)中的factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:967)org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor $ AutowiredFieldElement . inject(AutowiredAnnotationBeanPostProcessor.java:481)......还有28个

Note: 我尝试过使用basePackages,basePackageClasses的ComponentScan . 但是,它没有使用 spring 启动配置,因为它是用于学习目的 .

我在com.springinaction.aspects.concert.config包中创建了相同的SgtPeppers bean . 自动装配工作 . 为什么java配置bean创建方式不适用于在不同包中定义的bean?

任何建议都会有所帮助 .

谢谢 .