我们可以看到,在Container的默认实现,ContainerImpl中有两个实例变量。factoris和factoryNamesByType。
class ContainerImpl implements Container {
final Map<Key<?>, InternalFactory<?>> factories;
final Map<Class<?>, Set<String>> factoryNamesByType;
ContainerImpl( Map<Key<?>, InternalFactory<?>> factories ) {
this.factories = factories;
Map<Class<?>, Set<String>> map = new HashMap<Class<?>, Set<String>>();
for ( Key<?> key : factories.keySet() ) {
Set<String> names = map.get(key.getType());
if (names == null) {
names = new HashSet<String>();
map.put(key.getType(), names);
}
names.add(key.getName());
}
for ( Entry<Class<?>, Set<String>> entry : map.entrySet() ) {
entry.setValue(Collections.unmodifiableSet(entry.getValue()));
}
this.factoryNamesByType = Collections.unmodifiableMap(map);
}
}
class Key<T> {
final Class<T> type;
final String name;
final int hashCode;
//...
}
看这个type与name是不是想起什么了?
对,就是struts-default.xml
<struts>
<bean class="com.opensymphony.xwork2.ObjectFactory" name="struts"/>
<bean type="com.opensymphony.xwork2.factory.ResultFactory" name="struts" class="org.apache.struts2.factory.StrutsResultFactory" />
<bean type="com.opensymphony.xwork2.factory.ActionFactory" name="struts" class="com.opensymphony.xwork2.factory.DefaultActionFactory" />
<bean type="com.opensymphony.xwork2.factory.ConverterFactory" name="struts" class="com.opensymphony.xwork2.factory.DefaultConverterFactory" />
<bean type="com.opensymphony.xwork2.ActionProxyFactory" name="struts" class="org.apache.struts2.impl.StrutsActionProxyFactory"/>
<bean type="com.opensymphony.xwork2.ActionProxyFactory" name="prefix" class="org.apache.struts2.impl.PrefixBasedActionProxyFactory"/>
....
<struts>type和name能唯一确认了一个bean。interface InternalFactory<T> extends Serializable {
/**
* Creates an object to be injected.
*
* @param context of this injection
* @return instance to be injected
*/
T create(InternalContext context);
}InternalFactory中存储了生成一个类的方法,而不是这个类的实例。
ContainerImpl的inject方法如下所示。
//o就是人 人需要一辆车
void inject( Object o, InternalContext context ) {
//获得人身上的所有注入器
List<Injector> injectors = this.injectors.get(o.getClass());
for ( Injector injector : injectors ) {
//调用注入器
injector.inject(context, o);
}
}获得"人"上都有哪些注入器。public class Person{
private Car car;
public Person(){
//其他代码
}
@Inject()
public void setCar(Car c){
this.car=c;
}
public void drive(){
car.drive();
}
}注入器分两类,方法注入器,属性注入器。 /**
* Injects a field or method in a given object.
*/
interface Injector extends Serializable {
void inject( InternalContext context, Object o );
}static class FieldInjector implements Injector {
final Field field;
final InternalFactory<?> factory;
final ExternalContext<?> externalContext;
public FieldInjector( ContainerImpl container, Field field, String name )
throws MissingDependencyException {
this.field = field;
...
}
Key<?> key = Key.newInstance(field.getType(), name);
factory = container.getFactory(key); //标识2
...
public void inject( InternalContext context, Object o ) {
ExternalContext<?> previous = context.getExternalContext();
context.setExternalContext(externalContext);
//省略trycatch
field.set(o, factory.create(context));//标识1
}
}标识2 就是从容器里获得这个key的InternalFactory public void set(Object obj, Object value)
throws IllegalArgumentException, IllegalAccessException如果对person p的字段Car c,及容器内部的Car c2来说,final Map<Class<?>, List<Injector>> injectors =
new ReferenceCache<Class<?>, List<Injector>>() {
@Override
protected List<Injector> create( Class<?> key ) {
List<Injector> injectors = new ArrayList<Injector>();
addInjectors(key, injectors); //标识4
return injectors;
}
};怎么回事,看着好复杂呀。public abstract class ReferenceCache<K, V> extends ReferenceMap<K, V> {
private static final long serialVersionUID = 0;
transient ConcurrentMap<Object, Future<V>> futures =
new ConcurrentHashMap<Object, Future<V>>();
transient ThreadLocal<Future<V>> localFuture = new ThreadLocal<Future<V>>();
protected abstract V create(K key);
//...
}
ReferenceMap实现了map接口。
有了ReferenceCatch,我们操作map就高效多了,当我们调用get方法时,如果key已经存在,就直接返回,否则就调用creat产生并缓存,下一次就不用再create了。
同时大家注意这个create是个抽象方法。
再换句话说,ContainerImpl中的injectors是在运行期动态构建的。 void addInjectors( Class clazz, List<Injector> injectors ) {
if (clazz == Object.class) {
return;
}
// Add injectors for superclass first.
//英文看懂了吧, 先调用父类的
addInjectors(clazz.getSuperclass(), injectors);
// TODO (crazybob): Filter out overridden members.
addInjectorsForFields(clazz.getDeclaredFields(), false, injectors);
addInjectorsForMethods(clazz.getDeclaredMethods(), false, injectors);
}我们看看属性注入器。 void addInjectorsForFields( Field[] fields, boolean statics,
List<Injector> injectors ) {
addInjectorsForMembers(Arrays.asList(fields), statics, injectors,
new InjectorFactory<Field>() {
//标识5
public Injector create( ContainerImpl container, Field field, String name ) throws MissingDependencyException {
return new FieldInjector(container, field, name);
}
});
}在addInjectorsForFields里面,只有一行代码,就是调用addInjectorsForMembers,其参数的最后一个类型是InjectorFactory。 <M extends Member & AnnotatedElement> void addInjectorsForMembers(
List<M> members, boolean statics, List<Injector> injectors,
InjectorFactory<M> injectorFactory ) {
for ( M member : members ) {
if (isStatic(member) == statics) {
//看看这个member是否有Inject这个annotation
Inject inject = member.getAnnotation(Inject.class);
if (inject != null) {
try {
//这里调用injectorFactory了
//看上面代码的标识5
//就是产生一个injecter而已
injectors.add(injectorFactory.create(this, member, inject.value()));
} catch ( MissingDependencyException e ) {
if (inject.required()) {
throw new DependencyException(e);
}
}
}
}
}
}
如果大家再看看addInjectorsForMethods,只要我们在类的方法或成员变量上加上Inject这annotation,容器就会给参数注入一个相应的实例。
先看到这里吧,下一节我们再看XWork的实现机理。
(分析struts2的源码对我来说,还是很有难度的,文章写得不好,欢迎拍砖,共同进步)
感谢glt
原文:http://blog.csdn.net/dlf123321/article/details/43059933