我有一个Spring课程。
@Service("dbManager")
@Repository
@Transactional
public class DatabaseManager {
GenericXmlApplicationContext context;
@PersistenceContext
private EntityManager em;
public DatabaseManager(GenericXmlApplicationContext context) {
this.context = context;
}
....
} //end of class DatabaseManager
我有SpringUtil类
public class SpringUtil {
public static GenericXmlApplicationContext loadSpringContext(String springXmlFile) {
GenericXmlApplicationContext context = new GenericXmlApplicationContext();
context.load(springXmlFile);
context.refresh();
return context;
} //end of loadSpringContext()
} //end of class SpringUtil
现在我正在使用像
这样的东西public class Regulator {
public static void main( String[] args ) {
Test test = new Test;
test.start();
} //end of main()
} //end of class Regulator
这是测试类
public class Test {
public void start() {
String springXmlFile = "classpath:spring/plcb-app-context-xml.xml";
GenericXmlApplicationContext context = SpringUtil.loadSpringContext(springXmlFile);
} //end of reportStudent()
} //end of class Test
但是我收到错误
Could not instantiate bean class [...DatabaseManager]: No default constructor
found; nested exception is java.lang.NoSuchMethodException:
...DatabaseManager.<init>()
我希望在创建DatabaseManager
类时,然后使用SpringUtil.loadSpringContext(springXmlFile)
创建的spring context taht必须传递给它。我该怎么办?
由于
修改 -------------------
public void switchDataSource(DatabaseType databaseType) {
DriverManagerDataSource dataSource = null;
if (databaseType == DatabaseType.LEGACY) {
dataSource = (DriverManagerDataSource)context.getBean("myLegacyDataSource");
} else if (databaseType == DatabaseType.LS360) {
dataSource = (DriverManagerDataSource)context.getBean("myLs360DataSource");
}
LocalContainerEntityManagerFactoryBean emf = context.getBean("myEmf", LocalContainerEntityManagerFactoryBean.class);
emf.setDataSource(dataSource);
}
@SuppressWarnings("unchecked")
@Transactional(readOnly=true)
public List<Object> getResultList(String query, Class mappingClass) throws Exception {
Query emQuery = em.createNativeQuery(query, mappingClass);
return emQuery.getResultList();
} //end of findTraineeFromLegacy()
实际上我的DatabaseManager类中有这两种方法。我正在设置上下文,所以我可以从switchDataSource()
方法中的上下文中获取bean。
我可以做的一件事就是删除实例并将方法更改为
public void switchDataSource(DatabaseType databaseType, GenericXmlApplicationContext context) {
....
}
这就是我这样做的原因?
由于
答案 0 :(得分:2)
为DatabaseManager建立一个no-arg构造函数。
在DatabaseManager中实现ApplicationContextAware。 Spring会知道这个bean需要通知应用程序上下文:
@Service("dbManager")
@Repository
@Transactional
public class DatabaseManager implements ApplicationContextAware {
private ApplicationContext context;
public DatabaseManager() {...}
@Override
public void setApplicationContext(ApplicationContext appContext) {
this.context = appContext;
}
} //end of class DatabaseManager
但是,如果你真的需要注射的话,请考虑一下。在大多数情况下,你做错了。
更新
对于您的更新中的要求,您希望数据库管理器根据输入类型切换数据源,尽管执行此类操作似乎不太常见,但您可以简单地为数据库管理器注入Map并执行任何操作你想要的,而不是注入应用程序上下文。
@Service("dbManager")
@Repository
@Transactional
public class DatabaseManager implements ApplicationContextAware {
@Resource("&emfBean")
private LocalContainerEntityManagerFactoryBean emfBean;
@Resource("dbManagerDsMap")
private Map<DatabaseType, Datasource> dsMapping;
public DatabaseManager() {...}
public void switchDataSource(DatabaseType databaseType) {
emfBean.setDatasource(dsMapping.get(databaseType));
}
} //end of class DatabaseManager
但是我强烈建议你不要这样做。考虑为要连接的每个数据库设置单独的entityManagerFactory,并使用正确的emf连接到DB,而不是使用这种奇怪的切换逻辑。我相信应用程序启动后不应该更改。