|
|||||
|
|||||
Container Hierarchy
Container HierarchyContainers in Yan can be organized in a hierarchy to allow modularization. Scoped containerIn a web application, we could manage some global components in the application scope, while some other components can be managed in a session scope. Suppose we have two classes: A and B, where B depends on A. public class A{ ... } public class B{ public B(A a){...} ... } For the application scope components, a container object can be created as: Container app_container = new DefaultContainer();
registerGlobalComponents(app_container);
The registerGlobalComponents() function is responsible for registering the global application scope components: void registerGlobalComponents(Container container){
container.registerComponent(Components.ctor(A.class).singleton());
...
}
For the session scope components, a similar registerSessionComponents() function can be written as: class SessionScope implements Pool{ public synchronized Object getPooledInstance(){ return session.get(key); } public synchronized Object getInstance(ObjectReference ref){ Object r = getPooledInstance(); if(r==null){ r = ref.get(); session.put(key, r); } return r; } private final HttpSession session; private final Object key; ... } ... void registerSessionComponents(Container container, HttpSession session){ container.registerComponent(Components.ctor(B.class).singleton(new SessionScope(session, "B"))); ... }
We will then create a session scope container and register components to it: Container session_container = new DefaultContainer();
registerSessionComponents(session_container, session);
Getting organizedIt is obvious that the component B in the session scope container needs to depend on the component A which is in the application scope container. The inherit() combinator can be used to construct the hierarchy as: Container virtual_container = session_container.inherit(app_container);
Finally the containers need to be stored: application.put("container", app_container);
session.put("container", virtual_container);
Multi-inheritanceDepending on requirement, we may change our mind to have the application scope container inherit from the session scope one. public class SingleSignon{ public SingleSignon(UserInfo user, ...){...} ... } The SingleSignon component is registered into the app_container: void registerAppContainer(Container container) container.registerComponent(Components.ctor(SingleSignon.class)); }
The container hierarchy is organized as such: Container virtual_container = app_container.inherit(session_container);
Thus, for each different session, we get a different UserInfo object, and hence a different SingleSignon object. You may start wondering that
Rest assured, the immutability nature of the inherit() combinator is to rescue. When "container1.inherit(container2)" is called, neither container1 nor container2 is modified. Instead, a new container object maintaining the inheritance relationship is created. This means, you can inherit from as many containers as needed. One could even have app_container.inherit(session_container) and session_container.inherit(app_container) both exist at the same time if he's crazy enough to find a use for it. (If you find a senario to do so, please kindly let me know so I can update this article with a practical example.) What about life cycle?Life cycle in Yan is decoupled from containers. A separate LifecycleManager class is used to manage lifecycle for components. To support life cycle, the registerGlobalComponents() and registerSessionComponents() functions need to be slightly changed to include a LifecycleManager parameter: void registerGlobalComponents(Container container, DefaultLifecycleManager man){
Component a = Components.ctor(A.class).singleton();
Lifecycle lifecycle = man.newLifecycle()
.initializer("init")
.disposer("destroy");
container.registerComponent(man.withLifecycle(a, lifecycle));
...
}
void registerSessionComponents(Container container, HttpSession session, DefaultLifecycleManager man){
Component b = Components.ctor(B.class).singleton(new SessionScope(session, "B"));
Lifecycle lifecycle = man.newLifecycle()
.starter("start")
.stopper("stop");
container.registerComponent(man.withLifecycle(b, lifecycle));
...
}
Now, if we want a central life cycle management regardless of the container hierarchy, we could use a single DefaultLifecycleManager object as: DefaultLifecycleManager man = new DefaultLifecycleManager();
...
registerGlobalComponents(app_container, man);
...
registerSessionComponents(session_container, session, man);
...
This way, life-cycle for instances from both scope are managed at the same place in respect with the order of creation. Or, we could create one DefaultLifecycleManager object for each scope: DefaultLifecycleManager app_man = new DefaultLifecycleManager(); ... registerGlobalComponents(app_container, app_man); ... DefaultLifecycleManager session_man = new DefaultLifecycleManager(); registerSessionComponents(session_container, session, session_man); ... This way, we can manage component life-cycle separatly for different scope. |
|||||
|
Copyright 2003-2006 - The Codehaus. All rights reserved unless otherwise noted.
Powered by Atlassian Confluence
|
|||||