import java.util.HashMap;
import java.util.Map;
import com.opensymphony.xwork2.ActionProxy;
import com.opensymphony.xwork2.ActionProxyFactory;
import com.opensymphony.xwork2.config.Configuration;
import com.opensymphony.xwork2.config.ConfigurationManager;
import com.opensymphony.xwork2.inject.Container;
public class Main {
public static void main(String args[]){
ConfigurationManager cm = new ConfigurationManager();//1
Configuration config = cm.getConfiguration();//2
Container c = config.getContainer();//3
ActionProxyFactory actionProxyFactory = c.getInstance(ActionProxyFactory.class);//4
Map<String,Object> m = new HashMap<String,Object>();//5
m.put("name", "bobo");
ActionProxy actionProxy = actionProxyFactory.createActionProxy(
"/helloWorld", "actionTest",null, m);//6
try {
actionProxy.execute();//7
} catch (Exception e) {
e.printStackTrace();
}
}
}
1 . ConfigurationManager,这个是xwork配置管理的核心,它默认是读取xwork.xml的配置文件的信息,xwork.xml可以通过extends="xwork-default" 来继承xwork-default.xml的配置信息,可以使用里面定义的各种拦截器,ConfigurationManager的主要内容如下:
public class ConfigurationManager {
protected Configuration configuration;//相关的配置信息
protected Lock providerLock = new ReentrantLock();//获取/设置containerProviders时使用的锁
private List<ContainerProvider> containerProviders = new CopyOnWriteArrayList<ContainerProvider>();//为容器提供bean,constants/properties信息
private List<PackageProvider> packageProviders = new CopyOnWriteArrayList<PackageProvider>();//提供包配置信息 TODO
protected String defaultFrameworkBeanName;
public ConfigurationManager() {
this("xwork");
}
public ConfigurationManager(String name) {
this.defaultFrameworkBeanName = name;
}
public List<ContainerProvider> getContainerProviders() {
providerLock.lock();
try {
//没有提供的话就默认使用一下2个provider
if (containerProviders.size() == 0) {
containerProviders.add(new XWorkConfigurationProvider());
containerProviders.add(new XmlConfigurationProvider("xwork.xml", false));
}
return containerProviders;
} finally {
providerLock.unlock();
}
}
public synchronized Configuration getConfiguration() {
if (configuration == null) {
//第一次获取的时候会初始化所有相关的ContainerProvider
setConfiguration(new DefaultConfiguration(defaultFrameworkBeanName));
try {
configuration.reloadContainer(getContainerProviders());
} catch (ConfigurationException e) {
setConfiguration(null);
throw new ConfigurationException("Unable to load configuration.", e);
}
} else {
conditionalReload();
}
return configuration;
}
}
2.Configuration是xwork的配置信息,它是一个接口主要的实现类有2个DefaultConfiguration和MockConfiguration(单元测试用的),Configuration的主要内容如下:
public interface Configuration extends Serializable {
PackageConfig getPackageConfig(String name);//取得某一个package的配置信息
Map<String, PackageConfig> getPackageConfigs();//取得所有package的配置信息
RuntimeConfiguration getRuntimeConfiguration();//取得运行时期的配置信息
void addPackageConfig(String name, PackageConfig packageConfig);//添加包配置信息
PackageConfig removePackageConfig(String packageName);//移除包配置信息
Container getContainer();//获得容器
Set<String> getLoadedFileNames();//获得加载的配置文件的信息
}
DefaultConfiguration是Configuration的实现类,它的主要成员变量有:
public class DefaultConfiguration implements Configuration {
//相关的信息都存储在以下的成员变量中---------
protected Map<String, PackageConfig> packageContexts = new LinkedHashMap<String, PackageConfig>();
protected RuntimeConfiguration runtimeConfiguration;
protected Container container;
protected String defaultFrameworkBeanName;
protected Set<String> loadedFileNames = new TreeSet<String>();
protected List<UnknownHandlerConfig> unknownHandlerStack;
//xwork提供的对象创建工厂,使用buildBean 来创建所有的类,用户可以自定义自己的ObjectFactory
ObjectFactory objectFactory;
}
DefaultConfiguration的主要责任就是在reloadContainer的时候根据注册的所有ConfigurationProvider的提供的信息来实例化一个Container(它的默认实现是ContainerImpl),然后根据Container来实例化ObjectFactory,最后使用Container对各个ConfigurationProvider进行依赖注入
public synchronized List<PackageProvider> reloadContainer(List<ContainerProvider> providers) throws ConfigurationException {
packageContexts.clear();
loadedFileNames.clear();
List<PackageProvider> packageProviders = new ArrayList<PackageProvider>();
//在取得xwork的配置信息的时候使用了2个类从各个Providers取得相应的信息
ContainerProperties props = new ContainerProperties();
ContainerBuilder builder = new ContainerBuilder();
for (final ContainerProvider containerProvider : providers)
{
containerProvider.init(this);
containerProvider.register(builder, props);//各个provider在register的时候往这2个实例中放入配置参数
}
props.setConstants(builder);
builder.factory(Configuration.class, new Factory<Configuration>() {
public Configuration create(Context context) throws Exception {
return DefaultConfiguration.this;
}
});
ActionContext oldContext = ActionContext.getContext();
try {
// Set the bootstrap container for the purposes of factory creation
Container bootstrap = createBootstrapContainer();
setContext(bootstrap);
container = builder.create(false);
setContext(container);
objectFactory = container.getInstance(ObjectFactory.class);
// Process the configuration providers first
for (final ContainerProvider containerProvider : providers)
{
if (containerProvider instanceof PackageProvider) {
container.inject(containerProvider);
((PackageProvider)containerProvider).loadPackages();
packageProviders.add((PackageProvider)containerProvider);
}
}
// Then process any package providers from the plugins
Set<String> packageProviderNames = container.getInstanceNames(PackageProvider.class);
if (packageProviderNames != null) {
for (String name : packageProviderNames) {
PackageProvider provider = container.getInstance(PackageProvider.class, name);
provider.init(this);
provider.loadPackages();
packageProviders.add(provider);
}
}
rebuildRuntimeConfiguration();
} finally {
if (oldContext == null) {
ActionContext.setContext(null);
}
}
return packageProviders;
}
ContainerBuilder是一个final类,它主要是存储有关类型和相关实现类的信息,它主要的成员变量和方法有:
public final class ContainerBuilder {
final Map<Key<?>, InternalFactory<?>> factories =
new HashMap<Key<?>, InternalFactory<?>>();//所有class和name对应的实现类
final List<InternalFactory<?>> singletonFactories =
new ArrayList<InternalFactory<?>>();//所有的单例的实现类
final List<Class<?>> staticInjections = new ArrayList<Class<?>>();//配置中bean中static=true的类
boolean created;//是否已经创建,适用于单例模式
boolean allowDuplicates = false;
/**
* 添加映射
*/
public <T> ContainerBuilder factory(final Class<T> type, final String name,
final Class<? extends T> implementation, final Scope scope) {
// This factory creates new instances of the given implementation.
// We have to lazy load the constructor because the Container
// hasn't been created yet.
InternalFactory<? extends T> factory = new InternalFactory<T>() {
volatile ContainerImpl.ConstructorInjector<? extends T> constructor;
@SuppressWarnings("unchecked")
public T create(InternalContext context) {
if (constructor == null) {
this.constructor =
context.getContainerImpl().getConstructor(implementation);
}
return (T) constructor.construct(context, type);
}
@Override
public String toString() {
return new LinkedHashMap<String, Object>() {{
put("type", type);
put("name", name);
put("implementation", implementation);
put("scope", scope);
}}.toString();
}
};
return factory(Key.newInstance(type, name), factory, scope);
}
private <T> ContainerBuilder factory(final Key<T> key,
InternalFactory<? extends T> factory, Scope scope) {
ensureNotCreated();
checkKey(key);
final InternalFactory<? extends T> scopedFactory =
scope.scopeFactory(key.getType(), key.getName(), factory);
factories.put(key, scopedFactory);
if (scope == Scope.SINGLETON) {
singletonFactories.add(new InternalFactory<T>() {
public T create(InternalContext context) {
try {
context.setExternalContext(ExternalContext.newInstance(
null, key, context.getContainerImpl()));
return scopedFactory.create(context);
} finally {
context.setExternalContext(null);
}
}
});
}
return this;
}
/**
*创建Container
*/
public Container create(boolean loadSingletons) {
ensureNotCreated();
created = true;
final ContainerImpl container = new ContainerImpl(
new HashMap<Key<?>, InternalFactory<?>>(factories));
if (loadSingletons) {
container.callInContext(new ContainerImpl.ContextualCallable<Void>() {
public Void call(InternalContext context) {
for (InternalFactory<?> factory : singletonFactories) {
factory.create(context);
}
return null;
}
});
}
container.injectStatics(staticInjections);
return container;
}
}