代码/**
* Pxb IOC.
* Copyright 2008 Panxiaobo.
* All rights reserved.
* $Id: DefaultFactoryBuilder.java 35 2008-08-18 11:10:07Z Panxiaobo $
*/
package pxb.ioc.impl.builders;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;
import pxb.ioc.Context;
import pxb.ioc.Factory;
import pxb.ioc.ImplementedBy;
import pxb.ioc.Inject;
import pxb.ioc.InjectException;
import pxb.ioc.InstanceCreater;
import pxb.ioc.Key;
import pxb.ioc.Scope;
import pxb.ioc.ScopeFactory;
import pxb.ioc.ScopeNotFoundExcpetion;
import pxb.ioc.Scoped;
import pxb.ioc.builders.FactoryBuilder;
import pxb.ioc.builders.InstanceCreaterBuilder;
import pxb.ioc.managers.FactoryManager;
/**
* @author Panxiaobo [pxb1988@126.com]
*/
public class DefaultFactoryBuilder implements FactoryBuilder
{
protected ClassLoader classLoader;
protected Map<Class<?>, String> clazzScops = new HashMap<Class<?>, String>();
protected FactoryManager factoryManager;
protected InstanceCreaterBuilder instanceCreaterBuilder;
protected Map<String, Scope> scopes = new HashMap<String, Scope>();
public DefaultFactoryBuilder()
{
super();
classLoader = this.getClass().getClassLoader();
}
public void addScope(String name, Scope scope)
{
this.scopes.put(name, scope);
}
/*
* (non-Javadoc)
* @see pxb.ioc.FactoryBuilder#buildFactory(pxb.ioc.FactoryManager,
* java.util.Map, pxb.ioc.Key)
*/
@SuppressWarnings("unchecked")
public <T> Factory<T> buildFactory(Key<T> key, Class<? extends T> type)
throws Exception
{
synchronized (type)
{
Factory<T> f = factoryManager.getFactory(key, false);
if (f != null)
return f;
int modifiers = type.getModifiers();
if (Modifier.isInterface(modifiers)
|| Modifier.isAbstract(modifiers)
|| !Modifier.isPublic(modifiers))
{
ImplementedBy implementedBy = type
.getAnnotation(ImplementedBy.class);
if (implementedBy == null)
{
throw new InjectException("No Maping Found For Key:" + key);
}
Class<?> clazz = classLoader.loadClass(implementedBy.value());
type = (Class<T>) clazz;
}
String scopeName = this.clazzScops.get(type);
if (scopeName == null)
{
Scoped scoped = type.getAnnotation(Scoped.class);
scopeName = scoped == null ? Scope.DEFAULT : scoped.value();
}
Scope scope = scopes.get(scopeName);
if (scope == null)
{
throw new ScopeNotFoundExcpetion(scopeName, type);
}
ScopeFactory<T> factory = scope.createFactory(key);
// lock the factory
synchronized (factory)
{
factoryManager.addFactory(key, factory);
// just for test Thread safe
// Thread.currentThread().sleep(1000);
// InstanceCreater<T> instanceCreater = instanceCreaterBuilder
// .buildInstanceCreater(type);
******************************************************************************
这里并不构造instnceCreater,而是构造了一个代理,真正掉用到的时候才构造
InstanceCreater<T> instanceCreater = new ProxyInstanceCreater(
factory, instanceCreaterBuilder, type);
*******************************************************************************
factory.setInstanceCreater(instanceCreater);
}
return factory;
}
}
private static class ProxyInstanceCreater<T> implements InstanceCreater<T>
{
private InstanceCreaterBuilder instanceCreaterBuilder;
private Class<T> type;
private volatile InstanceCreater<T> instanceCreater;
private ScopeFactory<T> factory;
public ProxyInstanceCreater(ScopeFactory<T> factory,
InstanceCreaterBuilder instanceCreaterBuilder, Class<T> type)
{
this.factory = factory;
this.instanceCreaterBuilder = instanceCreaterBuilder;
this.type = type;
}
public synchronized void doCreate() throws Exception
{
if (this.instanceCreater == null)
{//在这之前使用double checked lock
//真正构造
instanceCreater = instanceCreaterBuilder
.buildInstanceCreater(type);
//设置给对应的factory,替代自己
factory.setInstanceCreater(instanceCreater);
this.factory = null;
}
}
/*
* (non-Javadoc)
* @see pxb.ioc.InstanceCreater#create(pxb.ioc.Context)
*/
public T create(Context context) throws Exception
{
if (this.instanceCreater == null)
this.doCreate();
return instanceCreater.create(context);
}
/*
* (non-Javadoc)
* @see pxb.ioc.InstanceCreater#inject(pxb.ioc.Context,
* java.lang.Object)
*/
public void inject(Context context, T t) throws Exception
{
if (this.instanceCreater == null)
this.doCreate();
instanceCreater.inject(context, t);
}
}
/**
* @param factoryManager
* the factoryManager to set
*/
@Inject
public void setFactoryManager(FactoryManager factoryManager)
{
this.factoryManager = factoryManager;
}
/**
* @param instanceCreaterBuilder
* the instanceCreaterBuilder to set
*/
@Inject
public void setInstanceCreaterBuilder(
InstanceCreaterBuilder instanceCreaterBuilder)
{
this.instanceCreaterBuilder = instanceCreaterBuilder;
}
/*
* (non-Javadoc)
* @see pxb.ioc.builders.FactoryBuilder#setScope(java.lang.Class,
* java.lang.String)
*/
public void setScope(Class<?> type, String name)
{
this.clazzScops.put(type, name);
}
}
|