Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.2k views
in Technique[技术] by (71.8m points)

spring - Java aop ComponentScan not working & AnnotationConfigApplicationContext getBean not working

I wrote a simple set of classes to show a friend about using Annotations for AOP (instead of xml config) . We couldnt get the @ComponentScan to work AND AnnotationConfigApplicationContext getBean too misbehaves. I wanted to understand two things . See Code below :

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());
    }

}

Question1 - Why @componentscan doesnt work .If I dont use AnnotationConfigApplicationContext in test case and just rely on @componentscan & autowired - the object in test case is null

Question2 - ctx.getBean(PersonOperations.class);//getBean of Child class not working - why ?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
  1. Usually you should use @ComponentScan along with a @Configuration annotated class and keep in mind that @ComponentScan without arguments tells Spring to scan the current package and all of its sub-packages..

  2. The @Component class tells Spring to create a bean of that type so you no longer need to use xml configuration, and the bean is a class that can be instantiated => no interface / abstract classes. So, in your case, you should remove the @Component from PersonOperationsI and leave it only in PersonOperations. When you annotate a class with @Component, the default name given to the bean is the class name with lower first letter, so you should call ctx.getBean("personOperationsI") or ctx.getBean(PersonOperations.class)

And for the future read these naming conventions for interfaces and implementations. In your case I would modify the following : PersonOperationsI to Operations


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...