How to initialize a Spring.net GenericApplicationContext after adding Object Definitions

1k views Asked by At

Given a GenericApplicationContext and adding some ObjectDefinitions programatically. What do I need to do (others than calling Refresh()) to proper initialize the context?

The Problem is, that even with IsLazyInit set to false the GetObject('beanId') seems to bee extremly slow compared to XmlApplicationContext filled with the same ObjectDefinitions via XML Files.

Following code is from the constructor of my custom application context extending a GenericApplicationContext. Already tried the ObjectDefinitionBuilder without successfully solving the problem of GetObject() is very slow.

IObjectDefinitionFactory objectDefinitionFactory =  new DefaultObjectDefinitionFactory();
foreach (Tuple<Type, ComponentAttribute> type in typesWithComponentTypeAttribute) {
    //ObjectDefinitionBuilder builder = ObjectDefinitionBuilder.RootObjectDefinition(objectDefinitionFactory, type.Item1);
    //builder.SetAutowireMode(type.Item2.AutoWiringMode);
    //builder.SetSingleton(type.Item2.IsSingleton);
    //builder.SetLazyInit(false);
    //builder.SetDependencyCheck(DependencyCheckingMode.All);
    MutablePropertyValues mutableProperties = new MutablePropertyValues();
    IList<PropertyInfo> properties = type.Item1.GetProperties();
    foreach (PropertyInfo propertyInfo in properties) {
        IList<InjectTypeAttribute> injectByType = propertyInfo.GetCustomAttributes(typeof(InjectTypeAttribute), true).Cast<InjectTypeAttribute>().ToList();
        if (injectByType.Any()) {
            //builder.AddPropertyReference(propertyInfo.Name, typeToInjectFullName);
            //builder.AddDependsOn(typeToInjectFullName);
            string typeToInjectFullName = injectByType.First().TypeToInject.FullName;
            mutableProperties.Add(propertyInfo.Name, new RuntimeObjectReference(typeToInjectFullName));
        }
        IList<InjectNameAttribute> injectByName = propertyInfo.GetCustomAttributes(typeof(InjectNameAttribute), true).Cast<InjectNameAttribute>().ToList();
        if (injectByName.Any()) {
            //string nameToInject = injectByName.First().Name;
            //builder.AddPropertyReference(propertyInfo.Name, nameToInject);
            //builder.AddDependsOn(nameToInject);
        }
    }

    AbstractObjectDefinition objDef = objectDefinitionFactory.CreateObjectDefinition(type.Item1.FullName,null, AppDomain.CurrentDomain);
    objDef.AutowireMode = type.Item2.AutoWiringMode;
    objDef.IsLazyInit = false;
    objDef.IsSingleton = type.Item2.IsSingleton;
    objDef.PropertyValues = mutableProperties;

    //ObjectFactory.RegisterObjectDefinition(type.Item1.FullName, builder.ObjectDefinition);
    ObjectFactory.RegisterObjectDefinition(type.Item1.FullName, objDef);
}

Refresh();

Given an object structure for a view model with about 10 sub view models with about 2 services each (each with a DAO) takes about 12 seconds until completion. Compared to 3 seconds it takes to complete with a standart XmlApplicationContext. When hitting pause (in Visual Studio) during the 12 seconds of loading it always hangs at getting the object from the context.

IApplicationContext context = ContextRegistry.GetContext();
T vm = (T)context.GetObject(typeof(T).FullName, arguments);
return vm;

Update 1 - Logfiles

Logged the beginning of the creation of the mentioned view model. 1.) using the XML Context:

DEBUG2015-06-26 10:27:56 – Returning context 'Spring.Context.Support.XmlApplicationContext' registered under name 'spring.root'.

DEBUG2015-06-26 10:27:56 –    GetObjectInternal: obtaining instance for name ProjectEditViewModel => canonical name ProjectEditViewModel

DEBUG2015-06-26 10:27:56 – Creating instance of Object 'ProjectEditViewModel' with merged definition [RootObjectDefinition : Class [Com.QueoFlow.TrackingtoolLogistik.Wpf.Ui.Windows.Project.ViewModels.ProjectEditViewModel]; Abstract = False; Parent = ; Scope = prototype; Singleton = False; LazyInit = False; Autowire = No; DependencyCheck = None; InitMethodName = ; DestroyMethodName = ; FactoryMethodName = ; FactoryObjectName = ; defined in = file [C:\Develop\vw_logiPIT\develop_mysql\TrackingtoolLogistik.Wpf\bin\Release\Config\Spring.ViewModels.xml] line 525].

DEBUG2015-06-26 10:27:56 – Invoking IInstantiationAwareObjectPostProcessors before the instantiation of 'ProjectEditViewModel'.

