I'm using spring mvc 3.1.x and jets3t.
I have a DataAccessObject that i instantiate as a Singleton bean..
I managed to get it working through extending the applicationcontextloader class and adding it to the web.xml
EDIT:
I changed my method, I tried inject and autowired but it's not suitable for my needs.
What I've done was to implement ApplicationContextAware and set it up as a bean, in the code I use it as follows:
ApplicationContext ctx = BannerApplicationContext.getApplicationContext();
BannerGenericDAO bdao = (BannerGenericDAO) ctx.getBean("dao");
I'm new to Spring and in general the servlet world..
Questions are:
what's the best way of doing this? Is this considered a "best-practice"?
How do you inject an object, keeping other method fields that are not supplied by autowiring?
How do you get an object to be used throughout the entire application?
Thanks!!
You could use annotations in your controller.
#Controller
public class MyController{
#Autowired // or #Inject, which is more JEEish (JSR330).
private SomeDao daoService;
}
Given "SomeDao" is the type of your singleton DAO, of course.
Related
Even when we create the Beans in a Spring configuration class, I feel it is still useful to use #Component annotation on the class just to document/indicate that it's a Bean. Is it a good idea? Can there be any other issue that Spring will find the same bean defined in two different ways?
It is bad practice to create two beans from one class...
#Component
class SimpleComponent {
}
#Bean
public SimpleComponent simpleComponentBean(){
new SimpleComponent();
}
By default if we use #Component spring creates bean with name of class, but starts with small letter simpleComponent, if we use #Bean it takes method name and create bean with name simpleComponentBean and we have duplicated beans...
If we have method name the same, as component class name, spring replace one of them and we can Inject unexpected bean.
PS: intellij idea enterprise - correct indicate about all beans.
Motivation
As a follow-up to my previous questions on classloading
How is the Classloader for a class chosen?
How Classloader determines which classes it can load?
Where does bytecode injection happen?
I'm curious about how do annotations work in a popular Spring framework.
Possible solution
As far as I understand, two mechanisms might be used:
1. Bytecode injection on classloading
Spring could use its own classloader to load required classes. At runtime, when the class is loaded and Spring determines it has some appropriate annotation, it injects bytecode to add additional properties or behavior to the class.
So a controller annotated with #Controller might be changed to extend some controller base class and a function might be changed to implement routing when annotated with #RequestMapping.
#Controller
public class HelloWorldController {
#RequestMapping("/helloWorld")
public String helloWorld(Model model) {
model.addAttribute("message", "Hello World!");
return "helloWorld";
}
}
2. Reflection used for instantiation
#Autowired could be read by reflection at runtime by the BeanFactory to take care of the instantiation order and instantiate the configured properties.
public class Customer
{
private Person person;
#Autowired
public void setPerson(Person person) {
this.person = person;
}
}
Question
How do Spring annotations really work?
Spring is open source so you don't need to figure how it work, look inside:
RequestMapping annotation is handled by RequestMappingHandlerMapping, see getMappingForMethod method.
Autowired annotation is handled by AutowiredAnnotationBeanPostProcessor, see processInjection method.
Both use reflection to get annotation data and build the handler mapping info in the first case or populate the bean in the second one.
Spring context understand annotation by set of classes which implements bean post processor interface. so to handle different type of annotation we need to add different annotation bean post processors.
if you add <context:annotation-config> in you configuration xml then you need not to add any annotation bean post processors.
Post processor provide methods to do pre and post processing for each bean initialization.
you can write your own bean post processors to do custom processing by created a bean which implements BeanPostProcessor interface.
Using Spring 3.1. If I want to retrieve a bean with prototype scope (i.e. I want a different instance of the class each time), is it possible to retrieve the bean without having to use an ApplicationContextaware class?
This is how I do it at present
#Component
#Qualifier("MyService")
public class MyServiceImpl implements MyService {
#Override
public void doSomething() {
Blah blah = (Blah)ApplicationContextProvider.getContext().getBean("blah");
blah.setThing("thing");
blah.doSomething();
}
}
#Component("blah")
#Scope("prototype")
public class Blah {
....
}
where ApplicationContextProvider implements ApplicationContextAware.
Is it possible to do this with annotations or simple Spring configuration without having to use an ApplicationContextAware class?
Spring has some fairly sophosticated methods for achieving what you're after...
See the spring documentation: http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/beans.html#beans-factory-scopes-other-injection
Searching for spring proxy scope on google also threw up some results...
You don't really need a ApplicationContextAware. You just need a BeanFactory (ApplicationContextAware is just a convinient way to get it).
A bean with scope prototype just means that everytime ApplicationContext.getBean is called a new instance of the bean is created. If you try to inject a prototype bean in a singleton, your prototype bean will be injected once (and so is no more a prototype).
There is something called method injection that may help you if you really need it, but it is more complex than simply calling applicationContext.getBean().
On many tutorial/books about spring JDBC, RowMapper class usually represented as private static final class inside DAO and the instance is created in every single query.
Does RowMapper have to be used and instantiate in this way?
Is it ok if I define RowMapper class as spring bean using #Component annotation and #Autowired it to my dao class?
Which one is better?
Does RowMapper have to be used and instantiate in this way
No, that's just a common usage pattern.
Is it ok if I define RowMapper class as spring bean using #Component annotation and #Autowired it to my dao class?
Sure, that would work. Unless the RowMapper needs access to other Spring services, though, there's not much point.
Which one is better?
Without seeing your code and getting a feel for your application, we can't really tell you if it's a good idea or not, only you can make that choice.
My personal preference would be to keep the RowMapper as a non-static inner class of your DAO class, and to insantiate it directly from the DAO. If the RowMapper needs access to other Spring beans, then wire those intop the DAO, and access them from the RowMapper inner class.
I use Spring and have an aspect that wraps around some class:
#Aspect
public class LoggingAspect{
#Around("execution(public * com.service.MyService.doStuff(..))")
public Object log(){
...
}
}
and in context xml:
<aop:aspectj-autoproxy/>
<bean id="loggingAspect" class="com.bla.bla.bla.LoggingAspect"/>
The problem is that instances of MyService are created at runtime so Spring knows nothing about this class during context initialization phase. Is it possible to use aspects in this case to wrap method calls of a class instantiated using new (not Spring)?
If my reading of the Spring docs is correct, you do it like this (for Spring proxy-based weaving):
ProxyFactory factory = new ProxyFactory(new SimplePojo());
factory.addInterface(Pojo.class);
factory.addAdvice(new RetryAdvice());
Pojo pojo = (Pojo) factory.getProxy();
or like this (for AspectJ-style weaving):
AspectJProxyFactory factory = new AspectJProxyFactory(new SimplePojo());
factory.addAspect(new RetryAspect());
Pojo proxy = factory.getProxy();
(I drive all my AOP weaving through my bean configuration so I've not needed to use this sort of thing in practice.)
No, you can only use Spring AOP to advise Spring beans (because Spring creates a proxy object behind the scenes). You'll have to use full AspectJ, or create your MyService in the Spring container. See http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/aop.html#aop-choosing.