所以我基本上有了这个设置:
我有一个在WAS 8.5.5上运行的应用程序,它使用此项目的Web-API将CRM同步到EMS。我负责创建一个Webfrontend来维持这些同步。要显示数据库值,我只是在html上打印数据库表。
我已经创建了一个小结构,进入代码片段时您会理解的。
此项目的工作流程基本上是轮询同步,并将结果数据收集到数据库中。我的前端负责显示收集的数据。为此,我使用了pojo的子类来对应客户端,因为我的前端能够采用从父类继承的任何形式的网格。
孩子从父类网格继承:
public class Grid {
private List<String> columnNames;
private List<Page> pages; //this are custom pages consisting of a specific amount of tablerows
private int currentPageIndex;
private boolean isSortedDescending;
//Getters and Setters
}
子类是:
HistoryGrid:
@Component
@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class HistoryGrid extends Grid{
private HistoryAttributes sortedBy; //this is a enumvalue
//Getter and Setter
}
和HistoryDetailGrid:
@Component
public class HistoryDetailGrid extends Grid {
private long historyEntryId; //to map the details to its Histories
private HistoryDetailAttributes sortedBy; //this is a enumvalue
//Getters and Setters
两个网格都代表数据库表,并且是1:n关系,每个历史记录条目都有n个历史细节条目。
比我的Businesslogic类遵循相同的继承模式:
GridService:
public abstract class GridService {
Grid grid;
public void nextPage() {
... //this needs the grid-variable
}
public void lastPage() {
... //this needs the grid-variable
}
//Getter and Setter
public abstract void initGrid();
public abstract void createPages();
public abstract void filter(Object property, String valueFilteredBy);
public abstract void sort(Object property, boolean isDescending);
}
The HistoryGridService:
@Service
public class HistoryGridService extends GridService {
@Autowired
private HistoryGrid hg;
@Override
public void createPages() {
...
}
@Override
public void initGrid() {
...
}
@Override
public void filter(Object property, String valueFilteredBy) {
...
}
@Override
public void sort(Object property, boolean isDescending) {
...
}
//Getters and Setters
}
和HistoryDetailGridService:
@Service
public class HistoryDetailGridService extends GridService {
@Autowired
HistoryDetailGrid hdg;
public void initGridByCsv() {
...
}
@Override
public void initGrid() {
...
}
@Override
public void createPages() {
...
}
@Override
public void filter(Object property, String valueFilteredBy) {
...
}
@Override
public void sort(Object property, boolean isDescending) {
...
}
}
为了简单起见,我删除了所有不必要的属性和逻辑,无需关注这一点。
启动应用程序时出现此异常:
com.ibm.ws.webcontainer.servlet.ServletWrapper init SRVE0271E: Uncaught init() exception created by servlet [dispatcher] in application [MyProjectEAR]: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'historyGridService': Unsatisfied dependency expressed through field 'grid'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.me.my_project.web.Grid' available: expected single matching bean but found 2: historyDetailGrid,historyGrid
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:588)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543)
at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:668)
at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:540)
at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:494)
at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:171)
at javax.servlet.GenericServlet.init(GenericServlet.java:161)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.init(ServletWrapper.java:345)
at com.ibm.ws.webcontainer.servlet.ServletWrapperImpl.init(ServletWrapperImpl.java:168)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.loadOnStartupCheck(ServletWrapper.java:1369)
at com.ibm.ws.webcontainer.webapp.WebApp.doLoadOnStartupActions(WebApp.java:642)
at com.ibm.ws.webcontainer.webapp.WebApp.commonInitializationFinally(WebApp.java:608)
at com.ibm.ws.webcontainer.webapp.WebAppImpl.initialize(WebAppImpl.java:426)
at com.ibm.ws.webcontainer.webapp.WebGroupImpl.addWebApplication(WebGroupImpl.java:88)
at com.ibm.ws.webcontainer.VirtualHostImpl.addWebApplication(VirtualHostImpl.java:171)
at com.ibm.ws.webcontainer.WSWebContainer.addWebApp(WSWebContainer.java:904)
at com.ibm.ws.webcontainer.WSWebContainer.addWebApplication(WSWebContainer.java:789)
at com.ibm.ws.webcontainer.component.WebContainerImpl.install(WebContainerImpl.java:427)
at com.ibm.ws.webcontainer.component.WebContainerImpl.start(WebContainerImpl.java:719)
at com.ibm.ws.runtime.component.ApplicationMgrImpl.start(ApplicationMgrImpl.java:1211)
at com.ibm.ws.runtime.component.DeployedApplicationImpl.fireDeployedObjectStart(DeployedApplicationImpl.java:1452)
at com.ibm.ws.runtime.component.DeployedModuleImpl.start(DeployedModuleImpl.java:641)
at com.ibm.ws.runtime.component.DeployedApplicationImpl.start(DeployedApplicationImpl.java:1034)
at com.ibm.ws.runtime.component.ApplicationMgrImpl.startApplication(ApplicationMgrImpl.java:795)
at com.ibm.ws.runtime.component.ApplicationMgrImpl$5.run(ApplicationMgrImpl.java:2279)
at com.ibm.ws.security.auth.ContextManagerImpl.runAs(ContextManagerImpl.java:5482)
at com.ibm.ws.security.auth.ContextManagerImpl.runAsSystem(ContextManagerImpl.java:5698)
at com.ibm.ws.security.core.SecurityContext.runAsSystem(SecurityContext.java:255)
at com.ibm.ws.runtime.component.ApplicationMgrImpl.start(ApplicationMgrImpl.java:2284)
at com.ibm.ws.runtime.component.CompositionUnitMgrImpl.start(CompositionUnitMgrImpl.java:436)
at com.ibm.ws.runtime.component.CompositionUnitImpl.start(CompositionUnitImpl.java:123)
at com.ibm.ws.runtime.component.CompositionUnitMgrImpl.start(CompositionUnitMgrImpl.java:379)
at com.ibm.ws.runtime.component.CompositionUnitMgrImpl.access$500(CompositionUnitMgrImpl.java:127)
at com.ibm.ws.runtime.component.CompositionUnitMgrImpl$CUInitializer.run(CompositionUnitMgrImpl.java:985)
at com.ibm.wsspi.runtime.component.WsComponentImpl$_AsynchInitializer.run(WsComponentImpl.java:524)
at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1892)
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.me.my_project.web.Grid' available: expected single matching bean but found 2: historyDetailGrid,historyGrid
at org.springframework.beans.factory.config.DependencyDescriptor.resolveNotUnique(DependencyDescriptor.java:173)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1116)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
... 46 more
该异常基本上说我的HistoryGridService无法注入Grid,这有点令人困惑,因为HistoryGridService不应该对网格有任何了解,因为它正在使用Grids子级-> HistoryGrid。Springs IoC容器也不应该对网格有任何了解,它不是bean。
那么这个异常怎么可能发生,我该如何解决?
我的期望是HistoryGridService应该能够注入HistoryGrid而不是Grid。
提前感谢。
编辑1@ M。 Deinum的方法
所以我做到了:
@Service
public class HistoryGridService extends GridService {
public class Config {
@Bean
public HistoryGrid historyGrid() {
return new HistoryGrid();
}
}
private final HistoryGrid HG;
public HistoryGridService(HistoryGrid hg) {
super(hg);
HG = hg;
}
...
}
请注意以下事实:我无法使hg最终化,因为它将在每种方法中进行更新。
和在GridService中:
public abstract class GridService {
private Grid grid;
public GridService(Grid grid) {
this.grid = grid;
}
但是这种方法导致此异常:
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:189)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1193)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1095)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543)
at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:668)
at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:540)
at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:494)
at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:171)
at javax.servlet.GenericServlet.init(GenericServlet.java:161)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.init(ServletWrapper.java:345)
at com.ibm.ws.webcontainer.servlet.ServletWrapperImpl.init(ServletWrapperImpl.java:168)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.loadOnStartupCheck(ServletWrapper.java:1369)
at com.ibm.ws.webcontainer.webapp.WebApp.doLoadOnStartupActions(WebApp.java:642)
at com.ibm.ws.webcontainer.webapp.WebApp.commonInitializationFinally(WebApp.java:608)
at com.ibm.ws.webcontainer.webapp.WebAppImpl.initialize(WebAppImpl.java:426)
at com.ibm.ws.webcontainer.webapp.WebGroupImpl.addWebApplication(WebGroupImpl.java:88)
at com.ibm.ws.webcontainer.VirtualHostImpl.addWebApplication(VirtualHostImpl.java:171)
at com.ibm.ws.webcontainer.WSWebContainer.addWebApp(WSWebContainer.java:904)
at com.ibm.ws.webcontainer.WSWebContainer.addWebApplication(WSWebContainer.java:789)
at com.ibm.ws.webcontainer.component.WebContainerImpl.install(WebContainerImpl.java:427)
at com.ibm.ws.webcontainer.component.WebContainerImpl.start(WebContainerImpl.java:719)
at com.ibm.ws.runtime.component.ApplicationMgrImpl.start(ApplicationMgrImpl.java:1211)
at com.ibm.ws.runtime.component.DeployedApplicationImpl.fireDeployedObjectStart(DeployedApplicationImpl.java:1452)
at com.ibm.ws.runtime.component.DeployedModuleImpl.start(DeployedModuleImpl.java:641)
at com.ibm.ws.runtime.component.DeployedApplicationImpl.start(DeployedApplicationImpl.java:1034)
at com.ibm.ws.runtime.component.ApplicationMgrImpl.startApplication(ApplicationMgrImpl.java:795)
at com.ibm.ws.runtime.component.ApplicationMgrImpl$5.run(ApplicationMgrImpl.java:2279)
at com.ibm.ws.security.auth.ContextManagerImpl.runAs(ContextManagerImpl.java:5482)
at com.ibm.ws.security.auth.ContextManagerImpl.runAsSystem(ContextManagerImpl.java:5698)
at com.ibm.ws.security.core.SecurityContext.runAsSystem(SecurityContext.java:255)
at com.ibm.ws.runtime.component.ApplicationMgrImpl.start(ApplicationMgrImpl.java:2284)
at com.ibm.ws.runtime.component.CompositionUnitMgrImpl.start(CompositionUnitMgrImpl.java:436)
at com.ibm.ws.runtime.component.CompositionUnitImpl.start(CompositionUnitImpl.java:123)
at com.ibm.ws.runtime.component.CompositionUnitMgrImpl.start(CompositionUnitMgrImpl.java:379)
at com.ibm.ws.runtime.component.CompositionUnitMgrImpl.access$500(CompositionUnitMgrImpl.java:127)
at com.ibm.ws.runtime.component.CompositionUnitMgrImpl$CUInitializer.run(CompositionUnitMgrImpl.java:985)
at com.ibm.wsspi.runtime.component.WsComponentImpl$_AsynchInitializer.run(WsComponentImpl.java:524)
at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1892)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.me.my_project.services.HistoryDetailGridService$Config': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'historyDetailGridService': Requested bean is currently in creation: Is there an unresolvable circular reference?
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:189)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1193)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1095)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:372)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1173)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1067)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1138)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741)
... 46 more
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'historyDetailGridService': Requested bean is currently in creation: Is there an unresolvable circular reference?
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.beforeSingletonCreation(DefaultSingletonBeanRegistry.java:347)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1138)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741)
... 69 more
编辑2修复
跟随@M。建议Deinum我能够解决此问题。这两个子类现在都有一个参数化的构造函数,可以接受HistoryGrid或HistoryDetailGrid的实例。在创建bean时,将从IoC容器中隐式注入这些。
public abstract class GridService {
private final Grid GRID;
public GridService(Grid grid) {
GRID = grid;
}
...
}
@Service
public class HistoryDetailGridService extends GridService {
private final HistoryDetailGrid HDG;
public HistoryDetailGridService(HistoryDetailGrid hdg) {
super(hdg);
HDG = hdg;
}
...
}
在这种情况下,Grid类被两个类(HistoryGrid和HistoryDetailGrid)扩展,Spring将不知道要注入两个实现中的哪个:在创建时区分bean名称,需要指定一个限定符。
--------------------------
public class Grid {
......
......
//added this method to show which implementation is invoked
public void printClassName(){
System.out.println("In Grid");
}
}
@Component("historyDetailGrid")
public class HistoryDetailGrid extends Grid {
......
......
@Override
public void printClassName(){
System.out.println("Inside historyDetail Grid");
}
}
@Component("historyGrid")
public class HistoryGrid extends Grid {
.......
.......
@Override
public void printClassName(){
System.out.println("Inside history Grid");
}
}
public abstract class GridService {
//Removed grid declaration and get grid object as method param
public void nextPage(Grid grid) {
}
public void lastPage(Grid grid) {
}
/**
* To show which implementation class is invoked from main method
*/
public abstract void printClassName();
public abstract void createPages();
public abstract void filter(Object property, String valueFilteredBy);
public abstract void sort(Object property, boolean isDescending);
}
@Service("historyDetailGridService")
public class HistoryDetailGridService extends GridService {
@Autowired
@Qualifier("historyDetailGrid")
Grid hdg;
@Override
public void printClassName() {
hdg.printClassName();
}
// other abstract methods
.....
}
@Service("historyGridService")
public class HistoryGridService extends GridService {
@Autowired
@Qualifier("historyGrid")
private Grid hg;
@Override
public void printClassName() {
hg.printClassName();
}
// other abstract methods
.....
}
@SpringBootApplication
@ComponentScan({"com.*"})
public class Main {
@Autowired
@Qualifier("historyDetailGridService")
GridService historyDetailGridService;
@Autowired
@Qualifier("historyGridService")
GridService historyGridService;
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
@PostConstruct
public void printClasses(){
historyGridService.printClassName();
historyDetailGridService.printClassName();
}
}
----------------
output will be
Inside history Grid
Inside historyDetail Grid
2019-10-09 21:34:31.356 INFO 3235 --- [ main] com.service.Main : Started Main in 1.439 seconds (JVM running for 1.791)
-----------------