This is a very interesting question, I encountered these days.
Here is the question I was asked. "How to let some behaviors can be changed after system deploy"
The first idea comes to my mind is using late binding design pattern such as factory pattern.
If the factory pattern can be accepted, all I have to do is providing a properties file for customize setting and designing a factory class using a reflect method to load the specified class in the properties file.
Unforunatly, the factory pattern was not accepted, due to the setting of customize environment would be too complex for our user. Hence, I need a customize environement like Visual Basic Application in MS-Office. In Spring framework [1], they do provide the integration with several dynamic languages, such as Ruby, Groovy and Beanshell.
In my system, I hope all the service classes can be customized. Hence, I design a customize service interface with following functions to support the scripting environment.
public interface Action
{
public void setDao(Dao dao);
public void input(Map arg);
public boolean validate();
public void doActionPre();
public boolean doAction();
public void doActionPost();
}
public interface Service
{
public void setXXXXAction(Action action);
}
The second step import the dynamic-language-backed bean's XML schema definition as following:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:lang="http://www.springframework.org/schema/lang"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.0.xsd">
Then define the dynamic-language-backed bean
<lang:groovy refresh-check-delay="60000" id="scriptCustomizeAction" script-source="classpath:CustomizeAction.groovy">
<lang:property name="dao" ref="myDao"/>
</lang:groovy>
<!-- an otherwise normal bean that will be injected by the Groovy-backed Messenger -->
<bean id="myService" class="x.y.MyService">
<property name="xXXXAction" ref="scriptCustomizeAction" />
</bean>
/*CustomizeAction.groovy*/
package x.y;
class CustomizeAction implements Action
{
public void setDao(Dao dao)
{
}
public void input(Map arg)
{
}
public boolean validate()
{
}
public void doActionPre()
{
}
public boolean doAction()
{
}
public void doActionPost()
{
}
}
Here are some points you must be aware in your scripting task[4].
- The "scope" of the scripting bean is "singleton" in default. It also can be prototype.
- If your scripting beans do not implements any java interface and you try to inject one scripting bean into another scripting bean as property, your program will throw Exception because springframework cannot use reflection to find the proper set method.
- If you use groovy as your dynamic language, please don't define more than one class per Groovy source file.
- groovy-1.5.5.jar
- asm-2.2.3.jar
- antlr-2.7.6.jar
Reference.
- http://static.springframework.org/spring/docs/2.0.x/reference/dynamic-language.html
- http://book.javanb.com/Professional-Java-Development-with-the-Spring-Framework/BBL0079.html
- http://www.javaworld.com/javaworld/jw-10-2003/jw-1003-beanshell.html
- http://scriptlandia.blogspot.com/2007/03/how-to-build-completely-dynamic-example.html
- http://www.xeniumhk.com/blog/?postid=54
沒有留言:
張貼留言