When you configure an IoC component you can also specify its scope. If you do not specify any scope, no scope (Scope.NONE
) is assumed. Below we describe the available scopes provided by MentaContainer and what they mean:
SingletonFactory
for example. So to make it clear, the scope NONE always ask the factory for an instance and never caches any instance.
ThreadLocal
. The result is that each thread will receive its own cached instance from the ThreadLocal
until the THREAD scope or the key is cleared.
Below are some examples of using scopes:
Container c = new MentaContainer(); // if you don't provide a scope the Scope is NONE // meaning a new instance is created on every // request for the factory c.ioc("myString", String.class).addInitValue("saoj"); // Scope.NONE String s1 = c.get("myString"); String s2 = c.get("myString"); Assert.assertTrue(s1 != s2); // different instances // then you can use SINGLETON // always get the same instance no matter what c.ioc("myString", String.class, Scope.SINGLETON).addInitValue("saoj"); // Scope.SINGLETON s1 = c.get("myString"); s2 = c.get("myString"); Assert.assertTrue(s1 == s2); // same singleton instance // then you can use THREAD // each thread will get a different instance c.ioc("myString", String.class, Scope.THREAD).addInitValue("saoj"); // Scope.THREAD s1 = c.get("myString"); s2 = c.get("myString"); Assert.assertTrue(s1 == s2); // same thread so same instances
If you have an instance in the THREAD or SINGLETON scope you can clear its cache with the clear(Object key)
method. Se some examples below:
c.ioc("myString", String.class, Scope.SINGLETON).addInitValue("saoj"); // Scope.SINGLETON String s1 = c.get("myString"); String s2 = c.get("myString"); Assert.assertTrue(s1 == s2); // same singleton instance // now I want to clear the cache in the SINGLETON scope: c.clear("myString"); String s3 = c.get("myString"); Assert.assertTrue(s1 != s3); // different instances
Same thing for the THREAD scope which will be useful when you have a thread pool for example. With a thread pool you will have the same thread handling two different tasks in two different moments. That's because when the first task was completed the thread was not killed but instead it was returned to the pool. Later the same thread will be used to handle a new request but of course you do not want the same instances that were cached when the first task was executed. So you can issue use the clear
method when your thread is returned to your thread pool:
c.ioc("myString", String.class, Scope.THREAD).addInitValue("saoj"); // Scope.THREAD String s1 = c.get("myString"); String s2 = c.get("myString"); Assert.assertTrue(s1 == s2); // same thread so same instance // now I want to clear the cache in the THREAD scope: c.clear("myString"); String s3 = c.get("myString"); Assert.assertTrue(s1 != s3); // same thread but now different instances after a clear
NOTE1: The clear(Object key)
method returns the instance that was just cleared or null if no instance was found to be cleared.
NOTE2: Trying to clear something in the Scope.NONE
does nothing because as you know there is no cache for the NONE scope.
If you don't know the keys but still want to clear the instances for that scope, you can use the clear(Scope scope)
method. Below are the details of how this method works for each scope:
ThreadLocal
cache. That only affects the thread calling clear(Scope.THREAD)
because only the values from his ThreadLocal
will be cleared. The values for the other threads will be unaffected. It just calls remove()
on all its ThreadLocal
s.Below are some examples:
c.ioc("myString1", String.class, Scope.THREAD).addInitValue("saoj1"); c.ioc("myString2", String.class, Scope.THREAD).addInitValue("saoj2"); c.ioc("myString3", String.class, Scope.THREAD).addInitValue("saoj3"); String s1 = c.get("myString1"); String s2 = c.get("myString2"); String s3 = c.get("myString3"); // now clear everything but just for the current thread and not for all threads: c.clear(Scope.THREAD); s11 = c.get("myString1"); s22 = c.get("myString2"); s33 = c.get("myString3"); Assert.assertTrue(s1 != s11); Assert.assertTrue(s2 != s22); Assert.assertTrue(s3 != s33);
NOTE1: Just keep in mind that when a thread calls clear(Scope.THREAD)
the values for the other threads are unaffected, in other words, the THREAD scope isolates the thread instances through a ThreadLocal
. It is easy to think that clear(Scope.THREAD)
clears all values for all threads which is NOT the case.
NOTE:2 The THREAD scope can be used to implement a REQUEST scope inside a web container since each web request will be handled by its own thread. Just remember to clear the THREAD scope after the request is done because most web containers use a thread pool.