Is there a way to auto-cast Spring beans to the class defined in the application context XML? I'd like to avoid putting type information about the beans in 2 places.... in the xml configuration file and also in the code as a cast.
For instance, given this config file
<bean id="bean-name" class="SimpleSpringBean" scope="prototype">
<property name="myValue" value="simple value"></property>
</bean>
Can I call ApplicationContext.getBean("bean-name") in such a way as to avoid directly casting the return type to SimpleStringBean. I know I can also call ApplicationContext.getBean("bean-name", SimpleSpringBean.class) to avoid the cast itself, but I still have the type info in 2 places.
It seems that Spring can get the class info (ApplicationContext.getType) or by getting the type from the bean itself, but no way to automatically cast the type without programmer intervention.
I agree with Sii, you should avoid calling getBean as much as you can. Just wire your beans to classes that depends on them.
Still, if you have a single class that holds the application context, you can provide a wrapper generic method like the following:
class MyContextHolder{
ApplicationContext appContext;
......
#SuppressWarnings("unchecked")
public static <T> T getBean(String beanName)
{
return (T)appContext.getBean(beanName);
}
}
Then you can call it without casting
MyClass mc = MyContextHolder.getBean("myClassBean");
The answer is you shouldn't be using ApplicationContext.getBean() at all if it's possible, and bear with the one place you have to in the bootstrap code. (Generally, you should never need to use getBean() outside of your application's entry points.)
Also, what you're asking is likely impossible in the Java language at all. Casting is a compile-time feature, combined with a runtime check. The return type of getBean() simply must be known at compile time. Even if Spring can determine the type of an object, it can't change its own method signatures at runtime.
Another thing is that even if this were possible, the feature wouldn't be all that useful. Because Spring AOP is implemented using dynamic proxies, you nearly always want Spring to hand you an instance of an interface the bean implements (which could be an AOP proxy), not of the implementation class.
Another approach I also use is autowiring the bootstrapping class using:
public class Main {
#Autowired FooFacade foo;
#Autowired BarFacade bar;
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("appCtx.xml");
AutowireCapableBeanFactory bf = ctx.getAutowireCapableBeanFactory();
Object main = bf.createBean(Main.class,
AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT,
false);
((Main) main).run();
}
private void run() {
foo.doBootstrapStuff();
bar.doMoreBootstrapStuff();
}
}
(Code done from memory. Might only work if you have the Spring context configured to process wiring annotations, in that case making setters for foo and bar should work.)
The main reason for getBean being untyped is the compatibility of Spring (up to version 2.5.x) with Java 1.4. Spring 3.0 will drop that and thus offer typed getBean method then.
Nevertheless you should avoid looking up beans directly and minimize its usage as far as possible.
What if I use Spring as an object factory that my application uses extensively.
That is, instead of writing a bunch of classes that already inherit or wrap around
known Java classes I just decide to move all that into an xml file to cut down on
lines of Java code. This will mean many lines of xml but I won't need to make
skeleton Java classes which I inject with Spring or autowire. Thus making the lines
of Java code less.
For this reason and still as I am new to Spring I have just as stated in previous
posts used static Java methods which wrap around the getBeans().
I have worked with Spring but it is still new to me so forgive my question.
"Because Spring AOP is implemented using dynamic proxies, you nearly always want Spring to hand you an instance of an interface the bean implements (which could be an AOP proxy), not of the implementation class"
So there is no way to get a dynamic proxy using getBean(), then whats the best practice if there are no interfaces and its a stand alone driver class to be executed?
Related
This seems like it should be trivial, but both Google and StackOverflow seem to be just as uncooperative as Spring docs (or I just don't know where to look).
My Spring Boot application needs to manually instantiate certain classes. Some of the classes have dependencies, so I can't use .newInstance(); instead, I figure I need to ask Spring to give me the instance from its DI container. Something like
Class<? extends Interface> className = service.getClassName();
Interface x = SpringDI.getInstance(className);
But I can't seem to find any way of doing this. What should I do?
EDIT
Class names are resolved dynamically, I have updated my sample pseuido-code to reflect that.
How about autowiring the ApplicationContext in the component in which you want to instantiate those classes? As ApplicationContext implements the BeanFactory interface, you can call the getBean() method.
Something like:
#Autowired
private ApplicationContext applicationContext;
[...]
applicationContext.getAutowireCapableBeanFactory().getBean(clazz_name);
I am not sure why you would want to do this, tho, as it defies the purpose of using Spring. (you can just not use Spring but use Java's reflection API)
Please refer to this part of the JavaDocs: http://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/beans/factory/BeanFactory.html
In my ApplicationContext I have several Beans being created the same style. So I have a lot of dublicated code writing a FactoryBean for each of this beans. Those beans have a common ground, implementing all one special interface.
I would like to move all that bean creation to one factory. That one would have to provide a methode like this
<T extends CommonInterface> T createInstance(Class<T> clazz);
There I could implement all the instantiation necessary to create one of my special beans.
My implementation would be called by spring for
#Autowired
private MyCommonInterfaceImplementation impl;
in that way
createInstance(MyCommonInterfaceImplementation.class)
So far I looked at BeanFactory and FactoryBean, both seem not to be I'm searching for.
Any suggestions?
why not use #bean
#Bean
public MyCommonInterfaceImplementation getMyCommonInterfaceImplementation(){
return MyBeanFactory.createInstance(MyCommonInterfaceImplementation.class);
}
//should autowire here
#Autowired
private MyCommonInterfaceImplementation impl;
Basically you need the #Bean annotation on a "factory" only if you need some special handling during the creation of a bean.
If everything can be #Autowired, either by setters, fields, or one constructor, and nothing else needs to be done on a bean during initialization, you can simply declare the annotation #Component on each implementation of your interface. This works as long as you have component scanning active inside your application. The result will be that for each component spring will create a bean which you can use.
I'm writing this on a mobile so showing code is not the best. Just follow some tutorial on #ComponentScan, or if you need, let me know and I can augment this answer with an example.
As of Spring 4.3 you no longer have to annotate your bean classes and you can let them be instantiated via a componentscan.
#Configuration
#ComponentScan(
value = "some.package.path",
includeFilters = {
#Filter(type = ASSIGNABLE_TYPE, value = {
MyClass1.class,
MyClass2.class,
MyClass3.class
})
})
This actually creates beans for the three classes listed there. The example should work without filters as well (everything in the package becomes a bean). This works as long as the classes have a single constructor that can be used for autowiring. I don't think it is possible to filter for all implementations of a particular interface and then register a bean.
To do that, you might do something with a ContextListener and e.g. use reflection to find out what classes to instantiate and then use context.autowire(..) to inject any dependencies from your context. A bit hacky but it might work.
#Override
public void onApplicationEvent(ContextRefreshedEvent event) {
ApplicationContext context = event.getApplicationContext();
MyClass bean
= context
.getAutowireCapableBeanFactory()
.autowire(MyClass.class, Autowire.BY_NAME.value(), true);
...
}
That still leaves the problem of how to get the bean registered in the context of course.
You might also be able to adapt the answer to this SO question on how to add beans programmatically.
Finally the best approach I've found is using a ConfigurationClassPostProcessor. As example I've used https://github.com/rinoto/spring-auto-mock
But, since it is quite complicated and "too much magic" to create beans from nothing, we decided to explicitly create those beans via #Bean.
Thanks for your answers.
I have a DAO that has method like this:
class AbcService
{
private AbcDAO isntance;
public void getStuff()
{
instance.getQueryResult();
}
}
Now if this method is called from anywhere it will give a NullPointerException where instance calls the query method.
Still this code is in use in the project from a long time and i would think twice before calling it incorrect. Is there some way by which this code can be accessed. Is this a standard practice?
If you have a setter for isntance, you just need to call it before calling getStuff. This is standard (although some would say all needed fields should be set inside a constructor.
This answer just applies if you are using springbean and its broader than your question.. But I guess this will be useful to you
Yes this is generally used practice when you are using it as a spring bean. So, before calling this method, you need to be sure that this springbean is instantiated. Basically, this is done by either getting spring bean from ApplicationContext or the caller class itself receives instance of this bean from its parent bean....
General practise is to load application context by defining contextloaderlistener in web.xml. For more info on how to do it, see http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/web/context/ContextLoaderListener.html
I think the object instance is injected to AbcService via the Spring Dependency Injection. Please search for any ".xml" file in your project, which has fully qualified class name of AbcService mentioned in its bean definition.
I'm just getting started with Spring IOC concept. I often see most of the examples found in the internet use the code to get the object.
ApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Hello hello = (Hello) appContext.getBean("hello");
As a reference from these questions 1 and 2 in the stackoverflow. I've inferred that, it's not necessary to use appContext.getBean("hello") in the code which is considered to be the bad practice. Also, not recommended anymore. Correct me right here, If my inference is wrong.
Keeping that in view, I have made changes in my project accordingly.
Here's my applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<bean id="utilClassRef" class="org.hd.derbyops.DUtils" lazy-init="false" />
<bean id="appContext" class="org.hd.derbyops.ContextProvider" lazy-init="false">
<property name="utils" ref="utilClassRef" />
</bean>
</beans>
My contextProvider Class Code
public class ContextProvider implements ApplicationContextAware {
private static ApplicationContext ctx;
/**
* Objects as properties
*/
private static DUtils utils;
public void setApplicationContext(ApplicationContext appContext)
throws BeansException {
ctx = appContext;
}
public static ApplicationContext getApplicationContext() {
return ctx;
}
public static DUtils getUtils() {
return utils;
}
public void setUtils(DUtils dUtilsRef) {
utils = dUtilsRef;
}
}
For instance, consider a class A that depends on org.hd.derbyops.DUtils.
I'm using the following code line
ContextProvider.getUtils();
inorder to get DUtils Object in class A, thus avoiding usage of ApplicationContext.getBean() anywhere in my code.
Assume, if I have 10 classes and my class A is dependent on all of them, whose objects to be created and accessed without using ApplicationContext.getBean(). In that case also, as done above, I have a thought of creating properties of ContextProvider class followed by setter's and getter's of that property, where in get<PropertyName> is static. So that, I can use it wherever I'm in need of an object, like this
ContextProvider.get<PropertyName>;
Here's my brief question.
Firstly, Is my approach right? If it's right, loading all the beans at the start-up, wouldn't it be a performance killer? How would you do that in your applications without calling getBean atleast more than once?
If you were to design a web-application & you were to implement Spring IOC, without using ApplicationContext.getBean() in any of the code. How would you do that?
Note: with reference to the other questions tagged above
Calling ApplicationContext.getBean() is not Inversion of Control!
The simple answers are yes and no, no, and no. And finally, do a search online for spring MVC, as this probably does what you want.
So, your approach. Yes, you've got most of it right. However, it's considered very bad practice to use static methods for everything. And, you don't need to. Spring is based on the idea that you can simply create normal pojos, and spring will use them as singletons, and inject them into one another (it can also create objects on the fly, but I'm going for the common case here). If you use static classes and methods then:
You can't mock them for unit testing (you're using JUnit right?)
You can't use them with inheritance
Static initialisers are a great way to loose exceptions
etc, etc
So, yes to injection, and no to static stuff.
Next, performance. You're right in that it's a lot slower to use spring, but, if you do all your injection on startup it only happens once. Spring is meant for server side applications where there is likely to be a number of singleton classes passing data around. So, there might be a class to get stuff from a DB, one to process it, and one to display it, and spring is used to wire them together.
If you're using spring in an application where you start up repeatedly, like a command line app, then you are using it for the wrong sort of application, and you probably want to use a builder or something. Spring is meant for big enterprise apps that aren't restarted often.
Finally, if you simply inject all the dependencies for a class into it at startup, and you do this with all your classes, then you don't need to do any getBean stuff at all. Also, using the init-method and destroy-method attributes on a bean means that you can start up processes once spring has finished injecting dependencies. You need only load the context, and your app will spring (pun intended) into existence.
As for web projects, Spring MVC basically takes the whole inversion of control pattern and applies it to web applications. The spring stuff gets loaded by the container, and you can define the URLs to respond to using nothing more than bean names. And most of your code can stay as pojos. If you have something insanely complex, you may want to look at spring web flow, but I'd advise you to make sure that your spring foo is very strong before attempting that.
Here's my example for getting the first instance without actually calling getBean() on ApplicationContext.
public class Test{
// Declare private static variable so that we can access it in main()
private static Triangle triangle;
// Use constructor injection to set the triangle
public Test(Triangle triangle) {
Test.triangle = triangle;
}
public static void main(String[] args) {
// Specify the context file containing the bean definitions
// Spring automatically creates instances of all the beans defined
// in this XML file. This process is performed before you actually make
// a getBean("beanName") call.
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
// Use instance methods of triangle
Test.triangle.draw();
}
}
You can use another way:
In spring.xml (Your bean configuration XML file)
<bean class="com.example.Test" init-method="myMethod">
<constructor-args ref="triangle"/>
</bean>
Now for your main class
public class Test {
private final Triangle triangle;
public Test (Triangle triangle) {
this.triangle = triangle;
}
public static void main (String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
}
// Called by Spring immediately after the Triangle Bean has been created and
// all the properties for the bean have been set. This method name must match
// the one specified with destroy-method attribute in spring.xml
public void myMethod () {
triangle.draw();
}
}
Given the following classes:
package com.acme;
public class Foo {
private Bar bar;
public void setBar(Bar newBar) {
this.bar = newBar;
}
}
#AcmeService
public interface Bar {}
and a Spring configuration file of:
<beans>
<bean id="foo" class="com.acme.Foo">
<property name="bar" ref="bar" />
</bean>
</beans>
when Spring's configuration phase runs, is it possible to do the following?
Catch the missing dependency exception (or detect that there is going to be one)
Discover that the missing dependency "bar" of bean "foo" is of type com.acme.Bar
Notice that Bar is an #AcmeService, and so we're going to handle it. Otherwise, the error can be considered fatal
Generate a proxy of type com.acme.Bar
Inject the Bar proxy into Foo, ensuring that method calls on Bar can be advised with Spring AOP just as if I had explicitly created the Bar proxy in the Spring config file and injected the proxy into the Foo bean.
I was initially drawn to BeanPostProcessor and BeanFactoryPostProcessor as a means to implement this, although upon reading the documentation I did not see an obvious way of doing precisely what I want.
In case you're wondering, the underlying use case is that I want to:
Replace all Spring context files with my service-layer bean definitions with a single context file that generates proxies of #AcmeService bean interfaces.
Advise invocations against those proxies to instead be invoked on interface mocks of the service layer bean proxies. (The kicker is that the mocks are defined at runtime by a remote system and are uploaded to this app for integration testing purposes. For my regular unit tests, I do the more sane thing of simply creating and injecting mocks as needed).
I have all of that working except for the whole "dynamically generate proxies" bit. Currently I have empty implementations of my service interfaces defined in my context file just so they can be injected and advised - but I'd rather not have so many empty interface classes generated and checked in. And lastly, I assume I need to generate these proxies as I do not know how to advise attempted invocations on null dependencies.
OK, there's a number of things in here to talk about.
Firstly, I don't think you'll be able to do exactly what you're asking. In particular, if you have <property name="bar" ref="bar"/> and there is no bean definition for bar, the bean initialization will fail, and I don't think you can intercept that easily. You could, of course, write your own subclass of the BeanFactory itself, but that's not something to be taken lightly.
The closest existing mechanism to what you're asking for is auto-wiring. Take a look at AutowiredAnnotationBeanPostProcessor. You could use this as a guide for writing your own BeanPostProcessor which looks at every bean as it's instantiated by the container, looking for properties which are of types which in turn have the #AcmeService annotation. When it finds one, it can generate a proxy for that type and inject it.
That brings us on to the proxy generation itself. The place to look for that is ProxyFactory. This allows you to generate objects at runtime that implement any interface or extend any class, whilst attaching advisors/interceptors. These interceptors can do all the work - the proxy doesn't have to have anything "behind" it if you don't want to.
With this approach, you wouldn't need the "hanging" <property name="bar" ref="bar"/> entry in your config - the presence of the property in Foo would be enough to trigger the process.