3、所有需要解析的配置文件的解析类全部放入ConfigurationManager中的containerProviders中之后
1:Container container = init_PreloadConfiguration();
这段代码,负责创建一个container对象,并初始化所有需要配置的文件信息;
首先,该方法属于Dispatcher中的方法,该方法的主要内容如下:
/**
* 加载前进行的配置初始化
* @return
*/
private Container init_PreloadConfiguration() {
//获取configuration
①Configuration config = configurationManager.getConfiguration();
//从configuration中获取container的一个实例
②Container container = config.getContainer();
//获取是否配置了国际化
③boolean reloadi18n = Boolean.valueOf(container.getInstance(String.class, StrutsConstants.STRUTS_I18N_RELOAD));
//定义是否需要重新装载资源绑定
④LocalizedTextUtil.setReloadBundles(reloadi18n);
return container;
}
①Configuration config = configurationManager.getConfiguration();
调用ConfigurationManager的getConfiguration()方法获取一个Configuration的实例,该方法的主要内容如下:
/**
* 获取当前的xwork配置类。顺便一个DefaultConfiguration的实体对象将被返回
*/
public synchronized Configuration getConfiguration() {
//系统首次运行时,该对象为空
if (configuration == null) {
//创建一个新的DefaultConfiguration对象,并用其初始化Configuration
setConfiguration(createConfiguration(defaultFrameworkBeanName));
try {
//调用DefaultConfiguration对象的reloadContainer方法;加载、解析所有配置文件
configuration.reloadContainer(getContainerProviders());
} catch (ConfigurationException e) {
setConfiguration(null);
throw new ConfigurationException("Unable to load configuration.", e);
}
} else {
//重新加载配置文件如果配置文件里面指明要重新加载
conditionalReload(configuration.getContainer());
}
//返回这个configuration实例
return configuration;
}
代码setConfiguration(createConfiguration(defaultFrameworkBeanName));
其中createConfiguration(defaultFrameworkBeanName)的具体代码如下
/**
* 创建一个DefaultConfiguration对象
* @param beanName 此时beanName为struts
* @return
*/
protected Configuration createConfiguration(String beanName) {
return new DefaultConfiguration(beanName);
}
在该方法里,调用DefaultConfiguration的构造方法如下:
/**
* 构造方法,传递一个DefaultBeanName;
* 如果没传递的话,默认设置为xwork
* @param defaultBeanName
*/
public DefaultConfiguration(String defaultBeanName) {
this.defaultFrameworkBeanName = defaultBeanName;
}
在这里设置了DefaultConfiguration的protected String defaultFrameworkBeanName;
上述createConfiguration(String beanName)返回了一个DefaultConfiguration的实例,
此时再调用ConfigurationManager中的setConfiguration把新实例化的DefaultConfiguration填充变量,该方法的具体代码如下:
/**
* 通过传递过来的参数DefaultConfiguration初始化configuration
* @param configuration
*/
public synchronized void setConfiguration(Configuration configuration) {
this.configuration = configuration;
}
此时初始化
protected Configuration configuration;//这个变量为DefaultConfiguration
然后调用实例化之后的configuration的reloadContainer(getContainerProviders())方法,在该方法内部负责对配置文件进行加载和解析
首先调用ConfigurationManager的getContainerProviders()返回containerProviders这个实例具体代码如下
/**
* 获取当前ConfigurationManager中包含的provider对象
* @return the list of registered ConfigurationProvider objects
* @see ConfigurationProvider
*/
public List<ContainerProvider> getContainerProviders() {
providerLock.lock();
try {
//理论上,不出意外的话,将直接返回containerProviders对象
if (containerProviders.size() == 0) {
containerProviders.add(new XWorkConfigurationProvider());//该类主要加载bean
containerProviders.add(new XmlConfigurationProvider("xwork.xml", false));//加载xwork配置解析provider
}
return containerProviders;
} finally {
providerLock.unlock();
}
}
此时返回containerProviders这个实例
然后调用configuration的reloadContainer(List<ContainerProvider> containerProviders)方法,在这个方法里面,对所有的配置信息进行了解析该方法的具体内容如下:
/**
* @throws ConfigurationException
*/
public synchronized List<PackageProvider> reloadContainer(List<ContainerProvider> providers) throws ConfigurationException {
1)packageContexts.clear();//清空packageContexts
2)loadedFileNames.clear();//清空loadedFileNames
3)List<PackageProvider> packageProviders = new ArrayList<PackageProvider>();
4)ContainerProperties props = new ContainerProperties();//创建一个容器配置管理类,当前内部类
5)ContainerBuilder builder = new ContainerBuilder();//创建一个ContainerBuilder对象
6)Container bootstrap = createBootstrapContainer();//实例化一个Container对象,该对象是ContainerImpl的一个实例
//循环每一个ContainterProvider,将他们各自对应的容器配置元素注册到ContainerBuilder中去,
//这里,首先加载provider中的配置
for (final ContainerProvider containerProvider : providers)
{
//containerProvider进行依赖注入,这部分代码放在后面的struts2的依赖注入进行介绍
7)bootstrap.inject(containerProvider);
//这里对于资源文件的处理分两步走
//当前的this指DefaultConfiguration这个对象
8)containerProvider.init(this);//第一步是初始化,即完成格式转换,如xml格式的转换为 document对象集合.
//providers中存放的数据有以下内容:
/**
* 1、DefaultPropertiesProvider(default.properties),这个类的register运行结束之后,参数全部放入了props里面
* 2、StrutsXmlConfigurationProvider(struts-defaults.xml);这个类中constant放入build中,bean放入props中
* 3、StrutsXmlConfigurationProvider(struts-plugin.xml);这个类中constant放入build中,bean放入props中
* 4、StrutsXmlConfigurationProvider(struts.xml);这个类中constatn放入build中,bean放入props中
* 5、LegacyPropertiesConfigurationProvider;这个类中需要配置的参数放入build中
* 6、加载用户配置的文件,一般情况下,未添加
* 7、init_FilterInitParameters(添加在web.xml的Filter中配置的常量);把web.xml中的fileter中的参数放入props中
* 8、BeanSelectionProvider;把配置放入builder中的factories中
*/
9)containerProvider.register(builder, props);//第二步是将资源文件中配置的对象注册到容器构造者对象中去。
}
//把props中的参数放入builder中
10)props.setConstants(builder);
//在builder中添加一个Configuration
11)builder.factory(Configuration.class, new Factory<Configuration>() {
public Configuration create(Context context) throws Exception {
return DefaultConfiguration.this;
}
});
//获取当前线程的ActionContext
12)ActionContext oldContext = ActionContext.getContext();
try {
// Set the bootstrap container for the purposes of factory creation
13)setContext(bootstrap);
14)container = builder.create(false);
15)setContext(container);
16)objectFactory = container.getInstance(ObjectFactory.class);//获取一个objectFactory实例
// Process the configuration providers first
// 首先执行providers配置
for (final ContainerProvider containerProvider : providers)
{
/**
* 解析xml中配置的package元素
*/
if (containerProvider instanceof PackageProvider) {
17)container.inject(containerProvider);//进行依赖注入,这部分代码放在后面的struts2的依赖注入进行介绍
/**
* 1、DefaultPropertiesProvider(default.properties),这个类的loadPackages()方法不执行任何操作
* 2、StrutsXmlConfigurationProvider(struts-defaults.xml);这个类中的loadPackages()方法执行的结果解析了配置文件中的package元素并放入DefaultConfiguration元素的packageContexts中
* 3、StrutsXmlConfigurationProvider(struts-plugin.xml);这个类中的loadPackages()方法执行的结果解析了配置文件中的package元素并放入DefaultConfiguration元素的packageContexts中
* 4、StrutsXmlConfigurationProvider(struts.xml);这个类中的loadPackages()方法执行的结果解析了配置文件中的package元素并放入DefaultConfiguration元素的packageContexts中
* 5、LegacyPropertiesConfigurationProvider;这个类的loadPackages()方法不执行任何操作
* 6、加载用户配置的文件,一般情况下,未添加
* 7、init_FilterInitParameters;这个类的loadPackages()方法不执行任何操作
* 8、BeanSelectionProvider;这个类的loadPackages()方法不执行任何操作
*/
18)((PackageProvider)containerProvider).loadPackages();//调用loadPackages方法
19)packageProviders.add((PackageProvider)containerProvider);
}
}
// Then process any package providers from the plugins
//让后执行plugins中的package providers
20)Set<String> packageProviderNames = container.getInstanceNames(PackageProvider.class);
if (packageProviderNames != null) {
for (String name : packageProviderNames) {
21)PackageProvider provider = container.getInstance(PackageProvider.class, name);
22)provider.init(this);
23)provider.loadPackages();
24)packageProviders.add(provider);
}
}
25)rebuildRuntimeConfiguration();
} finally {
if (oldContext == null) {
26)ActionContext.setContext(null);
}
}
27)return packageProviders;
}
1)packageContexts.clear();//清空packageContexts
该DefaultConfiguration中有
protected Map<String, PackageConfig> packageContexts = new LinkedHashMap<String, PackageConfig>();
这么一个属性在第一次加载时,先把这个属性中的内容清空
map里面的PackageConfig(com.opensymphony.xwork2.config.entities)这个类是一个package的配置类,该类在xml的配置文件中,相当于package标签。该类的具体作用和用法将在下面讲到
2)loadedFileNames.clear();//清空loadedFileNames,该参数用于记录已经加载的文件名
该DefaultConfiguration中有
protected Set<String> loadedFileNames = new TreeSet<String>();这么一个属性。在第一次加载时,先把这个属性中的内容清空
3)List<PackageProvider> packageProviders = new ArrayList<PackageProvider>();
创建一个PackageProvider(com.opensymphony.xwork2.config)的list;该PackageProvider是一个接口,该接口的主要内容如下
public interface PackageProvider {
/**
* 初始化配置信息
* @param configuration The configuration
* @throws ConfigurationException If anything goes wrong
*/
public void init(Configuration configuration) throws ConfigurationException;
/**
* 告知该packageProvider是否需要重新加载
*
* @return <tt>true</tt>, whether the PackageProvider should reload its configuration, <tt>false</tt>otherwise.
*/
public boolean needsReload();
/**
* 为配置加载该packageProvider
* @throws ConfigurationException
*/
public void loadPackages() throws ConfigurationException;
}
该接口定义了3个方法,分别为init(Configuration configuration),needsReload(),loadPackages()
4)ContainerProperties props = new ContainerProperties();//创建一个容器配置管理类,当前内部类
创建一个ContainerProperties(当前DefaultConfiguration的内部类)的类,该类的主要代码如下
/**
* 容器配置类
* 该类继承自LoctableProperites
* @author Administrator
*
*/
class ContainerProperties extends LocatableProperties {
private static final long serialVersionUID = -7320625750836896089L;
@Override
public Object setProperty(String key, String value) {
String oldValue = getProperty(key);
if (LOG.isInfoEnabled() && oldValue != null && !oldValue.equals(value) && !defaultFrameworkBeanName.equals(oldValue)) {
LOG.info("Overriding property "+key+" - old value: "+oldValue+" new value: "+value);
}
return super.setProperty(key, value);
}
/**
* 把builder中的
* @param builder
*/
public void setConstants(ContainerBuilder builder) {
for (Object keyobj : keySet()) {
String key = (String)keyobj;
//这里调用了builder的方法,将在后面进行介绍
builder.factory(String.class, key,
new LocatableConstantFactory<String>(getProperty(key), getPropertyLocation(key)));
}
}
}
该类继承自LocatableProperties(com.opensymphony.xwork2.util.location)这个类继承了Properties类,并实现了Locatable(com.opensymphony.xwork2.util.location)接口,
Locatable接口的主要内容如下:
public interface Locatable {
/**
* 得到这个对象的地址
* @return 返回对象创建的地址
*/
public Location getLocation();
}
5)ContainerBuilder builder = new ContainerBuilder();//创建一个ContainerBuilder对象
调用ContainerBuilder(com.opensymphony.xwork2.inject)的默认无参构造方法,该方法具体内容如下:
/**
* 创建一个新的builder.
*/
public ContainerBuilder() {
// 在当前容器中作为默认容器的实现
factories.put(Key.newInstance(Container.class, Container.DEFAULT_NAME), CONTAINER_FACTORY);
// 注入的注入成员的日志记录
factories.put(Key.newInstance(Logger.class, Container.DEFAULT_NAME), LOGGER_FACTORY);
}
在该ContainerBuilder中有一个常量
final Map<Key<?>, InternalFactory<?>> factories = new HashMap<Key<?>, InternalFactory<?>>();
该常量是构建容器所必须的。其内容组成是与具体运行环境有关,既有来自struts2框架本身的配置所提供的一些组成部分,又有来自客户项目的配置数据提供的组成部分
其中Key中包含的是类的类型,名称和哈希值。InternalFactory代表的是生成类的工厂对象,调用其中的factory方法,就可以生成相应的对象
Key(com.opensymphony.xwork2.inject)该类的代码如下:
/**
* 依赖映射的关键。所需的类型和名称的唯一性标识。
*/
class Key<T> {
final Class<T> type;//类型
final String name;//名称
final int hashCode;//哈希值
private Key(Class<T> type, String name) {
if (type == null) {
throw new NullPointerException("Type is null.");
}
if (name == null) {
throw new NullPointerException("Name is null.");
}
this.type = type;
this.name = name;
hashCode = type.hashCode() * 31 + name.hashCode();
}
Class<T> getType() {
return type;
}
String getName() {
return name;
}
@Override
public int hashCode() {
return hashCode;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof Key)) {
return false;
}
if (o == this) {
return true;
}
Key other = (Key) o;
return name.equals(other.name) && type.equals(other.type);
}
@Override
public String toString() {
return "[type=" + type.getName() + ", name='" + name + "']";
}
static <T> Key<T> newInstance(Class<T> type, String name) {
return new Key<T>(type, name);
}
}
InternalFactory(com.opensymphony.xwork2.inject)是一个接口,该接口的主要内容如下:
/**
* 创建将要被注入的对象的实例化工厂
*/
interface InternalFactory<T> extends Serializable {
/**
* 创建一个将要被注入的对象
*
* @param context of this injection
* @return instance 将要被注入的类的实例
*/
T create(InternalContext context);
}
InternalContext(com.opensymphony.xwork2.inject)该类用于协调和支持循环依赖注入;该类的代码如下
/**
* 内部上下文。用于协调和支持循环依赖注入。
*/
class InternalContext {
final ContainerImpl container;
final Map<Object, ConstructionContext<?>> constructionContexts = new HashMap<Object, ConstructionContext<?>>();
Scope.Strategy scopeStrategy;
ExternalContext<?> externalContext;
InternalContext(ContainerImpl container) {
this.container = container;
}
public Container getContainer() {
return container;
}
ContainerImpl getContainerImpl() {
return container;
}
Scope.Strategy getScopeStrategy() {
if (scopeStrategy == null) {
scopeStrategy = (Scope.Strategy) container.localScopeStrategy.get();
if (scopeStrategy == null) {
throw new IllegalStateException("Scope strategy not set. "
+ "Please call Container.setScopeStrategy().");
}
}
return scopeStrategy;
}
@SuppressWarnings("unchecked")
<T> ConstructionContext<T> getConstructionContext(Object key) {
ConstructionContext<T> constructionContext =
(ConstructionContext<T>) constructionContexts.get(key);
if (constructionContext == null) {
constructionContext = new ConstructionContext<T>();
constructionContexts.put(key, constructionContext);
}
return constructionContext;
}
@SuppressWarnings("unchecked")
<T> ExternalContext<T> getExternalContext() {
return (ExternalContext<T>) externalContext;
}
void setExternalContext(ExternalContext<?> externalContext) {
this.externalContext = externalContext;
}
}
在创建ContainerBuilder的时候
factories.put(Key.newInstance(Container.class, Container.DEFAULT_NAME), CONTAINER_FACTORY);//在factories中添加一个创建Container的工厂
这行代码,向factory中添加了一个记录:Key.newInstance(Container.class, Container.DEFAULT_NAME)为一个Key的实例。其中Container.DEFAULT_NAME为default
CONTAINER_FACTORY(为Container创建了一个工厂)为:
private static final InternalFactory<Container> CONTAINER_FACTORY = new InternalFactory<Container>() {
public Container create(InternalContext context) {
return context.getContainer();
}
};
factories.put(Key.newInstance(Logger.class, Container.DEFAULT_NAME), LOGGER_FACTORY);//在factories中添加一个创建Logger的工厂
LOGGER_FACTORY(为Logger创建一个工厂)为:
private static final InternalFactory<Logger> LOGGER_FACTORY = new InternalFactory<Logger>() {
public Logger create(InternalContext context) {
Member member = context.getExternalContext().getMember();//(未分析)
return member == null ? Logger.getAnonymousLogger() : Logger.getLogger(member.getDeclaringClass().getName());(未分析)
}
};
6)Container bootstrap = createBootstrapContainer();//实例化一个Container对象,该对象是ContainerImpl的一个实例
在这里首先创建一个ContainerBuilder,利用该对象中的方法,初始化factories让后再创建一个ContainerImpl返回
该方法属于DefaultConfiguration中的方法,其主要作用是创建一个Container对象。其代码如下:
/**
* 创建一个Container对象
* @return
*/
protected Container createBootstrapContainer() {
/**
* 首先生成一个ContainerBuilder对象,调用register来实现对builder
* 对象的factories成员变量的设置
*/
ContainerBuilder builder = new ContainerBuilder();
/**
* 对框架的扩展点的实现,完成框架功能必须,因此也需要加载,否则容器无法正常起效,
* 以下这些扩展点暂时未分析
*/
//ObjectFactory负责创建核心框架对象
builder.factory(ObjectFactory.class, Scope.SINGLETON);
//其中FileManager访问文件系统和文件的变化进行监测的基本接口
//DefaultFileManager是FileManager接口的实现类
builder.factory(FileManager.class, DefaultFileManager.class, Scope.SINGLETON);
//未分析
builder.factory(ReflectionProvider.class, OgnlReflectionProvider.class, Scope.SINGLETON);
//ValueStackFactory值栈类接口,OgnlValueStackFactory值栈的实现类
builder.factory(ValueStackFactory.class, OgnlValueStackFactory.class, Scope.SINGLETON);
//xwork的类型转换器
builder.factory(XWorkConverter.class, Scope.SINGLETON);
//xwork的类型转换器
builder.factory(XWorkBasicConverter.class, Scope.SINGLETON);
//Collection类型转换器
builder.factory(TypeConverter.class, "collection", CollectionConverter.class, Scope.SINGLETON);
//Array类型转换器
builder.factory(TypeConverter.class, "array", ArrayConverter.class, Scope.SINGLETON);
//Date类型转换器
builder.factory(TypeConverter.class, "date", DateConverter.class, Scope.SINGLETON);
//Number类型转换器
builder.factory(TypeConverter.class, "number", NumberConverter.class, Scope.SINGLETON);
//String类型转换器
builder.factory(TypeConverter.class, "string", StringConverter.class, Scope.SINGLETON);
//文本类型转换器
builder.factory(TextProvider.class, "system", DefaultTextProvider.class, Scope.SINGLETON);
builder.factory(ObjectTypeDeterminer.class, DefaultObjectTypeDeterminer.class, Scope.SINGLETON);
builder.factory(PropertyAccessor.class, CompoundRoot.class.getName(), CompoundRootAccessor.class, Scope.SINGLETON);
builder.factory(OgnlUtil.class, Scope.SINGLETON);
builder.constant("devMode", "false");
builder.constant("logMissingProperties", "false");
/**
* 参数收集完成,通过create实现容器的创建
*/
return builder.create(true);
}
在这个方法里面涉及到ContainerBuilder的很多方法下面来对这些代码进行分析:
public final class ContainerBuilder {
/**
*
* factories是构建容器所必须的,但其内容组成是与具体运行环境有关,既有来自struts2框架本身的
* 配置所提供的一些组成部分,又有来自客户项目的配置数据提供的组成部分
* 构造容器对象的时候的参数是一个个的键值对,
* Key中包含的是类的类型,名称和哈希值
* InternalFactory代表的是生成类的工厂对象,调用其中的factory方法,就可以生成相应的对象
*/
final Map<Key<?>, InternalFactory<?>> factories = new HashMap<Key<?>, InternalFactory<?>>();
/**
* 创建将要被注入的单例模式对象的列表
*/
final List<InternalFactory<?>> singletonFactories = new ArrayList<InternalFactory<?>>();
final List<Class<?>> staticInjections = new ArrayList<Class<?>>();
boolean created;//是否已被创建
boolean allowDuplicates = false;
//container_factory
private static final InternalFactory<Container> CONTAINER_FACTORY = new InternalFactory<Container>() {
public Container create(InternalContext context) {
return context.getContainer();
}
};
//logger_factory
private static final InternalFactory<Logger> LOGGER_FACTORY = new InternalFactory<Logger>() {
public Logger create(InternalContext context) {
Member member = context.getExternalContext().getMember();
return member == null ? Logger.getAnonymousLogger() : Logger.getLogger(member.getDeclaringClass().getName());
}
};
/**
* 创建一个新的builder.
*/
public ContainerBuilder() {
// 在当前容器中作为默认容器的实现
factories.put(Key.newInstance(Container.class, Container.DEFAULT_NAME), CONTAINER_FACTORY);
// 注入的注入成员的日志记录
factories.put(Key.newInstance(Logger.class, Container.DEFAULT_NAME), LOGGER_FACTORY);
}
/**
* 实现功能的主体。其它的factory方法主要是用来进行参数的适配和改造。
*/
private <T> ContainerBuilder factory(final Key<T> key, InternalFactory<? extends T> factory, Scope scope) {
ensureNotCreated();//用来确定该容器是否已经创建
checkKey(key);//确认一个key是否已经映射了
final InternalFactory<? extends T> scopedFactory = scope.scopeFactory(key.getType(), key.getName(), factory);//对工厂类的作用范围进行包装
factories.put(key, scopedFactory);//把该工厂类放入factories中
//如果该工厂类的作用范围为singleton
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;
}
/**
* 确定一个key是否已经映射了
*/
private void checkKey(Key<?> key) {
if (factories.containsKey(key) && !allowDuplicates) {
throw new DependencyException("Dependency mapping for " + key + " already exists.");
}
}
/**
* 映射一个factory通过给定的依赖类型和名称
*
* @param type of dependency
* @param name of dependency
* @param factory creates objects to inject
* @param scope scope of injected instances
* @return this builder
*/
public <T> ContainerBuilder factory(final Class<T> type, final String name, final Factory<? extends T> factory, Scope scope) {
/**
* 对传入的factory对象进行装饰
*/
InternalFactory<T> internalFactory = new InternalFactory<T>() {
public T create(InternalContext context) {
try {
Context externalContext = context.getExternalContext();
return factory.create(externalContext);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public String toString() {
return new LinkedHashMap<String, Object>() {{
put("type", type);
put("name", name);
put("factory", factory);
}}.toString();
}
};
return factory(Key.newInstance(type, name), internalFactory, scope);
}
/**
* 相当于调用factory(final Class<T> type, final String name, final Factory<? extends T> factory, Scope scope);
*/
public <T> ContainerBuilder factory(Class<T> type, Factory<? extends T> factory, Scope scope) {
return factory(type, Container.DEFAULT_NAME, factory, scope);
}
/**
* 相当于调用factory(final Class<T> type, final String name, final Factory<? extends T> factory, Scope scope);
*/
public <T> ContainerBuilder factory(Class<T> type, String name, Factory<? extends T> factory) {
return factory(type, name, factory, Scope.DEFAULT);
}
/**
* 相当于调用factory(final Class<T> type, final String name, final Factory<? extends T> factory, Scope scope);
*/
public <T> ContainerBuilder factory(Class<T> type, Factory<? extends T> factory) {
return factory(type, Container.DEFAULT_NAME, factory, Scope.DEFAULT);
}
/**
* 映射一个给定依赖名字和类型的实现类,用container创建一个实例,递归依赖注入
* @param type 依赖的类型
* @param name 依赖的名称
* @param implementation 实现类
* @param scope 注入的作用范围
* @return this builder
*/
public <T> ContainerBuilder factory(final Class<T> type, final String name, final Class<? extends T> implementation, final Scope scope) {
// 这个工厂创建一个给定实现类的实例
//对给定的implementation进行装饰
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);
}
/**
* 映射一个给定依赖名字和类型的实现类,用container创建一个实例,递归依赖注入
* <p>Sets scope to value from {@link Scoped} annotation on the
* implementation class. Defaults to {@link Scope#DEFAULT} if no annotation
* is found.
*
* @param type of dependency
* @param name of dependency
* @param implementation class
* @return this builder
*/
public <T> ContainerBuilder factory(final Class<T> type, String name, final Class<? extends T> implementation) {
Scoped scoped = implementation.getAnnotation(Scoped.class);
Scope scope = scoped == null ? Scope.DEFAULT : scoped.value();
return factory(type, name, implementation, scope);
}
/**
* 相当于调用 factory(final Class<T> type, String name, final Class<? extends T> implementation)
*/
public <T> ContainerBuilder factory(Class<T> type, Class<? extends T> implementation) {
return factory(type, Container.DEFAULT_NAME, implementation);
}
/**
* 相当于调用 factory(final Class<T> type, String name, final Class<? extends T> implementation)
*/
public <T> ContainerBuilder factory(Class<T> type) {
return factory(type, Container.DEFAULT_NAME, type);
}
/**
* 相当于调用 factory(final Class<T> type, String name, final Class<? extends T> implementation)
*/
public <T> ContainerBuilder factory(Class<T> type, String name) {
return factory(type, name, type);
}
/**
* 相当于调用factory(final Class<T> type, final String name, final Class<? extends T> implementation, final Scope scope)
*/
public <T> ContainerBuilder factory(Class<T> type, Class<? extends T> implementation, Scope scope) {
return factory(type, Container.DEFAULT_NAME, implementation, scope);
}
/**
* 相当于调用factory(final Class<T> type, final String name, final Class<? extends T> implementation, final Scope scope)
*/
public <T> ContainerBuilder factory(Class<T> type, Scope scope) {
return factory(type, Container.DEFAULT_NAME, type, scope);
}
/**
* 相当于调用factory(final Class<T> type, final String name, final Class<? extends T> implementation, final Scope scope)
*/
public <T> ContainerBuilder factory(Class<T> type, String name, Scope scope) {
return factory(type, name, type, scope);
}
/**
* 相当于调用alias(Class<T> type, String alias)
*/
public <T> ContainerBuilder alias(Class<T> type, String alias) {
return alias(type, Container.DEFAULT_NAME, alias);
}
/**
* 映射一个已存在的工厂一个新的名字
*
* @param type of dependency
* @param name of dependency
* @param alias of to the dependency
* @return this builder
*/
public <T> ContainerBuilder alias(Class<T> type, String name, String alias) {
return alias(Key.newInstance(type, name), Key.newInstance(type, alias));
}
/**
* 映射一个现有的依赖关系。并替换key为aliasKey
*/
private <T> ContainerBuilder alias(final Key<T> key, final Key<T> aliasKey) {
ensureNotCreated();//判断该容器是否已经被创建
checkKey(aliasKey);//判断该key是否已经存在
//获取factories中指定key的对象
final InternalFactory<? extends T> scopedFactory = (InternalFactory<? extends T>)factories.get(key);
//如果该对象不存在,抛出异常
if (scopedFactory == null) {
throw new DependencyException("Dependency mapping for " + key + " doesn't exists.");
}
//把新的key,和对象放入aliasKey中
factories.put(aliasKey, scopedFactory);
return this;
}
/**
* 映射一个给定名称的常量值
*/
public ContainerBuilder constant(String name, String value) {
return constant(String.class, name, value);
}
/**
* 映射一个给定名称的常量值
*/
public ContainerBuilder constant(String name, int value) {
return constant(int.class, name, value);
}
/**
* 映射一个给定名称的常量值
*/
public ContainerBuilder constant(String name, long value) {
return constant(long.class, name, value);
}
/**
* 映射一个给定名称的常量值
*/
public ContainerBuilder constant(String name, boolean value) {
return constant(boolean.class, name, value);
}
/**
* 映射一个给定名称的常量值
*/
public ContainerBuilder constant(String name, double value) {
return constant(double.class, name, value);
}
/**
* 映射一个给定名称的常量值
*/
public ContainerBuilder constant(String name, float value) {
return constant(float.class, name, value);
}
/**
* 映射一个给定名称的常量值
*/
public ContainerBuilder constant(String name, short value) {
return constant(short.class, name, value);
}
/**
* 映射一个给定名称的常量值
*/
public ContainerBuilder constant(String name, char value) {
return constant(char.class, name, value);
}
/**
* 映射一个给定名称的常量值
*/
public ContainerBuilder constant(String name, Class value) {
return constant(Class.class, name, value);
}
/**
* 映射一个给定名称的常量值
*/
public <E extends Enum<E>> ContainerBuilder constant(String name, E value) {
return constant(value.getDeclaringClass(), name, value);
}
/**
* 映射一个给定名称和类型的常量值.
*/
private <T> ContainerBuilder constant(final Class<T> type, final String name, final T value) {
//对给定值进行装饰
InternalFactory<T> factory = new InternalFactory<T>() {
public T create(InternalContext ignored) {
return value;
}
@Override
public String toString() {
return new LinkedHashMap<String, Object>() {
{
put("type", type);
put("name", name);
put("value", value);
}
}.toString();
}
};
return factory(Key.newInstance(type, name), factory, Scope.DEFAULT);
}
/**
* 在创建时,容器将注入静态域和方法为给定的类。
* @param types 将被注入的静态常量成员
*/
public ContainerBuilder injectStatics(Class<?>... types) {
staticInjections.addAll(Arrays.asList(types));
return this;
}
/**
* 如果factories中包含给定类型和名称的值,则返回true
*/
public boolean contains(Class<?> type, String name) {
return factories.containsKey(Key.newInstance(type, name));
}
/**
* 相当于调用contains(Class<?> type, String name)
*/
public boolean contains(Class<?> type) {
return contains(type, Container.DEFAULT_NAME);
}
/**
* Creates a {@link Container} instance. Injects static members for classes
* which were registered using {@link #injectStatics(Class...)}.
* 创建一个Container实例。
*
* @param loadSingletons 如果 boolean created(loadSingletons)值为true 的话,先调用scope="singleton" 的对象工厂的create方法
* @throws IllegalStateException if called more than once
*/
public Container create(boolean loadSingletons) {
ensureNotCreated();//判断是否已经创建
created = true;//设置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);
//返回一个ContainerImpl实例对象
return container;
}
/**
* 现在我们只支持创造每一容器实例生成器。
* 如果我们想支持创建每建造多个容器,我们要搬到一个“工厂”的模式,我们创建每个集装箱厂实例。
* 现在,一个工厂的实例将在所有容器共享,单身人士对容器时延迟加载,等。
*/
private void ensureNotCreated() {
if (created) {
throw new IllegalStateException("Container already created.");
}
}
public void setAllowDuplicates(boolean val) {
allowDuplicates = val;
}
/**
* Implemented by classes which participate in building a container.
*/
public interface Command {
/**
* Contributes factories to the given builder.
*
* @param builder
*/
void build(ContainerBuilder builder);
}
}
7)bootstrap.inject(containerProvider);
containerProvider进行依赖注入,这部分代码放在后面的struts2的依赖注入进行介绍
8)containerProvider.init(this);//这里是比较核心的一个模块
首先确定当前的providers中有哪些记录
1:DefaultPropertiesProvider(default.properties)
执行DefaultPropertiesProvider该类的init(Configuration configuration)方法
该类的该方法如下:
/**
* 不用把该对象转换成document对象
*/
public void init(Configuration configuration) throws ConfigurationException {
}
2:StrutsXmlConfigurationProvider(struts-default.xml)
该类没有对init方法进行重写,因此调用父类(XmlConfigurationProvider)的init方法
/**
* @param configuration 为DefaultConfiguration对象的一个实例
*/
public void init(Configuration configuration) {
this.configuration = configuration;//设置configuration
this.includedFileNames = configuration.getLoadedFileNames();//此时为空
loadDocuments(configFileName);//第一次为loadDocuments(struts-defaults.xml)
}
/**
* @param configFileName struts-default.xml
*/
private void loadDocuments(String configFileName) {
try {
loadedFileUrls.clear();
documents = loadConfigurationFiles(configFileName, null);//把*.xml转换成document形式,并存放到documents中
} catch (ConfigurationException e) {
throw e;
} catch (Exception e) {
throw new ConfigurationException("Error loading configuration file " + configFileName, e);
}
}
其中private Set<String> loadedFileUrls = new HashSet<String>();//已经加载的file的URL
/**
* 返回*.xml的document形式结果
* @param fileName struts-default.xml
* @param includeElement null
*/
private List<Document> loadConfigurationFiles(String fileName, Element includeElement) {
List<Document> docs = new ArrayList<Document>();//创建一个新的List<dom>对象
List<Document> finalDocs = new ArrayList<Document>();//再创建一个finalDocs的List<dom>对象
if (!includedFileNames.contains(fileName)) {//如果includedFileNames不包含名为fileName的对象
if (LOG.isDebugEnabled()) {
LOG.debug("Loading action configurations from: " + fileName);
}
//把该fileName添加到includedFileNames,防止重复添加
includedFileNames.add(fileName);
Iterator<URL> urls = null;
InputStream is = null;
IOException ioException = null;
try {
/**
* 获取fileName的URL
*/
urls = getConfigurationUrls(fileName);
} catch (IOException ex) {
ioException = ex;
}
/**
* 如果urls为空,或urls.hasNext = true,则执行下面的代码
*/
if (urls == null || !urls.hasNext()) {
if (errorIfMissing) {
throw new ConfigurationException("Could not open files of the name " + fileName, ioException);
} else {
if (LOG.isInfoEnabled()) {
LOG.info("Unable to locate configuration files of the name "
+ fileName + ", skipping");
}
return docs;//此时docs对象为空
}
}
//否则
URL url = null;
while (urls.hasNext()) {
try {
//把fileName的URL传递给url
url = urls.next();
//fileManager对象为DefaultFileManager,通过struts框架自动注入进来
//根据URL加载指定的文件,并返回inputStream形式的结果
is = fileManager.loadFile(url);
InputSource in = new InputSource(is);
//设置此输入源的系统标识符
in.setSystemId(url.toString());
/**
* 在docs中添加一个document
*/
docs.add(DomHelper.parse(in, dtdMappings));
} catch (XWorkException e) {
if (includeElement != null) {
throw new ConfigurationException("Unable to load " + url, e, includeElement);
} else {
throw new ConfigurationException("Unable to load " + url, e);
}
} catch (Exception e) {
final String s = "Caught exception while loading file " + fileName;
throw new ConfigurationException(s, e, includeElement);
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
LOG.error("Unable to close input stream", e);
}
}
}
}
//对documents进行排序,通过order这个属性
Collections.sort(docs, new Comparator<Document>() {//(未分析)
public int compare(Document doc1, Document doc2) {
return XmlHelper.getLoadOrder(doc1).compareTo(XmlHelper.getLoadOrder(doc2));
}
});
/**
* 对docs中的内容进行遍历
*/
for (Document doc : docs) {
Element rootElement = doc.getDocumentElement();
NodeList children = rootElement.getChildNodes();
int childSize = children.getLength();//struts-default.xml中有72个child;
//对xml进行解析,查看其所有子元素中是否包含include元素
for (int i = 0; i < childSize; i++) {
Node childNode = children.item(i);
if (childNode instanceof Element) {
//获取element
Element child = (Element) childNode;
//获取element的name
final String nodeName = child.getNodeName();
//如果element==include
if ("include".equals(nodeName)) {
String includeFileName = child.getAttribute("file");
if (includeFileName.indexOf('*') != -1) {
// handleWildCardIncludes(includeFileName, docs, child);
ClassPathFinder wildcardFinder = new ClassPathFinder();
wildcardFinder.setPattern(includeFileName);
Vector<String> wildcardMatches = wildcardFinder.findMatches();
for (String match : wildcardMatches) {
finalDocs.addAll(loadConfigurationFiles(match, child));
}
} else {
finalDocs.addAll(loadConfigurationFiles(includeFileName, child));//递归调用,把所有include加载到finalDocs
}
}
}
}
finalDocs.add(doc);
loadedFileUrls.add(url.toString());
}
if (LOG.isDebugEnabled()) {
LOG.debug("Loaded action configuration from: " + fileName);
}
}
return finalDocs;
}
/**
* 获取fileName的Iterator<URL>
* @param fileName
* @return
* @throws IOException
*/
protected Iterator<URL> getConfigurationUrls(String fileName) throws IOException {
return ClassLoaderUtil.getResources(fileName, XmlConfigurationProvider.class, false);
}
至此,struts-default.xml已经转换成一个document对象放入docs中,接下来调用register再对转换好的docs中的内容进行解析
3:StrutsXmlConfigurationProvider(struts-plugin.xml)
同2:
4:StrutsXmlConfigurationProvider(struts.xml)
同2:
5:LegacyPropertiesConfigurationProvider
该类的register中的代码具体如下:
/**
* 注册参数,把需要配置的参数放入builder对象的factories中
*/
@SuppressWarnings("unchecked")
public void register(ContainerBuilder builder, LocatableProperties props)throws ConfigurationException {
//获取一个Settings的实例
final Settings settings = Settings.getInstance();
loadSettings(props, settings);
// Set default locale by lazily resolving the locale property as needed into a Locale object
builder.factory(Locale.class, new Factory() {
private Locale locale;
public synchronized Object create(Context context) throws Exception {
if (locale == null) {
String loc = context.getContainer().getInstance(String.class, StrutsConstants.STRUTS_LOCALE);
if (loc != null) {
StringTokenizer localeTokens = new StringTokenizer(loc, "_");
String lang = null;
String country = null;
if (localeTokens.hasMoreTokens()) {
lang = localeTokens.nextToken();
}
if (localeTokens.hasMoreTokens()) {
country = localeTokens.nextToken();
}
locale = new Locale(lang, country);
} else {
if (LOG.isInfoEnabled()) {
LOG.info("No locale define, substituting the default VM locale");
}
locale = Locale.getDefault();
}
}
return locale;
}
});
}
6:用户配置
具体代码具体分析
7:web.xml的filter中配置的参数
//把web.xml中配置的fileter中的参数放入props中
public void register(ContainerBuilder builder, LocatableProperties props) throws ConfigurationException {
props.putAll(initParams);
}
8:BeanSelectionProvider
该类内部的register方法如下:
/**
* 注册
*/
public void register(ContainerBuilder builder, LocatableProperties props) {
/**
* 把这些配置放入builder的factories中
*/
alias(ObjectFactory.class, StrutsConstants.STRUTS_OBJECTFACTORY, builder, props);
alias(FileManager.class, StrutsConstants.STRUTS_FILEMANAGER, builder, props);
alias(XWorkConverter.class, StrutsConstants.STRUTS_XWORKCONVERTER, builder, props);
alias(TextProvider.class, StrutsConstants.STRUTS_XWORKTEXTPROVIDER, builder, props, Scope.DEFAULT);
alias(ActionProxyFactory.class, StrutsConstants.STRUTS_ACTIONPROXYFACTORY, builder, props);
alias(ObjectTypeDeterminer.class, StrutsConstants.STRUTS_OBJECTTYPEDETERMINER, builder, props);
alias(ActionMapper.class, StrutsConstants.STRUTS_MAPPER_CLASS, builder, props);
alias(MultiPartRequest.class, StrutsConstants.STRUTS_MULTIPART_PARSER, builder, props, Scope.DEFAULT);
alias(FreemarkerManager.class, StrutsConstants.STRUTS_FREEMARKER_MANAGER_CLASSNAME, builder, props);
alias(VelocityManager.class, StrutsConstants.STRUTS_VELOCITY_MANAGER_CLASSNAME, builder, props);
alias(UrlRenderer.class, StrutsConstants.STRUTS_URL_RENDERER, builder, props);
alias(ActionValidatorManager.class, StrutsConstants.STRUTS_ACTIONVALIDATORMANAGER, builder, props);
alias(ValueStackFactory.class, StrutsConstants.STRUTS_VALUESTACKFACTORY, builder, props);
alias(ReflectionProvider.class, StrutsConstants.STRUTS_REFLECTIONPROVIDER, builder, props);
alias(ReflectionContextFactory.class, StrutsConstants.STRUTS_REFLECTIONCONTEXTFACTORY, builder, props);
alias(PatternMatcher.class, StrutsConstants.STRUTS_PATTERNMATCHER, builder, props);
alias(StaticContentLoader.class, StrutsConstants.STRUTS_STATIC_CONTENT_LOADER, builder, props);
alias(UnknownHandlerManager.class, StrutsConstants.STRUTS_UNKNOWN_HANDLER_MANAGER, builder, props);
alias(UrlHelper.class, StrutsConstants.STRUTS_URL_HELPER, builder, props);
/**
* 判断props中的devMode是否为true
*/
if ("true".equalsIgnoreCase(props.getProperty(StrutsConstants.STRUTS_DEVMODE))) {
//设置国际化
props.setProperty(StrutsConstants.STRUTS_I18N_RELOAD, "true");
props.setProperty(StrutsConstants.STRUTS_CONFIGURATION_XML_RELOAD, "true");
props.setProperty(StrutsConstants.STRUTS_FREEMARKER_TEMPLATES_CACHE, "false");
props.setProperty(StrutsConstants.STRUTS_FREEMARKER_TEMPLATES_CACHE_UPDATE_DELAY, "0");
// Convert struts properties into ones that xwork expects
props.setProperty("devMode", "true");
} else {
props.setProperty("devMode", "false");
}
//把struts2的properties转换成xwork的properties
convertIfExist(props, StrutsConstants.STRUTS_LOG_MISSING_PROPERTIES, "logMissingProperties");
convertIfExist(props, StrutsConstants.STRUTS_ENABLE_OGNL_EXPRESSION_CACHE, "enableOGNLExpressionCache");
convertIfExist(props, StrutsConstants.STRUTS_ALLOW_STATIC_METHOD_ACCESS, "allowStaticMethodAccess");
LocalizedTextUtil.addDefaultResourceBundle("org/apache/struts2/struts-messages");
//加载用户资源绑定
loadCustomResourceBundles(props);
}
在这个方法内部调用了该类的alias方法,该方法具体如下:
/**
* 调用该类的alias(Class type, String key, ContainerBuilder builder, Properties props, Scope scope)方法,同时传递scope为single
* @param type
* @param key
* @param builder
* @param props
*/
void alias(Class type, String key, ContainerBuilder builder, Properties props) {
alias(type, key, builder, props, Scope.SINGLETON);
}
接着调用另一个alias方法,该方法具体如下:
/**
* 把参数放入builder中
* @param type class类型
* @param key
* @param builder
* @param props
* @param scope
*/
void alias(Class type, String key, ContainerBuilder builder, Properties props, Scope scope) {
//判断builder中是否存在指定type的参数
if (!builder.contains(type)) {
/**
* 从props中获取指定key和默认值的字符串
*/
String foundName = props.getProperty(key, DEFAULT_BEAN_NAME);
//检测builder中是否包含该type和指定默认值的配置
if (builder.contains(type, foundName)) {
if (LOG.isInfoEnabled()) {
LOG.info("Choosing bean (#0) for (#1)", foundName, type.getName());
}
//重新加载到builder中
builder.alias(type, foundName, Container.DEFAULT_NAME);
} else {
try {
//反射生成class
Class cls = ClassLoaderUtil.loadClass(foundName, this.getClass());
if (LOG.isDebugEnabled()) {
LOG.debug("Choosing bean (#0) for (#1)", cls.getName(), type.getName());
}
//把cls添加到builder中的factories中
builder.factory(type, cls, scope);
} catch (ClassNotFoundException ex) {
// Perhaps a spring bean id, so we'll delegate to the object factory at runtime
if (LOG.isDebugEnabled()) {
LOG.debug("Choosing bean (#0) for (#1) to be loaded from the ObjectFactory", foundName, type.getName());
}
if (DEFAULT_BEAN_NAME.equals(foundName)) {
// Probably an optional bean, will ignore
} else {
if (ObjectFactory.class != type) {
builder.factory(type, new ObjectFactoryDelegateFactory(foundName, type), scope);
} else {
throw new ConfigurationException("Cannot locate the chosen ObjectFactory implementation: " + foundName);
}
}
}
}
} else {
if (LOG.isWarnEnabled()) {
LOG.warn("Unable to alias bean type (#0), default mapping already assigned.", type.getName());
}
}
}
ContainerBuilder的代码在上面已经给出了分析,因此在这里不对其方法再次进行介绍。
10)props.setConstants(builder);
调用ContainerProperties的setConstants(ContainerBuilder builder)方法,把props中的信息放入ContainerBuilder的factories中;具体代码在上面已经展示过了
11)这行代码调用了ContainerBuilder的factory方法,向其factories中添加了一个Configuration的工厂类,该类的实例化为一个DefaultConfiguration对象
builder.factory(Configuration.class, new Factory<Configuration>() {
public Configuration create(Context context) throws Exception {
return DefaultConfiguration.this;
}
});