Java @Autowire 没有预先注入 Spring @Bean 配置

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18865037/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 11:44:59  来源:igfitidea点击:

@Autowire not preperly injected with Spring @Bean configuration

javaspringdependency-injectionautowired

提问by Yves Nicolas

I am practising on spring-social and it seems that the userConnectionRepository is not properly autowired in the following code when I do a "Run as Junit Test" in Eclipse. I get a Null pointer exception on the usersConnectionRepository when creating a new FacebookOffLine although breakpoints put in the @Bean java creation code shows that they seem to be properly created. Thanks in advance,

我正在 spring-social 上练习,当我在 Eclipse 中执行“Run as Junit Test”时,userConnectionRepository 似乎没有在以下代码中正确自动装配。在创建新的 FacebookOffLine 时,我在 usersConnectionRepository 上收到空指针异常,尽管 @Bean java 创建代码中的断点显示它们似乎已正确创建。提前致谢,

public class FacebookOffline {

    private Facebook fb;

    @Autowired
    private UsersConnectionRepository usersConnectionRepository;

    public FacebookOffline(User user) {
        super();

        ConnectionRepository cr = usersConnectionRepository.createConnectionRepository(user.getId());
        fb = cr.getPrimaryConnection(Facebook.class).getApi();
    }

}

Here is the test code :

这是测试代码:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {
        org.springframework.social.quickstart.config.MainConfig.class,
        org.springframework.social.quickstart.config.SocialConfig.class })
public class FacebookOfflineTest {

    @Test
    public void test1() {
        FacebookOffline essai = new FacebookOffline(new User("yves"));

And the Spring configuration classes adapted from Keith Donald Quick Start Sample :

以及改编自 Keith Donald Quick Start Sample 的 Spring 配置类:

@Configuration
@ComponentScan(basePackages = "org.springframework.social.quickstart", excludeFilters = { @Filter(Configuration.class) })
@PropertySource("classpath:org/springframework/social/quickstart/config/application.properties")
public class MainConfig {

    @Bean
    public DataSource datasource() {
        DriverManagerDataSource toReturn = new DriverManagerDataSource("jdbc:mysql://localhost:3306/spring_social");
        toReturn.setDriverClassName("com.mysql.jdbc.Driver");
        toReturn.setUsername("spring");
        toReturn.setPassword("spring");
        return toReturn;

    }
}

@Configuration
public class SocialConfig {

    @Inject
    private Environment environment;

    @Inject
    private DataSource dataSource;

    @Bean
    public ConnectionFactoryLocator connectionFactoryLocator() {
        ConnectionFactoryRegistry registry = new ConnectionFactoryRegistry();
        registry.addConnectionFactory(new FacebookConnectionFactory(environment
                .getProperty("facebook.clientId"), environment
                .getProperty("facebook.clientSecret")));
        return registry;
    }

@Bean
    public UsersConnectionRepository usersConnectionRepository() {
        JdbcUsersConnectionRepository repository = new JdbcUsersConnectionRepository(
                dataSource, connectionFactoryLocator(), Encryptors.noOpText());
        return repository;
    }

}

采纳答案by M. Deinum

Actually there are 2 problems here.

其实这里有2个问题。

  1. Spring cannot autowire beans it doesn't control (i.e. created with new)
  2. Dependencies aren't available in the constructor (an object instance is needed before it can be injected)
  1. Spring 不能自动装配它不受控制的 bean(即用 new 创建)
  2. 依赖项在构造函数中不可用(在注入之前需要一个对象实例)

The first one can be mitigated by letting spring manage an instance of FacebookOffline (or if you need multiple instances make the bean request or session scoped).

第一个可以通过让 spring 管理 FacebookOffline 的实例来缓解(或者如果您需要多个实例使 bean 请求或会话范围限定)。

The second is a bit harder but can probaly solved by using a method annotated with @PostConstruct(or by implementing InitializingBeanfrom spring).

第二个有点难,但可以通过使用注释的方法@PostConstruct(或InitializingBean从 spring实现)来解决。

回答by chrylis -cautiouslyoptimistic-

Spring can't autowire fields on an instance you create via newsince it doesn't know about it. Declare a bean of type FacebookOfflineinstead.

Spring 无法在您创建的实例上自动装配字段,new因为它不知道它。FacebookOffline改为声明一个 bean 类型。

回答by TheKojuEffect

You did

你做到了

FacebookOffline essai = new FacebookOffline(new User("yves"));

That means, Spring isn't managing this essaiinstance and thus spring can't autowire any variables in the essai.

这意味着,Spring 不管理此essai实例,因此 spring 无法自动装配essai.

You'll have to create bean of FacebookOfflinein SocialConfig.

你必须创建 bean of FacebookOfflinein SocialConfig

Then you can have

然后你可以有

/* ... */
public class FacebookOfflineTest {

@Autowired
ApplicationContext context;

@Test
public void test1() {
    FacebookOffline essai = context.getBean(FacebookOffline.class);

OR

或者

 /* ... */
public class FacebookOfflineTest {

@Autowired
FacebookOffline essai;

@Test
public void test1() {
    // You can use essai now

Also, you'll need to update FacebookOfflineas Dependencies ain't available in constructor.

此外,您需要更新,FacebookOffline因为依赖项在构造函数中不可用。

public class FacebookOffline {

private Facebook fb;

@Autowired
private UsersConnectionRepository usersConnectionRepository;

public FacebookOffline(User user) {
    super();  
}

@PostConstruct
void loadFacebook() {
    ConnectionRepository cr =       usersConnectionRepository.createConnectionRepository(user.getId());
     fb = cr.getPrimaryConnection(Facebook.class).getApi();
   }
}