I want to be able to call Interfaces in my class, but have spring instantiate them with the right implementation class behind the scenes.
I.e. Normally you can do:
IClass clz = new Class();
I want to have the line IClass clz; preferable in the middle of a method (or as one of the attributes if it can't be done), where clz is instantiated to the class I want by Spring.
The reason I'd like to do it this way is because I want to be able to be able to change which implementation I want to use simply by editing the context files.
Even better, would be knowing how to do the above with class contructors that expect parameters. i.e. new Class(ar1, arg2);
I hope this makes sense. Any help would be much appreciated.
You can make your class implement BeanFactoryAware and then Spring will inject the bean factory in your class. If you then want to get an instance of a class implementing your interface you say something like:
beanFactory.getBean(IClass.class);
If there are multiple beans that implement the same interface you will have to resolve by name. To create a new object each time you ask this, set the bean scope of the bean you're asking for to "prototype".
You can include code such as:
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
IClass clz = (IClass) context.getBean("beanName");
Not saying this is better per se than Gerco's answer btw, just it's an option, depending what you want to do.
You can also implement the ApplicationContextAware interface: I've found that using ApplicationContext gives me beans with filled-in properties, e.g. if you have an app.properties file which contains key/value property pairs which you expect to be resolved within the Spring config, beans retrieved via BeanFactory calls may not resolve those.
See this previous SO topic for more info.
Related
I am not a native English speaker...there maybe some errors in expression, please forgive me..
//import org.springframework.context.ApplicationContext;
//in a #Component class
#Autowired
private static ApplicationContext context
I hope that the above code can work, the field variable context can get the applicationcontext of the springboot application.. but actually it doesn't work.
I have searched for some means to realize this aim, but I think them complex, for example ,implementing ApplicationContextAware...
Please think of factory pattern. Some of the instances which the factory class may return have field variable which need #Autowired, so they have to be managed by Spring, and the factory has to return applicationContext.getBean(...), can't use return new ... or return Class.forName(...)....
I think the factory pattern should be used widely, which I want use to prove that it is meaningful to get the the instance of ApplicationContext of a spring-boot application simply just like the top code...And why it's still complex now?
Thanks.
You can think of Spring as a factory that can create objects for you. These objects are called 'Beans' in spring world.
So, usually the beans do not have an access to the factory that has created them.
For example, think about the factory that produces "cars" like Toyota of Ford.
In terms of OOP, you can "buy" or "drive" the car (an instance of the class Car), but that factory creates these instance (does new Car). Since the actual car is managed by spring, its a bean. Now if you describe the car as a class in Java, its not reasonable to have something like this, right?
#Component
public class Car {
...
private CarFactory carFactory;
}
So Spring already "hides" the factory for you and you have a class Car "clean" of the boilerplate.
Now, as for the application context itself. It is actually that factory - and as our colleagues have already stated, you shouldn't really use the application context reference in your beans.
If you really need it, you can inject the application context but then it should not be static, and in general its better to access it from the #Configuration classes that are supposed to provide the way to create beans in more flexible ways.
I have query on bean instantiation in spring.
According to the Spring Reference document, in the section 'Instantiating beans", it is mentioned that
" container itself directly creates the bean by calling its constructor reflectively, somewhat equivalent to Java code using the new operator " .
This implies that Spring container uses reflection to create beans.How ever in few scenarios, container also uses static factory method on a class to create a bean. The only case I knew container use static factory method is "WHEN THE CONSTRUCTOR IS PRIVATE".
So my doubt is, since container uses Reflection to create objects, it should be able create objects of classes of even private constructor as well.Why should container rely on static factory method ?
Or are there any other uses of calling static factory method to create beans ?
Thanks in advance. If there is any fundamental understanding required for me, kindly suggest so.
Yes you are right Spring can invoke private constructor if you provide right arguments while defining the bean in configuration. But on question that comes to my mind is why would you do that if that bean is not meant to be instantiated?
It would be the case only say when you have helper class with static method or singleton etc. So it wont make sense to instantiate those classes.
But in your case, it's factory and you might be getting the object back by calling static method (accessing Static method/field doesn't necessarily need Object to access field/method) say getShape and you might be getting different shape based on parameter's that you might supply.
We sometimes need to use a class which was not designed for Spring and need to be instantiated via static factory method and Spring provides us with such possibility.
I am having some problems understanding the concept of component instantiation in iPOJO. I read this guide
and I get the analogy to classes and objects but I still have some concrete problems and some conceptual problems that I hope someone can clarify
I thought I needed to create instances via iPOJO (#Instantiate or factories) only for service providers since they never use new because the impl is always hidden. However, I have some consumers #Component that I instantiate myself (say in a main() method where I call new on them directly). I made them #Component because they need to have things injected. I was assuming that the ipojo bytecode manipulation would make it so that when the objects were constructed, they would have their dependencies injected (I'm using mostly method injection with #Bind) but it seems that is not the case. Can someone clarify this to me please. Now it seems to me that for iPOJO to do any injection at all I need to always use one of the iPOJO instantiation techniques. The problem I have is that then the constructors I made in the consumer classes are not called.
This is a simplified example to illustrate my confusion
#Component(name="test")
public class MyFoo {
private List<External> externals; //injected
private Bar bar; //passed via constructor. Bar is *not* a #Component
public MyFoo(Bar otherBar) {
bar = otherBar;
externals = new ArrayList();
}
#Bind(aggregate=true)
public addExternal(External service) {
externals.add(service);
}
}
So, as can be seen here, I need to have all the providers of interface External, but I also need a Bar object that I pass when I construct the object using new MyFoo(someBar)
My problem is that if I need to pass a Bar to the constructor then I need to use new; but If i use new, iPojo never invokes my injection method. On the other hand, if I use iPOJOs instantiation (say I add #Instantiate) then the injection does happen but the constructor is not invoked, so the bind throws a NPE because the list has not been created yet + bar will not be set. I know I can create the list inside the bind method, but my question is more conceptual.
How are you supposed to accomplish this (framework injection + argument passing in the constructor)?
How can iPOJO be calling addExternal (which means the object has been created) without calling my one and only constructor that creates the object? this is very counter-intuitive in standard java
Are you just not supposed to use constructors when using iPOJO components maybe?
iPojo works similar to other DI (dependency injection) frameworks such as Blueprint (OSGi), Spring, Guice, etc. That is, in order to allow DI to do it's job you have to let the container (iPojo) manage the lifecycle of the object you're interacting with. So, your inclination was correct: You have to use one of iPojo's instantiation techniques. If you choose to use new on your object, your code is then managing the lifecycle (and thus you will manually need to "inject" all parameters).
In the example, your constructor isn't invoked because out of the box iPojo will support two main cases: The default constructor (MyFoo()) or the constructor accepting a BundleContext (MyFoo(BundleContext c)). iPojo also supports constructor service and property injection if you're on version 1.7.0 or later using #Requires / #Property respectively on your constructor variable (or the equivalent in your metadata).
When iPojo bytecode manipulation kicks in, it manipulates the bytecode to make it manageable by iPojo, not managed by iPojo. It does this by adding a MyClass(InstanceManager) constructor among other things that is used internally by iPojo when instantiating your object.
So, to answer your questions:
You can accomplish this by defining injected variables as either properties or service requirements and delegating to iPojo to create them. iPojo has multiple methods for interacting with instance creation, but the two you may be interested in are via the OSGi ConfigurationAdmin or the iPojo factory (assuming publicFactory is set to true on your #Component, which is the default). As an example using the config admin and assuming Bar doesn't live in the OSGi service registry your MyFoo class would look like this:
#Component(name="test")
public class MyFoo {
private List<External> externals; //injected
private Bar bar; //passed via constructor. Bar is *not* a #Component
public MyFoo(#Property(name = "somebar") Bar otherBar) {
bar = otherBar;
externals = new ArrayList();
}
#Bind(aggregate=true)
public addExternal(External service) {
externals.add(service);
}
}
Then, you would use the configuration admin (or iPojo factory) to create an instance. So, your main method would pull in the ConfigAdmin or the iPojo factory from the OSGi service layer (e.g. by pulling it out from the BundleContext, etc.), create a configuration with the "somebar" property set to your "new Bar()" and save that configuration. The iPojo managed service factory that is created for you will then instantiate a version of MyFoo with the new Bar you supplied in the configuration, injecting it into the MyFoo constructor:
...
Configuration config = configAdmin.createFactoryConfiguration(
MyFoo.class.getCanonicalName());
Hashtable<String, String> properties = new Hashtable<>();
properties.put("somebar", new Bar()); // This is where you new
config.update(properties);
// do something useful with the config if you need to update
// the instance or destroy it later.
...
The first parameter to the config admin's createFactoryConfiguration specifies the pid. In this case the pid is the name of the class, which is what iPojo will use by default unless you override it in your #Component annotation. Then you add your somebar to the properties and update the configuration. The iPojo factory is similar to this, though I believe it uses the builder pattern to create instances. It may be preferable to use the iPojo factory instead if you don't want to add a dependency on the OSGi config admin.
I'm no expert on iPojo internals, and I'm drawing a conclusion here based on what I've experienced and what I read in their documentation. As mentioned, iPojo does bytecode manipulation to augment your class to make it manageable by iPojo. One trait it adds to your class is a constructor with an InstanceManager. Since the constructor you've added has no metadata bound to it (i.e., annotations -- i'm assuming there is no manual metadata in a manifest or xml file) it more or less completely ignores that constructor and instead chooses to use the one dynamically generated by the bytecode manipulation process. Once it's done, it will eventually call your #Bind method to add the external service (since that method is marked up) and you will find yourself in the state you described.
The key here is to let iPojo manage the lifecycle of your object, as explained above. By calling a constructor you're in effect managing the lifecycle of that instance, so iPojo is out of the loop. So, you can either use constructors and manually "inject" parameters into it or rely on iPojo to do that for you.
This question is a continuation of Using guice for a framework with injected classes, proper way to initialize?, which I've tried to implement, and also tried other ways to get around the issue, but nothing has worked so far.
The main issue is this. I have an InterfaceA and InterfaceB that are exposed in different parts of the API. There are two classes that implement both of these interfaces, TestClass and RealClass, so that depending on whether I'm testing or doing something else, I can do the following:
bind(InterfaceA.class).to(TestClass.class);
bind(InterfaceB.class).to(TestClass.class);
or, for production:
bind(InterfaceA.class).to(RealClass.class);
bind(InterfaceB.class).to(RealClass.class);
I have two requirements for using these classes:
I need the same instance of TestClass or RealClass to be bound to all injections of InterfaceA and InterfaceB; so, like a singleton pattern, except that:
The singleton is only for a specific scope or child injector, many of which are created during the execution of the program.
The default no-scope approach causes multiple instances of RealClass/TestClass to be created for each interface injection. I don't want that, so I've tried implementing this with scopes, child injectors, and other methods. Nothing has worked:
Child injector approach: I create a new injector and try to bind the TestClass or RealClass to a singleton instance in that injector. The problem is, whether TestClass or RealClass is being used is configured in the parent injector, and since it's a singleton, it's already instantiated (unless in Stage.DEVELOPMENT). There's no way to bind InterfaceA to TestClass, in the parent injector, for example, and then re-bind it as a singleton in the child injector.
Scope approach: I create a custom scope and annotate TestClass and RealClass. Then, I enter and exit this scope to get single instances in that scope. The problem is that my code is multithreaded and having the scope change from one thread affects what the global injector can see and mucks up creating other instances.
Combined child injector and scope approach. I tried creating a child injector for each use of this custom scope, but then binding RealClass in the parent fails with
No scope is bound to name.package.WhateverScope.
because it seems to insist that the WhateverScope is available all the time, not just in the child injector.
All these problems seem to be due to the fact that I need to be able to configure whether to use TestClass or RealClass in the parent, but then to be able to instantiate them later, as a singleton, for a specific group of objects. I'm pulling my hair out over how to get this done!
By the way, the documentation for Guice scopes is horrible and almost impossible to understand. This article is the only one that has gotten me anywhere:
Apologies for a somewhat-breakthrough less than an hour after posting.
I seem to have been able to fix this by somewhat abusing the thread-local scope implementation provided at http://code.google.com/p/google-guice/wiki/CustomScopes. It seems to be a somewhat clean way to solve this problem without using child injectors. I'm not sure if it's 'proper', though. I'll still accept other answers.
Here's what I did. First, I create one instance of the scope, bind it to the appropriate annotation, and make it available in the injector:
ThreadLocalScope scope = new ThreadLocalScope();
bindScope(ExperimentScoped.class, scope);
bind(ThreadLocalScope.class).toInstance(scope);
Then, as the documentation says, I need to bind a fake provider for every type of key that would be seeded in the scope:
bind(SomeKey.class)
.toProvider(ThreadLocalScope.<SomeKey>seededKeyProvider())
.in(ExperimentScoped.class);
bind(SomeOtherKey.class)
.toProvider(ThreadLocalScope.<SomeOtherKey>seededKeyProvider())
.in(ExperimentScoped.class);
I may also have some other scope-able objects that I want to be distinct within each scope, so I bind those too. These are the TestClass and RealClass above. There may be also SomeScopedClass that was annotated with the #ExperimentScoped:
bind(InterfaceA.class).to(TestClass.class).in(ExperimentScoped.class);
bind(InterfaceB.class).to(TestClass.class).in(ExperimentScoped.class);
bind(SomeInterface.class).to(SomeScopedClass.class);
Finally, I can use the scope to create distinct sets of interdependent objects, in parallel from different threads. Each thread can do something like the following, even though they are using the same injector:
ThreadLocalScope scope = injector.getInstance(ThreadLocalScope.class);
scope.enter();
try {
// Seed the seed-able keys
scope.seed(SomeKey.class, keyInstance);
scope.seed(SomeOtherKey.class, otherKeyInstance);
SomeScopedClass instance = injector.getInstance(SomeScopedClass.class);
// Hooray! instance was injected with the seeds and created just for this scope!
}
finally {
scope.exit(); // Throws away the scope and referenced objects.
}
In my case, I can discard the scope completely because I don't care about keeping track of the set of objects in the scope once they're wired up properly. But it probably wouldn't work if I wanted to come back to this scope later and inject some more objects.
Hope this helped someone. The Guice scoping documentation is terrible!
I have a question regarding Spring inheritance:
Let's say I have a class (bean) BraveKnight that implements the interface Knight. After I declare this bean in the xml file with the id->knight, I'm trying to get a reference of the bean:
Knight knight = (Knight) context.getBean("knight");
This is the way it works. But why isn't possible to get the bean reference from the bean's name itself: BraveKnight (and why doesn't work with no interface at all)?
BraveKnight knight = (BraveKnight) context.getBean("knight");
First of all please use:
public <T> T getBean(String name, Class<T> requiredType)
instead of:
public Object getBean(String name)
You will avoid this nasty class cast.
Secondly your question about why it is not working with no interface is a little bit unobvious. I guess you have some kind of problem getting BraveKnight when it is not implementing any interface at all. If you want do that you have to force Spring to use CGLIB instead of dynamic proxy mechanism. If you have a problem with ClassCastException though when casting your bean to BraveKnight it means that Spring used dynamic proxy and implemented a $Proxy0 class which is only implementing Knigh interface and does not extend BraveKnigh directly. Whatever your problem is please try to get to know CGLIB and JDK dynamic proxy mechanism better so that you will not be surprised next time what Spring will do in the future with your objects.
If that answer does not correspond to your problem please try to attach some more info, stack trace or explanation.
You are getting the bean using its name: "knight". You're using the Spring bean name as the key.
If your question is "Why can't I look up the bean using its type", the answer is that you can as long as there's only one bean of that type. It's called "autowiring". Spring can do it for you if you add annotations and a couple of required XML tags.
As for why it won't work with no interface, who said it didn't? You can wire concrete class types with Spring.
A better question would be "When and why should I prefer to use interfaces in Spring?" The answer is that designing to an interface for those cases where implementation is likely to change is a good practice whether you use Spring or not. It makes it possible for Spring to generate dynamic proxies as needed (e.g. adding transactions to persistence objects).
You can call been without interface from application context without any problem.
You will need interface only when you use AOP Proxy, in that case any object reference called not by interface will cause exception.
You can use BraveKnight as the bean name if that makes it simple and easier for you to understand your mappings. Craig Walls Spring In Action used Knight as the bean name to make it clear your mapping is calling an implementation of Knight.
Again it would not work with an interface because in java you cannot instantiate an interface.
Mapping directly to Knight is exactly as doing;
Knight knight = new Knight(); // This is illegal
You will instantiate against the implementation of Knight to make it work, example:
Knight knight = new BraveKnight()//legal Implementation to Knight
This is the reason why the implementation was used as the mapping in the context file.