DEBUG2015-06-26 10:27:56 – Configuring object using definition 'ProjectEditViewModel'

DEBUG2015-06-26 10:27:56 – Resolving reference from property 'ActivityPlanTabControlViewModel' in object 'ProjectEditViewModel' to object 'ActivityPlanTabControlViewModel'.

DEBUG2015-06-26 10:27:56 –       GetObjectInternal: obtaining instance for name ActivityPlanTabControlViewModel => canonical name ActivityPlanTabControlViewModel

DEBUG2015-06-26 10:27:56 – Creating instance of Object 'ActivityPlanTabControlViewModel' with merged definition [RootObjectDefinition : Class [Com.QueoFlow.TrackingtoolLogistik.Wpf.Ui.UserControls.ActivityPlanTab.ViewModels.ActivityPlanTabControlViewModel]; Abstract = False; Parent = ; Scope = prototype; Singleton = False; LazyInit = False; Autowire = No; DependencyCheck = None; InitMethodName = ; DestroyMethodName = ; FactoryMethodName = ; FactoryObjectName = ; defined in = file [C:\Develop\vw_logiPIT\develop_mysql\TrackingtoolLogistik.Wpf\bin\Release\Config\Spring.ViewModels.xml] line 967].

DEBUG2015-06-26 10:27:56 – Invoking IInstantiationAwareObjectPostProcessors before the instantiation of 'ActivityPlanTabControlViewModel'.

DEBUG2015-06-26 10:27:56 – Configuring object using definition 'ActivityPlanTabControlViewModel'

DEBUG2015-06-26 10:27:56 – Resolving reference from property 'ActivityPlanService' in object 'ActivityPlanTabControlViewModel' to object 'activityPlanService'.

DEBUG2015-06-26 10:27:56 –          GetObjectInternal: obtaining instance for name activityPlanService => canonical name activityPlanService

DEBUG2015-06-26 10:27:56 – Returning cached instance of singleton object 'activityPlanService'.

DEBUG2015-06-26 10:27:56 – Calling code asked for normal instance for name 'activityPlanService'.

DEBUG2015-06-26 10:27:56 –       GetObjectInternal: returning instance for objectname activityPlanService

2.) using the programatically added object definitions

DEBUG2015-06-26 10:20:24 – Returning context 'Com.QueoFlow.Spring.Attributes.MixedApplicationContext' registered under name 'spring.root'.

DEBUG2015-06-26 10:20:24 –    GetObjectInternal: obtaining instance for name Com.QueoFlow.TrackingtoolLogistik.Wpf.Ui.Windows.Project.ViewModels.ProjectEditViewModel => canonical name Com.QueoFlow.TrackingtoolLogistik.Wpf.Ui.Windows.Project.ViewModels.ProjectEditViewModel

DEBUG2015-06-26 10:20:24 – Creating instance of Object 'Com.QueoFlow.TrackingtoolLogistik.Wpf.Ui.Windows.Project.ViewModels.ProjectEditViewModel' with merged definition [RootObjectDefinition : Class [Com.QueoFlow.TrackingtoolLogistik.Wpf.Ui.Windows.Project.ViewModels.ProjectEditViewModel]; Abstract = False; Parent = ; Scope = prototype; Singleton = False; LazyInit = False; Autowire = No; DependencyCheck = None; InitMethodName = ; DestroyMethodName = ; FactoryMethodName = ; FactoryObjectName = ].

DEBUG2015-06-26 10:20:24 – Invoking IInstantiationAwareObjectPostProcessors before the instantiation of 'Com.QueoFlow.TrackingtoolLogistik.Wpf.Ui.Windows.Project.ViewModels.ProjectEditViewModel'.

DEBUG2015-06-26 10:20:24 – Configuring object using definition 'Com.QueoFlow.TrackingtoolLogistik.Wpf.Ui.Windows.Project.ViewModels.ProjectEditViewModel'

DEBUG2015-06-26 10:20:24 – Resolving reference from property 'ActivityPlanTabControlViewModel' in object 'Com.QueoFlow.TrackingtoolLogistik.Wpf.Ui.Windows.Project.ViewModels.ProjectEditViewModel' to object 'Com.QueoFlow.TrackingtoolLogistik.Wpf.Ui.UserControls.ActivityPlanTab.ViewModels.ActivityPlanTabControlViewModel'.

DEBUG2015-06-26 10:20:24 –       GetObjectInternal: obtaining instance for name Com.QueoFlow.TrackingtoolLogistik.Wpf.Ui.UserControls.ActivityPlanTab.ViewModels.ActivityPlanTabControlViewModel => canonical name Com.QueoFlow.TrackingtoolLogistik.Wpf.Ui.UserControls.ActivityPlanTab.ViewModels.ActivityPlanTabControlViewModel

