/// <summary> /// <paramref name="type"/> 유형과 <paramref name="autowireAttribute"/>의 Autowire 특성을 분석하여 Spring Context에 등록하고, 객체를 생성하여 반환합니다. /// </summary> /// <param name="type"></param> /// <param name="autowireAttribute"></param> /// <param name="rootContextName"></param> /// <returns></returns> public static object Autowire(Type type, AutowireAttribute autowireAttribute, string rootContextName = DefaultRootContextName) { AbstractApplicationContext ctx = GetApplicationContext(rootContextName); if (autowireAttribute == null) { throw new NullReferenceException("AutowireAttribute missing"); } if (autowireAttribute.Type == null) { autowireAttribute.Type = type; } if (string.IsNullOrEmpty(autowireAttribute.ContextName)) { autowireAttribute.ContextName = $"[{type.GetShortAssemblyName()}]{$"Singleton={autowireAttribute.Singleton.ToString().ToLower()}".ToMD5String()}"; } var info = new AutowireTargetPropertyInfo(autowireAttribute, type); CreateObjectDefinition(ctx, info); return(ctx.GetObject(info.ObjectInfo.Id)); }
/// <summary> /// <paramref name="info"/> 정보를 분석하여 Spring Context에 등록합니다. /// </summary> /// <param name="ctx"></param> /// <param name="info"></param> private static void CreateObjectDefinition(AbstractApplicationContext ctx, AutowireTargetPropertyInfo info) { if (!ctx.IsObjectNameInUse(info.ObjectInfo.Id)) { lock (_lockMap.GetOrAdd(info.ObjectInfo.Id, new object())) { if (!ctx.IsObjectNameInUse(info.ObjectInfo.Id)) { IObjectDefinition objectDefinition = GetOrCreateObjectDefinition(ctx, info); // 병힙정의 찾기 IObjectDefinition mergeTargetObjectDefinition = null; if (!string.IsNullOrEmpty(info.ObjectInfo.PropertyDefinedAutowireAttribute.MergeBase) && ctx.IsObjectNameInUse(info.ObjectInfo.PropertyDefinedAutowireAttribute.MergeBase)) { mergeTargetObjectDefinition = ctx.GetObjectDefinition(info.ObjectInfo.PropertyDefinedAutowireAttribute.MergeBase); } // 병합정의가 있는경우 우선 처리 if (mergeTargetObjectDefinition != null) { foreach (PropertyValue propertyValue in mergeTargetObjectDefinition.PropertyValues) { if (info.ObjectInfo.ObjectType.GetProperty(propertyValue.Name) != null) { // 현재 정의에 없다면 등록한다. if (!objectDefinition.PropertyValues.Contains(propertyValue.Name)) { objectDefinition.PropertyValues.Add(mergeTargetObjectDefinition.PropertyValues.GetPropertyValue(propertyValue.Name)); } } } } // 현재 정의의 객체나 프로퍼티에 선언된 Property 특성으로 부터 확인된 속성정의를 우선 등록한다. foreach (var confirmedPropAttr in info.ObjectInfo.ConfirmedPropertyAttributes) { // 현재 정의에 이미 존재한다면, 제거하고 새로 등록한다. if (objectDefinition.PropertyValues.Contains(confirmedPropAttr.Name)) { objectDefinition.PropertyValues.Remove(objectDefinition.PropertyValues.GetPropertyValue(confirmedPropAttr.Name)); } objectDefinition.PropertyValues.Add(confirmedPropAttr.Name, new RuntimeObjectReference(confirmedPropAttr.Ref)); } // 현재 정의의 객체에 Autowire 특성을 가지고 있는 프로퍼티 foreach (AutowireTargetPropertyInfo inInfo in AutowireTargetPropertyGetter.GetAutowireTargetPropertiesInfo(info.ObjectInfo.ObjectType, info)) { // 이미 정의되어 있으나 이 것이 MergeBase에 의한 것이라면 지운다 if (objectDefinition.PropertyValues.Contains(inInfo.PropertyInfo.Name)) { if (mergeTargetObjectDefinition != null && mergeTargetObjectDefinition.PropertyValues.Contains(inInfo.PropertyInfo.Name)) { objectDefinition.PropertyValues.Remove(objectDefinition.PropertyValues.GetPropertyValue(inInfo.PropertyInfo.Name)); } } // 핸재 정의에 존재하지 않는다면 정의를 새로 생성한다. if (!objectDefinition.PropertyValues.Contains(inInfo.PropertyInfo.Name)) { CreateObjectDefinition(ctx, inInfo); objectDefinition.PropertyValues.Add(inInfo.PropertyInfo.Name, new RuntimeObjectReference(inInfo.ObjectInfo.Id)); } } } } } }
/// <summary> /// Spring ObjectDefinition을 가져오거나 생성합니다. /// </summary> /// <param name="ctx"></param> /// <param name="info"></param> /// <returns></returns> private static IObjectDefinition GetOrCreateObjectDefinition(AbstractApplicationContext ctx, AutowireTargetPropertyInfo info) { if (ctx.IsObjectNameInUse(info.ObjectInfo.Id)) { return(ctx.GetObjectDefinition(info.ObjectInfo.Id)); } else { AbstractObjectDefinition objectDefinition = fac.CreateObjectDefinition(info.ObjectInfo.Type, null, AppDomain.CurrentDomain); objectDefinition.IsSingleton = info.ObjectInfo.Singleton; ctx.ObjectFactory.RegisterObjectDefinition(info.ObjectInfo.Id, objectDefinition); return(ctx.GetObjectDefinition(info.ObjectInfo.Id)); } }
/// <summary> /// AutowireTargetPropertyInfo /// 속성으로 부터 정보를 가져올 때 사용합니다. /// </summary> /// <param name="prop">속성정보</param> /// <param name="parent">자신을 속성으로 포함하고 있는 부모의 정보</param> public AutowireTargetPropertyInfo(PropertyInfo prop, AutowireTargetPropertyInfo parent) { Parent = parent; PropertyInfo = prop; ObjectInfo = new ObjectInfo(Parent?.ObjectInfo, PropertyInfo); }