use of org.nutz.ioc.meta.IocField in project nutz by nutzam.
the class XmlIocLoaderTest method testXmlIocLoader.
@Test
public void testXmlIocLoader() throws ObjectLoadException {
IocLoader iocLoader = getNew("org/nutz/ioc/loader/xml/conf/zzh-offered.xml");
assertTrue(iocLoader.getName() != null);
assertTrue(iocLoader.getName().length > 0);
for (String name : iocLoader.getName()) {
assertNotNull(name);
assertNotNull(iocLoader.load(null, name));
IocObject iocObject = iocLoader.load(null, name);
if (iocObject.hasArgs()) {
for (IocValue iocValue : iocObject.getArgs()) {
iocValue.getType();
iocValue.getValue();
checkValue(iocValue);
}
}
if (iocObject.getFields() != null) {
for (IocField iocField : iocObject.getFields().values()) {
assertNotNull(iocField.getName());
if (iocField.getValue() != null) {
IocValue iocValue = iocField.getValue();
checkValue(iocValue);
}
}
}
}
iocLoader.load(null, "obj").getFields().values().iterator().next().getValue().getValue();
}
use of org.nutz.ioc.meta.IocField in project nutz by nutzam.
the class IocLoading method map2iobj.
@SuppressWarnings("unchecked")
public IocObject map2iobj(Map<String, Object> map) throws ObjectLoadException {
final IocObject iobj = new IocObject();
if (!isIocObject(map)) {
for (Entry<String, Object> en : map.entrySet()) {
IocField ifld = new IocField();
ifld.setName(en.getKey());
ifld.setValue(object2value(en.getValue()));
iobj.addField(ifld);
}
// if (log.isWarnEnabled()) // TODO 移除这种兼容性
// log.warn("Using *Declared* ioc-define (without type or events)!!! Pls use Standard Ioc-Define!!"
// + " Bean will define as:\n"
// + Json.toJson(iobj));
} else {
Object v = map.get("type");
// type
try {
String typeName = (String) v;
if (!Strings.isBlank(typeName)) {
iobj.setType(Lang.loadClass(typeName));
}
} catch (Exception e) {
throw E(e, "Wrong type name: '%s'", v);
}
// singleton
try {
v = map.get("singleton");
if (null != v)
iobj.setSingleton(Castors.me().castTo(v, boolean.class));
} catch (FailToCastObjectException e) {
throw E(e, "Wrong singleton: '%s'", v);
}
// scope
v = map.get("scope");
if (null != v)
iobj.setScope(v.toString());
// events
try {
v = map.get("events");
if (null != v) {
IocEventSet ies = Lang.map2Object((Map<?, ?>) v, IocEventSet.class);
iobj.setEvents(ies);
}
} catch (Exception e) {
throw E(e, "Wrong events: '%s'", v);
}
// args
try {
v = map.get("args");
if (null != v) {
Lang.each(v, new Each<Object>() {
public void invoke(int i, Object ele, int length) {
iobj.addArg(object2value(ele));
}
});
}
} catch (Exception e) {
throw E(e, "Wrong args: '%s'", v);
}
// fields
try {
v = map.get("fields");
if (null != v) {
Map<String, Object> fields = (Map<String, Object>) v;
for (Entry<String, Object> en : fields.entrySet()) {
IocField ifld = new IocField();
ifld.setName(en.getKey());
ifld.setValue(object2value(en.getValue()));
iobj.addField(ifld);
}
}
} catch (Exception e) {
throw E(e, "Wrong args: '%s'", v);
}
// factory方法
v = map.get("factory");
if (v != null && !Strings.isBlank(v.toString())) {
iobj.setFactory(v.toString());
}
}
return iobj;
}
use of org.nutz.ioc.meta.IocField in project nutz by nutzam.
the class ObjectMakerImpl method make.
public ObjectProxy make(final IocMaking ing, IocObject iobj) {
// 获取 Mirror, AOP 将在这个方法中进行
Mirror<?> mirror = ing.getMirrors().getMirror(iobj.getType(), ing.getObjectName());
// 获取配置的对象事件集合
IocEventSet iocEventSet = iobj.getEvents();
// 建立对象代理,并保存在上下文环境中 只有对象为 singleton
// 并且有一个非 null 的名称的时候才会保存
// 就是说,所有内部对象,将会随这其所附属的对象来保存,而自己不会单独保存
ObjectProxy op = new ObjectProxy();
if (iobj.isSingleton() && null != ing.getObjectName())
ing.getContext().save(iobj.getScope(), ing.getObjectName(), op);
// 为对象代理设置触发事件
if (null != iobj.getEvents()) {
op.setFetch(createTrigger(mirror, iocEventSet.getFetch()));
op.setDepose(createTrigger(mirror, iocEventSet.getDepose()));
}
try {
// 准备对象的编织方式
DefaultWeaver dw = new DefaultWeaver();
op.setWeaver(dw);
// 为编织器设置事件触发器:创建时
if (null != iobj.getEvents()) {
dw.setCreate(createTrigger(mirror, iocEventSet.getCreate()));
}
// 构造函数参数
ValueProxy[] vps = new ValueProxy[Lang.length(iobj.getArgs())];
for (int i = 0; i < vps.length; i++) vps[i] = ing.makeValue(iobj.getArgs()[i]);
dw.setArgs(vps);
// 先获取一遍,根据这个数组来获得构造函数
Object[] args = new Object[vps.length];
boolean hasNullArg = false;
for (int i = 0; i < args.length; i++) {
args[i] = vps[i].get(ing);
if (args[i] == null) {
hasNullArg = true;
}
}
// 缓存构造函数
if (iobj.getFactory() != null) {
// factory这属性, 格式应该是 类名#方法名 或者 $iocbean#方法名
final String[] ss = iobj.getFactory().split("#", 2);
if (ss[0].startsWith("$")) {
dw.setBorning(new Borning<Object>() {
public Object born(Object... args) {
Object factoryBean = ing.getIoc().get(null, ss[0].substring(1));
return Mirror.me(factoryBean).invoke(factoryBean, ss[1], args);
}
});
} else {
Mirror<?> mi = Mirror.me(Lang.loadClass(ss[0]));
if (hasNullArg) {
Method m = (Method) Lang.first(mi.findMethods(ss[1], args.length));
if (m == null)
throw new IocException(ing.getObjectName(), "Factory method not found --> ", iobj.getFactory());
dw.setBorning(new MethodCastingBorning<Object>(m));
} else {
Method m = mi.findMethod(ss[1], args);
dw.setBorning(new MethodBorning<Object>(m));
}
}
} else {
dw.setBorning((Borning<?>) mirror.getBorning(args));
}
// 如果这个对象是容器中的单例,那么就可以生成实例了
// 这一步非常重要,它解除了字段互相引用的问题
Object obj = null;
if (iobj.isSingleton()) {
obj = dw.born(ing);
op.setObj(obj);
}
// 获得每个字段的注入方式
List<IocField> _fields = new ArrayList<IocField>(iobj.getFields().values());
FieldInjector[] fields = new FieldInjector[_fields.size()];
for (int i = 0; i < fields.length; i++) {
IocField ifld = _fields.get(i);
try {
ValueProxy vp = ing.makeValue(ifld.getValue());
fields[i] = FieldInjector.create(mirror, ifld.getName(), vp, ifld.isOptional());
} catch (Exception e) {
throw Lang.wrapThrow(e, "Fail to eval Injector for field: '%s'", ifld.getName());
}
}
dw.setFields(fields);
// 如果是单例对象,前面已经生成实例了,在这里需要填充一下它的字段
if (null != obj)
dw.fill(ing, obj);
// 对象创建完毕,如果有 create 事件,调用它
dw.onCreate(obj);
} catch (IocException e) {
ing.getContext().remove(iobj.getScope(), ing.getObjectName());
((IocException) e).addBeanNames(ing.getObjectName());
throw e;
}// 当异常发生,从 context 里移除 ObjectProxy
catch (Throwable e) {
ing.getContext().remove(iobj.getScope(), ing.getObjectName());
throw new IocException(ing.getObjectName(), e, "throw Exception when creating");
}
// 返回
return op;
}
use of org.nutz.ioc.meta.IocField in project nutz by nutzam.
the class AnnotationIocLoader method addClass.
protected void addClass(Class<?> classZ) {
if (classZ.isInterface() || classZ.isMemberClass() || classZ.isEnum() || classZ.isAnnotation() || classZ.isAnonymousClass())
return;
int modify = classZ.getModifiers();
if (Modifier.isAbstract(modify) || (!Modifier.isPublic(modify)))
return;
IocBean iocBean = classZ.getAnnotation(IocBean.class);
if (iocBean != null) {
if (log.isDebugEnabled())
log.debugf("Found @IocBean : %s", classZ);
// 采用 @IocBean->name
String beanName = iocBean.name();
if (Strings.isBlank(beanName)) {
// 否则采用 @InjectName
InjectName innm = classZ.getAnnotation(InjectName.class);
if (null != innm && !Strings.isBlank(innm.value())) {
beanName = innm.value();
} else // 大哥(姐),您都不设啊!? 那就用 simpleName 吧
{
beanName = Strings.lowerFirst(classZ.getSimpleName());
}
}
// 重名了, 需要用户用@IocBean(name="xxxx") 区分一下
if (map.containsKey(beanName))
throw new IocException(beanName, "Duplicate beanName=%s, by %s !! Have been define by %s !!", beanName, classZ.getName(), map.get(beanName).getType().getName());
IocObject iocObject = new IocObject();
iocObject.setType(classZ);
map.put(beanName, iocObject);
iocObject.setSingleton(iocBean.singleton());
if (!Strings.isBlank(iocBean.scope()))
iocObject.setScope(iocBean.scope());
// 看看构造函数都需要什么函数
String[] args = iocBean.args();
// args = iocBean.param();
if (null != args && args.length > 0)
for (String value : args) iocObject.addArg(Iocs.convert(value, true));
// 设置Events
IocEventSet eventSet = new IocEventSet();
iocObject.setEvents(eventSet);
if (!Strings.isBlank(iocBean.create()))
eventSet.setCreate(iocBean.create().trim().intern());
if (!Strings.isBlank(iocBean.depose()))
eventSet.setDepose(iocBean.depose().trim().intern());
if (!Strings.isBlank(iocBean.fetch()))
eventSet.setFetch(iocBean.fetch().trim().intern());
// 处理字段(以@Inject方式,位于字段)
List<String> fieldList = new ArrayList<String>();
Mirror<?> mirror = Mirror.me(classZ);
Field[] fields = mirror.getFields(Inject.class);
for (Field field : fields) {
Inject inject = field.getAnnotation(Inject.class);
// 无需检查,因为字段名是唯一的
// if(fieldList.contains(field.getName()))
// throw duplicateField(classZ,field.getName());
IocField iocField = new IocField();
iocField.setName(field.getName());
IocValue iocValue;
if (Strings.isBlank(inject.value())) {
iocValue = new IocValue();
iocValue.setType(IocValue.TYPE_REFER_TYPE);
iocValue.setValue(field);
} else
iocValue = Iocs.convert(inject.value(), true);
iocField.setValue(iocValue);
iocField.setOptional(inject.optional());
iocObject.addField(iocField);
fieldList.add(iocField.getName());
}
// 处理字段(以@Inject方式,位于set方法)
Method[] methods;
try {
methods = classZ.getMethods();
} catch (Exception e) {
// 如果获取失败,就忽略之
log.infof("Fail to call getMethods() in Class=%s, miss class or Security Limit, ignore it", classZ, e);
methods = new Method[0];
} catch (NoClassDefFoundError e) {
log.infof("Fail to call getMethods() in Class=%s, miss class or Security Limit, ignore it", classZ, e);
methods = new Method[0];
}
for (Method method : methods) {
Inject inject = method.getAnnotation(Inject.class);
if (inject == null)
continue;
// 过滤特殊方法
int m = method.getModifiers();
if (Modifier.isAbstract(m) || (!Modifier.isPublic(m)) || Modifier.isStatic(m))
continue;
String methodName = method.getName();
if (methodName.startsWith("set") && methodName.length() > 3 && method.getParameterTypes().length == 1) {
IocField iocField = new IocField();
iocField.setName(Strings.lowerFirst(methodName.substring(3)));
if (fieldList.contains(iocField.getName()))
throw duplicateField(beanName, classZ, iocField.getName());
IocValue iocValue;
if (Strings.isBlank(inject.value())) {
iocValue = new IocValue();
iocValue.setType(IocValue.TYPE_REFER_TYPE);
iocValue.setValue(Strings.lowerFirst(methodName.substring(3)) + "#" + method.getParameterTypes()[0].getName());
} else
iocValue = Iocs.convert(inject.value(), true);
iocField.setValue(iocValue);
iocObject.addField(iocField);
fieldList.add(iocField.getName());
}
}
// 处理字段(以@IocBean.field方式)
String[] flds = iocBean.fields();
if (flds != null && flds.length > 0) {
for (String fieldInfo : flds) {
if (fieldList.contains(fieldInfo))
throw duplicateField(beanName, classZ, fieldInfo);
IocField iocField = new IocField();
if (fieldInfo.contains(":")) {
// dao:jndi:dataSource/jdbc形式
String[] datas = fieldInfo.split(":", 2);
// 完整形式, 与@Inject完全一致了
iocField.setName(datas[0]);
iocField.setValue(Iocs.convert(datas[1], true));
iocObject.addField(iocField);
} else {
// 基本形式, 引用与自身同名的bean
iocField.setName(fieldInfo);
IocValue iocValue = new IocValue();
iocValue.setType(IocValue.TYPE_REFER);
iocValue.setValue(fieldInfo);
iocField.setValue(iocValue);
iocObject.addField(iocField);
}
fieldList.add(iocField.getName());
}
}
// 处理工厂方法
if (!Strings.isBlank(iocBean.factory())) {
iocObject.setFactory(iocBean.factory());
}
} else {
// 不再检查其他类.
}
}
use of org.nutz.ioc.meta.IocField in project nutz by nutzam.
the class XmlIocLoader method parseFields.
protected void parseFields(Element beanElement, IocObject iocObject) throws Throwable {
List<Element> list = getChildNodesByTagName(beanElement, TAG_FIELD);
for (Element fieldElement : list) {
IocField iocField = new IocField();
iocField.setName(fieldElement.getAttribute("name"));
if ("true".equals(fieldElement.getAttribute("optional")))
iocField.setOptional(true);
if (fieldElement.hasChildNodes()) {
NodeList nodeList = fieldElement.getChildNodes();
for (int j = 0; j < nodeList.getLength(); j++) {
if (nodeList.item(j) instanceof Element) {
iocField.setValue(parseX((Element) nodeList.item(j)));
break;
}
}
}
iocObject.addField(iocField);
}
}
Aggregations