@Startup @Singleton在WebLogic中实例化两次(EJB 3.1)

我有一个标记为@Startup@Singleton的类,构造函数被调用两次。

为什么被叫两次?

  • WebLogic 12.1.1
  • 本地运行(不是群集)
  • 当@PostConstruct存在时,它也被调用两次
  • 与XML配置无关(weblogic-ejb-jar.xml等)

这是class级:

 import java.util.concurrent.atomic.AtomicInteger; import javax.ejb.Singleton; import javax.ejb.Startup; @Startup @Singleton public class CacheStartupListener { static AtomicInteger count= new AtomicInteger(0); public CacheStartupListener() { System.err.println("Singleton invoked " + count.incrementAndGet() + " " + getClass().getClassLoader().toString()); } } 

我可以从输出中看到构造函数都是从同一个类加载器中调用的。

构造函数中的wlfullclient-12.1.1jar都通过wlfullclient-12.1.1jar ,但wlfullclient-12.1.1jar 其他方面是不同的。

这是第一个实例化的堆栈跟踪:

 Daemon Thread [[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)'] (Suspended (breakpoint at line 30 in CacheStartupListener)) (out of synch) CacheStartupListener_m3hhum_NoIntfViewImpl(CacheStartupListener).() line: 30 (out of synch) CacheStartupListener_m3hhum_NoIntfViewImpl.(SingletonLocalObject) line: not available NativeConstructorAccessorImpl.newInstance0(Constructor, Object[]) line: not available [native method] NativeConstructorAccessorImpl.newInstance(Object[]) line: 57 DelegatingConstructorAccessorImpl.newInstance(Object[]) line: 45 Constructor.newInstance(Object...) line: 525 SingletonEJBLocalHomeImpl.allocateBI(Class) line: 45 SingletonEJBLocalHomeImpl.prepare() line: 30 SingletonSessionBeanInfoImpl(SessionBeanInfoImpl).prepare() line: 458 SingletonSessionBeanInfoImpl.prepare() line: 115 EJBDeployer.setupBeanInfos() line: 767 EJBDeployer.prepare(VirtualJarFile, EjbDescriptorBean) line: 920 EJBModule.prepare() line: 419 ScopedModuleDriver.prepare() line: 188 ExtensibleModuleWrapper.prepare() line: 83 ModuleListenerInvoker.prepare() line: 100 ModuleStateDriver$1.next(Module) line: 172 ModuleStateDriver$1.next(Object) line: 167 StateMachineDriver.nextState(StateChange, StateMachine[]) line: 35 ModuleStateDriver.prepare(Module[]) line: 38 DeploymentCallbackFlow.prepare(Module[]) line: 139 DeploymentCallbackFlow.prepare() line: 55 BaseDeployment$1.next(Object) line: 706 StateMachineDriver.nextState(StateChange, StateMachine[]) line: 35 EarDeployment(BaseDeployment).prepare(DeploymentContext) line: 237 EarDeployment.prepare(DeploymentContext) line: 61 DeploymentStateChecker.prepare(DeploymentContext) line: 158 AppContainerInvoker.prepare(DeploymentContext) line: 60 RedeployOperation.createAndPrepareContainer() line: 104 RedeployOperation.doPrepare() line: 138 RedeployOperation(AbstractOperation).prepare() line: 229 DeploymentManager.handleDeploymentPrepare(Deployment, DeploymentManager$DeploymentRequestInfo) line: 747 DeploymentManager.prepareDeploymentList(ArrayList, DeploymentContext) line: 1216 DeploymentManager.handlePrepare(DeploymentContext) line: 250 DeploymentServiceDispatcher.prepare(DeploymentContext) line: 159 DeploymentReceiverCallbackDeliverer.doPrepareCallback(DeploymentContext) line: 171 DeploymentReceiverCallbackDeliverer.access$000(DeploymentReceiverCallbackDeliverer, DeploymentContext) line: 13 DeploymentReceiverCallbackDeliverer$1.run() line: 46 SelfTuningWorkManagerImpl$WorkAdapterImpl.run() line: 545 ExecuteThread.execute(Runnable) line: 256 ExecuteThread.run() line: 221 

这是第二个实例化的堆栈跟踪:

 Daemon Thread [[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)'] (Suspended (breakpoint at line 30 in CacheStartupListener)) (out of synch) CacheStartupListener_m3hhum_Impl(CacheStartupListener).() line: 30 (out of synch) CacheStartupListener_m3hhum_Impl.() line: not available NativeConstructorAccessorImpl.newInstance0(Constructor, Object[]) line: not available [native method] NativeConstructorAccessorImpl.newInstance(Object[]) line: 57 DelegatingConstructorAccessorImpl.newInstance(Object[]) line: 45 Constructor.newInstance(Object...) line: 525 WeldConstructorImpl.newInstance(Object...) line: 204 ConstructorInjectionPoint.newInstance(BeanManagerImpl, CreationalContext) line: 117 ExtendedSessionBean(SessionBean).createInstance(CreationalContext) line: 212 ExtendedSessionBean.derivedCreateInstance(CreationalContext) line: 35 WeldEjbBeanManager$ExtendedInjectionTarget.produce(CreationalContext) line: 131 WeldEjbBeanManager.newBeanInstance(String) line: 78 InjectionBasedEjbComponentCreator.getBean(String, Class, boolean) line: 75 SingletonSessionManager(BaseEJBManager).createNewBeanInstance() line: 209 SingletonSessionManager.constructAndInitBean() line: 353 SingletonSessionManager.access$300(SingletonSessionManager) line: 63 SingletonSessionManager$SingletonLifecycleManager.doActualInit() line: 798 SingletonSessionManager$SingletonLifecycleManager.initInternal(boolean) line: 744 SingletonSessionManager$SingletonLifecycleManager.init() line: 631 SingletonSessionManager.init() line: 280 SingletonSessionManager.perhapsInit() line: 276 EJBDeployer.initializeBeans() line: 1287 EJBDeployer.start() line: 1174 EJBModule.start() line: 590 ModuleStateDriver$3.next(Module) line: 213 ModuleStateDriver$3.next(Object) line: 208 StateMachineDriver.nextState(StateChange, StateMachine[]) line: 35 ModuleStateDriver.start(Module[]) line: 70 ScopedModuleDriver.start() line: 212 ExtensibleModuleWrapper.start() line: 111 ModuleListenerInvoker.start() line: 124 ModuleStateDriver$3.next(Module) line: 213 ModuleStateDriver$3.next(Object) line: 208 StateMachineDriver.nextState(StateChange, StateMachine[]) line: 35 ModuleStateDriver.start(Module[]) line: 70 StartModulesFlow.activate() line: 24 BaseDeployment$2.next(Object) line: 729 StateMachineDriver.nextState(StateChange, StateMachine[]) line: 35 EarDeployment(BaseDeployment).activate(DeploymentContext) line: 258 EarDeployment.activate(DeploymentContext) line: 61 DeploymentStateChecker.activate(DeploymentContext) line: 165 AppContainerInvoker.activate(DeploymentContext) line: 79 RedeployOperation(AbstractOperation).activate(Deployment) line: 582 RedeployOperation(ActivateOperation).activateDeployment() line: 148 RedeployOperation(ActivateOperation).doCommit() line: 114 RedeployOperation(AbstractOperation).commit() line: 335 DeploymentManager.handleDeploymentCommit(Deployment, AbstractOperation) line: 844 DeploymentManager.activateDeploymentList(ArrayList, DeploymentManager$DeploymentRequestInfo) line: 1253 DeploymentManager.handleCommit(DeploymentContext) line: 440 DeploymentServiceDispatcher.commit(DeploymentContext) line: 163 DeploymentReceiverCallbackDeliverer.doCommitCallback(DeploymentContext) line: 195 DeploymentReceiverCallbackDeliverer.access$100(DeploymentReceiverCallbackDeliverer, DeploymentContext) line: 13 DeploymentReceiverCallbackDeliverer$2.run() line: 68 SelfTuningWorkManagerImpl$WorkAdapterImpl.run() line: 545 ExecuteThread.execute(Runnable) line: 256 ExecuteThread.run() line: 221 

第一个堆栈实际上并不是创建bean实例而是创建代理实例。 您的@Singleton没有声明任何业务接口,因此默认情况下它使用no-interface视图(可以使用@LocalBean显式配置)。 使用无接口视图时,容器会生成一个代理类,该代理类是类的子类(在本例中,代理名为CacheStartupListener_m3hhum_NoIntfViewImpl )。 当容器创建此代理子类的实例时,将调用EJB类的构造函数。 您可以尝试在构造函数中打印getClass()来certificate这一点。

我强烈建议完全删除Java构造函数并将所有初始化逻辑移动到@PostConstruct 。 Java构造函数与无接口视图不能很好地混合。