DEBUG2015-06-26 10:20:24 – Creating instance of Object 'Com.QueoFlow.TrackingtoolLogistik.Wpf.Ui.UserControls.ActivityPlanTab.ViewModels.ActivityPlanTabControlViewModel' with merged definition [RootObjectDefinition : Class [Com.QueoFlow.TrackingtoolLogistik.Wpf.Ui.UserControls.ActivityPlanTab.ViewModels.ActivityPlanTabControlViewModel]; Abstract = False; Parent = ; Scope = prototype; Singleton = False; LazyInit = False; Autowire = No; DependencyCheck = None; InitMethodName = ; DestroyMethodName = ; FactoryMethodName = ; FactoryObjectName = ; defined in = file [C:\Develop\vw_logiPIT\branches_mysql\spring_attribute\TrackingtoolLogistik.Wpf\bin\Release\Config\Spring.ViewModels.xml] line 911].

DEBUG2015-06-26 10:20:24 – Invoking IInstantiationAwareObjectPostProcessors before the instantiation of 'Com.QueoFlow.TrackingtoolLogistik.Wpf.Ui.UserControls.ActivityPlanTab.ViewModels.ActivityPlanTabControlViewModel'.

DEBUG2015-06-26 10:20:24 – Configuring object using definition 'Com.QueoFlow.TrackingtoolLogistik.Wpf.Ui.UserControls.ActivityPlanTab.ViewModels.ActivityPlanTabControlViewModel'

DEBUG2015-06-26 10:20:24 – Resolving reference from property 'ActivityPlanService' in object 'Com.QueoFlow.TrackingtoolLogistik.Wpf.Ui.UserControls.ActivityPlanTab.ViewModels.ActivityPlanTabControlViewModel' to object 'Com.QueoFlow.TrackingtoolLogistik.Services.Impl.ActivityPlanService'.

DEBUG2015-06-26 10:20:24 –          GetObjectInternal: obtaining instance for name Com.QueoFlow.TrackingtoolLogistik.Services.Impl.ActivityPlanService => canonical name Com.QueoFlow.TrackingtoolLogistik.Services.Impl.ActivityPlanService

DEBUG2015-06-26 10:20:24 – Creating instance of Object 'Com.QueoFlow.TrackingtoolLogistik.Services.Impl.ActivityPlanService' with merged definition [RootObjectDefinition : Class [Com.QueoFlow.TrackingtoolLogistik.Services.Impl.ActivityPlanService]; Abstract = False; Parent = ; Scope = prototype; Singleton = False; LazyInit = False; Autowire = No; DependencyCheck = None; InitMethodName = ; DestroyMethodName = ; FactoryMethodName = ; FactoryObjectName = ].

DEBUG2015-06-26 10:20:24 – Invoking IInstantiationAwareObjectPostProcessors before the instantiation of 'Com.QueoFlow.TrackingtoolLogistik.Services.Impl.ActivityPlanService'.

DEBUG2015-06-26 10:20:24 – Configuring object using definition 'Com.QueoFlow.TrackingtoolLogistik.Services.Impl.ActivityPlanService'

DEBUG2015-06-26 10:20:24 – Resolving reference from property 'ActivityPlanDao' in object 'Com.QueoFlow.TrackingtoolLogistik.Services.Impl.ActivityPlanService' to object 'Com.QueoFlow.TrackingtoolLogistik.Persistence.Impl.ActivityPlanDao'.

DEBUG2015-06-26 10:20:24 –             GetObjectInternal: obtaining instance for name Com.QueoFlow.TrackingtoolLogistik.Persistence.Impl.ActivityPlanDao => canonical name Com.QueoFlow.TrackingtoolLogistik.Persistence.Impl.ActivityPlanDao

The XMl Context simply returns the requested object whereas the generic context creates new instances down to the session factory.

2

There are 2 answers

0
Najera On

Not sure what is your problem, but if you don't want to wait when the context is initializing when you request an object you can call:

var context = (AbstractApplicationContext)ContextRegistry.GetContext();
context.Start();
0
pso On

Initializing the Application Context should be done when your program first runs. Code will look like this:

private IApplicationContext context;

public void InitContext()
{
   // Configure Spring programmatically
   var ctx = new CodeConfigApplicationContext();
   ctx.ScanWithAssemblyFilter(a => a.FullName.StartsWith("My.Assemble.Name.Path"));
   ctx.Refresh();
   context = ctx;
}

After you have the Application context, you can ask for your objects like this:

IShapeDao circleDao = context.GetObject<IShapeDao>("circle");

IShapeDao rectangleDao = context.GetObject<IShapeDao>("rectangle");

Please go through this article if you need more help.

http://sovitpoudel.com.np/2017/03/11/notes-on-spring-net-dao-code-configuration/

Thanks.