@Startup @Singleton在WebLogic中实例化两次(EJB 3.1) [英] @Startup @Singleton instantiated twice in WebLogic (EJB 3.1)
问题描述
我有一个标记为 @Startup
和 @Singleton
的类,并且构造函数被调用两次。
I have a class marked @Startup
and @Singleton
and the constructor is being called twice.
为什么要两次被叫?
- WebLogic 12.1.1
- 本地运行(非集群)
- @PostConstruct在它出现时也被调用两次
- XML配置中没有任何相关内容(weblogic-ejb-jar.xml等)
- WebLogic 12.1.1
- Running Locally (not cluster)
- @PostConstruct is also called twice when it is there
- Nothing relevant in XML configuration (weblogic-ejb-jar.xml et al)
这是类:
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());
}
}
我可以从输出中看到构造函数正在两次从相同的类加载器调用。
I can see from the output the the constructor is being called from the same classloader both times.
构造函数中的堆栈跟踪都通过 wlfullclient-12.1.1jar
,但stacktraces 是另有不同。
The stacktrace from within the constructor both lead through wlfullclient-12.1.1jar
, but the stacktraces are otherwise different.
这是第一次实例化的堆栈跟踪:
Here is the stack trace from the first instantiation:
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).<init>() line: 30 (out of synch)
CacheStartupListener_m3hhum_NoIntfViewImpl.<init>(SingletonLocalObject) line: not available
NativeConstructorAccessorImpl.newInstance0(Constructor, Object[]) line: not available [native method]
NativeConstructorAccessorImpl.newInstance(Object[]) line: 57
DelegatingConstructorAccessorImpl.newInstance(Object[]) line: 45
Constructor<T>.newInstance(Object...) line: 525
SingletonEJBLocalHomeImpl.allocateBI(Class<T>) 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<StateMachine>.nextState(StateChange<StateMachine>, StateMachine[]) line: 35
ModuleStateDriver.prepare(Module[]) line: 38
DeploymentCallbackFlow.prepare(Module[]) line: 139
DeploymentCallbackFlow.prepare() line: 55
BaseDeployment$1.next(Object) line: 706
StateMachineDriver<StateMachine>.nextState(StateChange<StateMachine>, 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
这是第二次实例化的堆栈跟踪:
And here is the stack trace for the second instantiation:
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).<init>() line: 30 (out of synch)
CacheStartupListener_m3hhum_Impl.<init>() line: not available
NativeConstructorAccessorImpl.newInstance0(Constructor, Object[]) line: not available [native method]
NativeConstructorAccessorImpl.newInstance(Object[]) line: 57
DelegatingConstructorAccessorImpl.newInstance(Object[]) line: 45
Constructor<T>.newInstance(Object...) line: 525
WeldConstructorImpl<T>.newInstance(Object...) line: 204
ConstructorInjectionPoint<T>.newInstance(BeanManagerImpl, CreationalContext<?>) line: 117
ExtendedSessionBean(SessionBean<T>).createInstance(CreationalContext<T>) 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<StateMachine>.nextState(StateChange<StateMachine>, 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<StateMachine>.nextState(StateChange<StateMachine>, StateMachine[]) line: 35
ModuleStateDriver.start(Module[]) line: 70
StartModulesFlow.activate() line: 24
BaseDeployment$2.next(Object) line: 729
StateMachineDriver<StateMachine>.nextState(StateChange<StateMachine>, 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()来证明这一点。
The first stack is not actually creating a bean instance but a proxy instance. Your @Singleton
does not declare any business interfaces, so by default it uses the no-interface view (which can be explicitly configured using @LocalBean
). When using the no-interface view, the container generates a proxy class that is a subclass of your class (in this case, the proxy is named CacheStartupListener_m3hhum_NoIntfViewImpl
). When the container creates an instance of this proxy subclass, the constructor of your EJB class will be invoked. You can try printing getClass() in your constructor to prove this point.
我强烈建议完全删除Java构造函数并将所有初始化逻辑移动到 @PostConstruct
。 Java构造函数与无接口视图混合不好。
I strongly recommend removing the Java constructor altogether and moving all initialization logic to @PostConstruct
. Java constructors do not mix well with no-interface view.
这篇关于@Startup @Singleton在WebLogic中实例化两次(EJB 3.1)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!