
Originally Posted by
jwisard
Andreas,
Interesting, indeed. Could you explain this idea a bit?
I think it's best demonstrated by some example code:
Consider this class, implementing an interface:
Code:
public class TestClass implements Foo {
private String str = "?";
private String id = "?";
public TestClass(String id) {
this.id = id;
}
public void foo() {
System.out.println(this.id + "/" + this.str + ": foo1");
}
public void setStr(String str) {
this.str = str;
}
}
public interface Foo {
void foo();
}
Let's assume the id to be passed to the constructor is known only at runtime. So we need a LifecycleHandler for initialization:
Code:
public class TestLifecycleHandler implements LifecycleHandler {
public TestLifecycleHandler() {}
public Object initialize(Map parameterMap) {
String id = (String) parameterMap.get("id");
return new TestClass(id);
}
public void uninitialize(Object obj) {}
public void postInitialize(Object obj, Map parameterMap) {}
}
In the application context it looks like that:
Code:
<bean id="testTarget" class="...TestClass" abstract="true">
<property name="str" value="xyz"/>
</bean>
<bean id="test" class="...ExternalLifecycleFactoryBean">
<property name="proxyInterfaces">
<list>
<value>...Foo</value>
</list>
</property>
<property name="targetName" value="testTarget"/>
<property name="lifecycleHandler">
<bean class="...TestLifecycleHandler"/>
</property>
</bean>
Note that "testTarget" is declared abstract as it is not intended to be instantiated directly (indeed the constructor argument would be missing). Note also that wiring could take place as indicated with the "str" property.
And it is used like this:
Code:
public class LcTest {
private static Logger logger = Logger.getLogger(LcTest.class);
public static void main(String[] args) {
try {
Logger.getRootLogger().setLevel(Level.INFO);
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("appContext.xml");
Foo o = (Foo) ctx.getBean("test");
Map p1 = new HashMap();
p1.put("id", "1");
LifecycleHelper.initialize(o, p1);
o.foo();
} catch (Throwable t) {
logger.error("ERROR", t);
}
}
}
Note that I do no uninitialization as that is not necessary in this case (but possible if required)
Just complete the package names and it should work.

Originally Posted by
jwisard
Also, would this work with objects that do not implement an interface? That is, my UserContext object does not implement an interface. Can a proxy be created for a concrete class? (via CGLIB, or something)
Unfortunately, the current implementation requires interface-based proxies. But instead of proxying UserContext you might consider proxying UserService, passing in the UserContext at runtime.
Hope that helps,
Andreas
P.S.: If you like this feature, feel free to vote for it on Jira