2013-09-18 3 views
3

Я тренируюсь на весенне-социальном уровне, и кажется, что userConnectionRepository не правильно автоподключен в следующем коде, когда я выполняю «Run as Junit Test» в Eclipse. Я получаю исключение Null указателя на userConnectionRepository при создании новой FacebookOffLine, хотя точки останова, введенные в код создания java-кода @Bean, показывают, что они, кажется, правильно созданы. Спасибо заранее,@Autowire не предварительно загружен с помощью конфигурации Spring @Bean

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")); 

И классы конфигурации Spring адаптирован из Кит Donald Quick Start Sample:

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

} 
+0

Возможный дубликат [Весна 3 автоуровня всегда равна нулю] (http://stackoverflow.com/questions/18861094/spring-3-autowire-is-always-null) – chrylis

ответ

6

На самом деле есть 2 проблемы.

  1. Весна не может autowire бобы не контролирует (т.е. созданные с новым)
  2. Зависимости не доступны в конструкторе (экземпляр объекта необходимо прежде, чем он может быть введен)

Первый можно смягчить, позволяя пружине управлять экземпляром FacebookOffline (или если вам нужно несколько экземпляров сделать запрос на бонус или сеансовое).

Второе немного сложнее, но может быть опробовано с использованием метода, аннотированного @PostConstruct (или путем внедрения InitializingBean с весны).

+0

Спасибо, это были правильные дела. Разделение конструктора с второй частью как initmethod, аннотированное @PostConstruct, заставило его работать нормально. –

0

Spring не autowire поля на экземпляр, который вы создаете через new, так как он об этом не знает. Вместо этого объявите компонент типа FacebookOffline.

+0

Хорошо, но значит ли это, что это еще не все равно autowire UserConnectionRepository, что мне действительно нужно? –

+0

@ YvesNicolas Я разъяснил свой ответ; Spring не может создавать поля для объекта, о котором он не знает (ваш 'FacebookOffline', который вы создаете с помощью' new', а не как компонент Spring). – chrylis

+0

Спасибо за разъяснение, выглядит как хороший путь для следования. Проделайте несколько тестов вокруг этого. –

2

Вы сделали

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

Это означает, что весна не управляет этой essai экземпляром и, таким образом, пружина не может autowire переменных в essai.

Вам необходимо создать фасоль FacebookOffline в SocialConfig.

Тогда вы можете иметь

/* ... */ 
public class FacebookOfflineTest { 

@Autowired 
ApplicationContext context; 

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

ИЛИ

/* ... */ 
public class FacebookOfflineTest { 

@Autowired 
FacebookOffline essai; 

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

Кроме того, вам нужно обновить 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(); 
    } 
} 
+0

Пробовал вторую часть, но ничего не изменил, пользователиConnectionRepository все еще не были созданы. Похоже, 3-й ответ на сообщение дает потенциальную вескую причину для taht. –

+0

Да, я полностью пропустил, что вы делаете это в конструкторе. Я обновлю свой ответ, и вы можете попробовать. – TheKojuEffect

Смежные вопросы