Я пытаюсь создать проект Spring, который использует MyBatis для уровня доступа к данным в качестве доказательства концепции для моей команды. Я действительно хочу избежать конфигурации XML, если это вообще возможно, поэтому я пытаюсь связать все вместе, используя аннотированные классы @Configuration.
Кажется, что все правильно подключено, но мой сопоставитель beans не подключен к моему сервису в AutoWired.
В моем примере я пытаюсь связать UserDao, объект пользователя и UserService.
UserDao
public interface UserDao {
@Select("SELECT * FROM users WHERE id = #{userId}")
User get(@Param("userId") Integer userId);
}
Пользователь
@Component("User")
public class User implements Entity {
public Integer userId;
public String username;
/** ... getters/setters ommitted **/
}
UserServiceImpl
@Service("UserService")
public class UserServiceImpl {
private UserDao userDao = null;
public User getUserDetails(Integer userId) {
return userDao.get(userId);
}
@Autowired
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
Я соединяю их вместе, используя два класса конфигурации.
ApplicationContextConfig
@Configuration
@EnableLoadTimeWeaving(aspectjWeaving=AspectJWeaving.ENABLED)
@Import(DefaultDataAccessConfig.class) // I'm importing this because I thought ordering might be important, otherwise I was hoping to just let the component scanning pull in additional configuration files
@ComponentScan(basePackages="com.example.gwtspringpoc.server",
[email protected](type=FilterType.ANNOTATION,
value=Controller.class))
public class ApplicationContextConfig {
/** No bean definitions needed here **/
}
DefaultDataAccessConfig
@Configuration
@EnableTransactionManagement
public class DefaultDataAccessConfig implements TransactionManagementConfigurer {
@Bean
public DataSource dataSource() {
OracleDataSource ods = null;
try {
ods = new OracleDataSource();
} catch (SQLException e) {
throw new RuntimeException(e);
}
ods.setURL("jdbc:oracle:thin:@//localhost:9601/sid");
ods.setUser("user");
ods.setPassword("pass");
return ods;
}
@Override
@Bean(name="transactionManager")
public PlatformTransactionManager annotationDrivenTransactionManager() {
return new DataSourceTransactionManager(dataSource());
}
@Bean
public SqlSessionFactory sqlSessionFactory() {
SqlSessionFactoryBean sf = new SqlSessionFactoryBean();
sf.setDataSource(dataSource());
try {
return (SqlSessionFactory) sf.getObject();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Bean
public SqlSession sqlSessionTemplate() {
return new SqlSessionTemplate(sqlSessionFactory());
}
/*
* This did not work at all. It seems to be configured correctly, but the UserDao bean never
* got created at any stage, which was very disappointing as I was hoping not to have to
* create a bean definition for each DAO manually
*/
/*@Bean
public static MapperScannerConfigurer mapperScannerConfig() {
MapperScannerConfigurer msc = new MapperScannerConfigurer();
msc.setBasePackage("com.ca.spna.gwtspringpoc.server.model.dao");
msc.setAnnotationClass(Repository.class);
return msc;
}*/
/*
* Because the above code did not work, I decided to create the mapping manually.
* This is most likely my problem - something about this setup. My understanding
* is that the MapperFactoryBean once instantiated by Spring, will create a proxy
* object of type UserDao with the name "userDao" that can be injected elsewhere.
*/
@Bean
public MapperFactoryBean<UserDao> userDao() {
MapperFactoryBean<UserDao> mfb = new MapperFactoryBean<UserDao>();
mfb.setMapperInterface(UserDao.class);
return mfb;
}
}
Вы можете прочитать комментарии выше двух последних методов в приведенном выше фрагменте кода, чтобы получить более полное представление о том, как я создаю UserDao bean.
Как только я получил всю настройку конфигурации, я создал unit test, чтобы попробовать протестировать UserService с помощью AnnotationConfigContextLoader, но сразу же попал со следующим исключением, когда пытаясь запустить тест:
Exception
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void com.example.gwtspringpoc.server.service.UserServiceImpl.setUserDao(com.example.gwtspringpoc.server.model.dao.UserDao); nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.example.gwtspringpoc.server.model.dao.UserDao] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
После этого я прокомментировал @Autowired в UserService и вернулся к моему unit test и ввел ApplicationContext, поэтому Я мог бы проверить его, а bean с именем "userDao" на самом деле является экземпляром MapperProxy.
Итак, я понимаю, как работает MapperFactoryBean, или это просто не очень совместимо с конфигурацией, управляемой аннотациями? Кроме того, если кто-нибудь знает, как сделать работу MapperScannerConfigurer корректной, я был бы очень признателен!