2014-11-06 48 views
0

我做了一個示例程序泄露我的問題:爲什麼@Autowired在應用程序和測試中的工作方式不同?

package test; 

public interface InterfaceA { 
} 

package test; 

public class ClassA implements InterfaceA { 
} 

package test; 

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.context.annotation.AnnotationConfigApplicationContext; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.Configuration; 

@Configuration 
public class Application { 

    @Bean 
    public InterfaceA beanA() { 
     return new ClassA(); 
    } 

    @Autowired 
    private ClassA beanA; 

    public static void main(String[] args) { 
     AnnotationConfigApplicationContext applicationContext 
       = new AnnotationConfigApplicationContext(Application.class); 
    } 

} 

@Autowired不與該應用程序代碼的具體類的工作。

package test; 

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; 

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(classes = Application.class) 
public class ApplicationTest { 

    @Autowired 
    ClassA beanA; 

    @Test 
    public void di() { 
     System.out.println(beanA); 
    } 

} 

但是@Autowired在這個測試代碼中與具體類一起工作。

爲什麼@Autowired在應用程序和測試中的工作方式不同?

我共享上面的代碼爲:

https://github.com/izeye/SpringTest

回答

0

您目前使用的應用程序上下文在應用程序的主入口點。在您的情況下額外的「主」類線,像這樣:

@Autowired 
Application context; 

在您的測試,你正在做啓動應用程序上下文的時候,你使用註釋:@ContextConfiguration(類=應用。類)。

在您的具體示例中,您正在引用與您嘗試使用它的同一類中的上下文。當您在main中初始化上下文時,正在運行代碼的Application實例已經實例化,並沒有自動裝配,因爲在實例化時沒有任何使用的上下文。

+0

自動佈線接口在兩者都可以正常工作。 我的問題是爲什麼只有在測試應用程序上下文Autowired與具體類的作品,當豆註冊接口。 – 2014-11-07 01:23:12

0

這是一個有點棘手:

解決方案將是使beanA靜態方法,並與@Lazy@DependsOn(value="beanA")註解註釋Application。即是這樣的:

@Configuration 
@Lazy 
public class Application { 

@Bean 
public static InterfaceA beanA() { 
    return new ClassA(); 
} 

@Autowired 
private ClassA beanA; 

public static void main(String[] args) { 
    AnnotationConfigApplicationContext applicationContext 
      = new AnnotationConfigApplicationContext(Application.class); 
} 
} 

原因:實際beanA bean創建春天需要首先實例Application類。在試圖解決對beanA的引用時,由於沒有實際的實現存在,唯一的信息容器對此未來bean的類型是它的類型(InterfaceA)。

但是,在測試類的情況下,已經初始化上下文,並且bean可以通過物理上已經創建的實際實現類來解析。如果您將嘗試從任何其他彈簧組件中按類別引用beanA,也是如此。

相關問題