这一步我们进一步改进,让框架能够识别@Named
首先自然是Container.java的修改,修改后的代码如下
public class Container {
//利用一个容器来存储类
private Map<Class<?>,Binder<?>> mapper;
public Container() {
mapper = new HashMap<>();
}
@SuppressWarnings("unchecked")
public <T> _binder<T> registerClass(Class<T> inter) {
Binder<T> binder;
if (mapper.containsKey(inter)) {
binder= (Binder<T>) mapper.get(inter);
}else {
binder = new Binder<>(inter);
mapper.put(inter,binder);
}
return new _binder<>(binder);
}
@SuppressWarnings("unchecked")
public <T> T getImpl(Class<T> inter) {
return (T) mapper.get(inter).get();
}
public <T> T getImplByName(Class<T> inter,String name) {
return (T) mapper.get(inter).get(name);
}
public boolean hasRegistered(Class inter) {
return mapper.containsKey(inter);
}
public class _binder<T> {
private Binder<T> binder;
private String name = Binder.DEFAULT_BIND_NAME;
_binder(Binder<T> binder) {
this.binder = binder;
}
private void setName(String name) {
this.name = name;
}
public _binder<T> named(String name) {
setName(name);
return this;
}
public _binder<T> providedBy(Provider<T> provider) {
binder.bind(name,provider);
return this;
}
public <K extends T> _binder<T> instanceOf(Class<K> impl) {
if (impl.isAnnotationPresent(Named.class)) {
Named named = impl.getAnnotation(Named.class);
this.named(named.value());
}
return providedBy(new ParseClass<>(binder.gettClass(),impl,Container.this));
}
}
}
注意到这里有个内部类_binder,以及将Mapper的value类型改成了下面的Binder。
Binder.java如下
class Binder<T> {
static String DEFAULT_BIND_NAME = "DEFAULT_BIND_NAME";
private Class<T> tClass;
private Map<String,Provider<T>> providers;
Binder(Class<T> tClass) {
this.tClass = tClass;
providers = new HashMap<>();
}
Binder<T> bind(String name, Provider<T> provider) {
providers.put(name,provider);
return this;
}
public Binder<T> bind(Provider<T> provider) {
return bind(DEFAULT_BIND_NAME,provider);
}
T get(String name) {
if (providers.containsKey(name)) {
return providers.get(name).get();
}
throw new RuntimeException("尚未绑定");
}
T get() {
return get(DEFAULT_BIND_NAME);
}
}
之所以这么做的目的是我想提供一种流式api,container.register(class).providedBy()这种操作。
然后ParseClass.java修改后的如下:
class ParseClass<T,K extends T> implements Provider<T> {
private Class<T> tClass;
private Class<K> implClass;
private Container container;
ParseClass(Class<T> tClass,Class<K> implClass,Container container) {
this.tClass = tClass;
this.container = container;
this.implClass = implClass;
}
@SuppressWarnings("unchecked")
private T newInstance()
throws IllegalAccessException, InvocationTargetException, InstantiationException {
if (!container.hasRegistered(tClass)) {
return null;
}
Class<K> implement = implClass;
Constructor[] constructors = implement.getConstructors();
if (constructors.length == 0){
//没有构造器
throw new NoConstructorsError();
}
T instance = null;
for (Constructor<K> constructor:constructors) {
if (constructor.getParameterCount() == 0) {
instance = constructor.newInstance();
break;
}
if (constructor.isAnnotationPresent(Inject.class)) {
//获得此构造函数的参数
Object[] params = new Object[constructor.getParameterCount()];
int j = 0;
for (Parameter p: constructor.getParameters()){
params[j++] = getValue(p,p.getType());
}
instance = constructor.newInstance(params);
break;
}
}
if (instance != null) {
initFields(instance,implement);
initMethod(instance,implement);
return instance;
}
return null;
}
private void initFields(T instance, Class<K> kClass)
throws IllegalAccessException, InstantiationException, InvocationTargetException {
for (Field field : kClass.getDeclaredFields()) {
if (field.isAnnotationPresent(Inject.class)) {
Object value = getValue(field,field.getType());
field.setAccessible(true);
field.set(instance,value);
field.setAccessible(false);
}
}
}
@SuppressWarnings("unchecked")
private void initMethod(T instance, Class<K> kClass) throws IllegalAccessException, InstantiationException, InvocationTargetException {
for (Method method : kClass.getMethods()) {
if (method.isAnnotationPresent(Inject.class)) {
Object[] params = new Object[method.getParameterCount()];
int j = 0;
for (Parameter parameter: method.getParameters()) {
params[j++] = getValue(parameter,parameter.getType());
}
method.invoke(instance,params);
}
}
}
private Object getValue(AnnotatedElement accessibleObject,Class tClass) {
if (accessibleObject.isAnnotationPresent(Named.class)) {
Named named = accessibleObject.getAnnotation(Named.class);
return container.getImplByName(tClass,named.value());
}else {
return container.getImpl(tClass);
}
}
@Override
public T get() {
try {
return newInstance();
} catch (IllegalAccessException | InvocationTargetException | InstantiationException e) {
e.printStackTrace();
throw new RuntimeException("无法获取该类实例");
}
}
}
这些文章也同步到了我自己的公众号平台:互联网科技杂谈