Can @Autowired by type produce a bean definition?
When you use @Autowired in a spring @Component, spring determines autowire candidates for every instantiation of the component, which is really not good when you use @Request/@Se开发者_C百科ssion scoped web stuff. Why doesn't spring just make a bean definition within the ApplicationContext once and re-use that ? Is there any way to make it do so ?
AutowiredAnnotationBeanPostProcessor
is a BeanPostProcessor
, not a BeanFactoryPostProcessor
, so it can't edit Bean definitions, by design. Implementing that differently would break expected functionality:
public class MyBean{
@Autowired(required=false)
public void setOtherBean(OtherBean o){this.otherBean=o;}
private OtherBean otherBean;
}
If no OtherBean
instance is available, none will be wired, but as soon as one becomes available (and I can easily programatically wire one), the next MyBean
instance (if scope is not singleton) will get the new OtherBean
(which was not available before).
I'm not saying this a use case I have encountered before, but it's a valid use case and it would break if things worked the way you suggest that they should.
Yes: Spring will reuse the component when you set the scope to something else (i.e. you must not use prototype, session or request). So the trick is to use two beans: One which has all the stuff that doesn't change. And one bean which is attached to the session/request and has just a single dependency: the first bean.
Spring can't do this for you since there is no rule when a bean is "static" enough - you as a developer have to determine that.
[EDIT] You have to collect the static parts of the bean (those which won't change over time) in a DAO/service bean. Then use that bean in your @Component
-> one lookup.
To speed up the lookup, attach a name to the component. For type-based lookup, Spring has to iterate over the whole context (because several beans could match) while name/ID based lookup is just a lookup in a map.
To give a bean a name, specify it in @Context
, or use @Bean(name="name")
. To tell Spring which bean to use from the context, use @Resource(name)
or @Qualifier("businessObject")
.
Best practice is to use service classes, components, DAOs etc. as singletons and to have just one instance in an application context.@Component annotation causes just the instaces to be found in component scan process, which means, that they are candidates for auto-scan and living instances in spring context. For example:
@Component
public class StudentDAO {
@Override
public String toString() {
return " inside StudentDAO";
}
}
StudentDAO is a data access object, and in best practices, more than one instance of this service calss aren't needed in context. It is basically a service class. It is a perfect candidate for a singleton. If there is just one instance of this object around, the autowiring works efficiently too as well 8-) .But you have to still beware of access' on singleton methods and decide to mark your methods as synchronized to prevent unwished effects of threads.
A manual alternative is to inject a singleton-scoped Provider
into your beans which provides prototype-scoped beans.
This means that there is more work done by the programmer, but nevertheless the performance hit will be eliminated.
Set the proxyMode attribute of the @Scope annotation on you request / session scoped beans. Spring will create a proxy which will be auto-wired - the proxy will lookup the actual bean which a method is invoked on it.
精彩评论