Java @Autowire未预先注入Spring@Bean配置

Java @Autowire未预先注入Spring@Bean配置,java,spring,dependency-injection,autowired,Java,Spring,Dependency Injection,Autowired,我正在练习SpringSocial,当我在Eclipse中执行“RunasJUnit测试”时,下面的代码中的userConnectionRepository似乎没有正确地自动连接。在创建新的FacebookOffLine时,我在usersConnectionRepository上得到一个空指针异常,尽管@BeanJava创建代码中的断点显示它们似乎被正确创建。提前感谢, public class FacebookOffline { private Facebook fb; @

我正在练习SpringSocial,当我在Eclipse中执行“RunasJUnit测试”时,下面的代码中的userConnectionRepository似乎没有正确地自动连接。在创建新的FacebookOffLine时,我在usersConnectionRepository上得到一个空指针异常,尽管@BeanJava创建代码中的断点显示它们似乎被正确创建。提前感谢,

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

}
以下是测试代码:

@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"));
以及根据Keith Donald Quick Start示例改编的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;
    }

}

Spring无法在您通过
new
创建的实例上自动关联字段,因为它不知道。改为声明类型为
FacebookOffline
的bean。

您这样做了

FacebookOffline essai = new FacebookOffline(new User("yves"));
这意味着Spring没有管理这个
essai
实例,因此Spring无法自动关联
essai
中的任何变量

您必须在
SocialConfig
中创建
FacebookOffline
的bean

那你就可以

/* ... */
public class FacebookOfflineTest {

@Autowired
ApplicationContext context;

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

此外,您还需要更新
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();
   }
}

实际上这里有两个问题

  • Spring无法自动连接它不控制的bean(即,使用new创建)
  • 依赖项在构造函数中不可用(需要对象实例才能注入)
  • 第一个问题可以通过让spring管理FacebookOffline的一个实例来缓解(或者如果需要多个实例,则将bean请求或会话范围限定)


    第二个问题有点难,但可能可以通过使用带有
    @PostConstruct
    注释的方法(或者通过从spring实现
    初始化bean
    )来解决。

    好的,但这是否意味着它不应该仍然自动连接我真正需要的UsersConnectionRepository?@YvesNicolas我澄清了我的答案;Spring无法在它不知道的对象上自动关联字段(您的
    FacebookOffline
    ,您正在通过
    new
    而不是作为Spring bean创建该对象)。感谢您的澄清,这看起来是一条很好的路径。将对此进行一些测试。可能重复了第二部分,但没有改变任何内容,usersConnectionRepository尚未实例化。看起来这篇文章的第三个答案给了塔希亚一个很好的理由,我完全没有意识到你在做这个。我会更新我的答案,你可以试试。谢谢,这是正确的做法。将构造函数与第二部分拆分为@PostConstruct注释的initmethod使其工作正常。
    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();
       }
    }