简体   繁体   English

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

[英]@Autowire not preperly injected with Spring @Bean configuration

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. 我在spring-social上练习,当我在Eclipse中执行“Run as Junit Test”时,似乎userConnectionRepository在以下代码中没有正确自动装配。 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. 在创建新的FacebookOffLine时,我在usersConnectionRepository上获得Null指针异常,尽管@Bean java创建代码中的断点显示它们似乎已正确创建。 Thanks in advance, 提前致谢,

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

}

Actually there are 2 problems here. 实际上这里有两个问题。

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

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 InitializingBean from spring). 第二个是有点难,但可以通过使用@PostConstruct注释的方法(或通过从spring实现InitializingBean )来解决。

You did 你做到了

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

That means, Spring isn't managing this essai instance and thus spring can't autowire any variables in the essai . 这意味着,Spring并没有管理这个essai实例,因此spring无法在essai自动装配任何变量。

You'll have to create bean of FacebookOffline in SocialConfig . 你必须在SocialConfig创建FacebookOffline bean。

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

Spring can't autowire fields on an instance you create via new since it doesn't know about it. Spring无法在您通过new创建的实例上自动装配字段,因为它不知道它。 Declare a bean of type FacebookOffline instead. 声明一个类型为FacebookOffline的bean。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM