我编写了一组简单的类来向 friend 展示有关使用AOP注释(而不是xml config)的知识。我们无法使@ComponentScan正常工作,并且AnnotationConfigApplicationContext getBean也行为不当。我想了解两件事。参见下面的代码:

PersonOperationsI.java

package samples.chapter3;

import org.springframework.stereotype.Component;

@Component
public interface PersonOperationsI {

    public String getName();

}

PersonOperations.java
/**
 *
 */
package samples.chapter3;

import org.springframework.stereotype.Component;

@Component
public class PersonOperations implements PersonOperationsI {


    public String getName() {
        return "";
    }

}

PersonOperationsConfigClass.java
package samples.chapter3;

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

@Configuration
//question2  - Below Component Scan didnt work - Test Case failing in setup()
//@ComponentScan(basePackages = {"samples.chapter3"})
@EnableAspectJAutoProxy

public class PersonOperationsConfigClass {

}

PersonOperationsAdvice.java
/**
 *
 */
package samples.chapter3;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class PersonOperationsAdvice {

    /**
     * execution( [Modifiers] [ReturnType] [FullClassName].[MethodName]
    ([Arguments]) throws [ExceptionType])

     * @param joinPoint
     * @return
     */
    @Before("execution(public * samples.chapter3.PersonOperations.getName()))")
    public String beforeGetName(JoinPoint joinPoint) {
        System.out.println("method name = " + joinPoint.getSignature().getName());
        return null;
    }
}

PersonOperationsTest.java
package samples.chapter3;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;

@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = { PersonOperationsConfigClass.class })
public class PersonOperationsTest {

    //@Autowired
    private PersonOperationsI obj;

    @Before
    public void setUp() {

        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
        ctx.scan("samples.chapter3");
        ctx.refresh();
        obj = ctx.getBean(PersonOperationsI.class);
//obj = ctx.getBean(PersonOperations.class);//getBean of Child class not working - why ?

        Assert.assertNotNull(obj);
        ctx.close();
    }

    @Test
    public void test() {
        System.out.println(obj.getName());
    }

}

问题1-为什么@componentscan不起作用。如果我在测试用例中不使用AnnotationConfigApplicationContext而仅依赖@componentscan&autowired-测试用例中的对象为null

问题2-ctx.getBean(PersonOperations.class); //子类的getBean无法正常工作-为什么?

最佳答案

  • 通常,您应该将@ComponentScan和带@Configuration注释的类一起使用,并记住 @ComponentScan不带参数会告诉Spring扫描当前包及其所有子包。
  • @Component 类告诉Spring创建该类型的bean,因此您不再需要使用xml配置,并且bean是可以实例化的类=>没有接口/抽象类。因此,在您的情况下,应从PersonOperationsI中删除 @Component ,仅将其保留在PersonOperations中。当您使用 @Component 注释类时,给该bean的默认名称是带有较低首字母的类名称,因此您应该调用ctx.getBean("personOperationsI")ctx.getBean(PersonOperations.class)

  • 对于将来,请阅读这些naming conventions以获取接口和实现。在您的情况下,我将修改以下内容:PersonOperationsIOperations

    09-10 02:54