I would like to lazy load a resource within a lazy loaded configuration class. it seems that it is not currently possible with Spring 4.1.
#Configuration
#Lazy
public class ModificationConfiguration {
#Resource(name="modProps")
#Lazy
Map<String, String> props;
#Bean
Map<String, String> modProps(){
...
}
}
from the Spring documentation
In addition to its role for component initialization, the #Lazy annotation may also be placed on
injection points marked with #Autowired or #Inject. In this context, it leads to the injection
of a lazy-resolution proxy.
It seems natural to also want this available with #Resource as I can't use #Autowired on a Map<String, String>. Without the #Lazy being available on #Resource the modProps() bean is created straight away.
Is there a technical reason why it is not currently possible to do this?
Related
I have a class which I have annotated with #Service #Scope
#Slf4j
#Service
#Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class ProductDataModel {
#Value("${message}")
private String message;
The above code seems to be creating a bean for ProductDataModel, without using the #Bean annotation.
I am using #Autowired ProductDataModel productDataModel in my code, and the dependency productDataModel is not null, when used with above piece of Code.
How come the above code is creating bean ??
Ideally, I would have expected bean to created only when I use the below code
//I am not using this piece of code in my program., for reference only
#Configuration
public class OSCConfig {
#Bean
#Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
ProductDataModel productDataModel(){
return new ProductDataModel();
}
Can someone explain the difference between 2 pieces of code and when to use which one.
As #M. Deinum pointed out that we don't need to specify #Bean for each class when we declare #Service or #Controller annotation they are picked up by Spring Container if component-scanning is enabled for that package.
So good use case for using #Bean could be that
If the Class is in third party jar and you can not add #Service/#Controller annotations
If you want to add some custom logic inside the #Bean annotate methods
The #Service annotation is picked up by Spring when scanning for objects to create (as part of a package scan). It is an specialisation of the spring #Component annotation, but doesn't really add much other than providing an indication to users about its intended purpose. The #Controlller annotation is similar, but the bean created has specific characteristics.
The #Bean annotation as you have used it is also used when creating objects, and in this context it is on a method in a Configuration class, therefore the bean created is of the type returned by the method.
I read about the component scan and as I understood that configuration classes are auto-scanned. my question if I have the following:
#Configuration
public class AppConfig {
#Bean(name="authenticationService")
public AuthenticationService getAuthenticationService(){
return new AuthenticationService();
}
}
if the #Configuration is already scanned (so the app config will be available ), wouldn't be the bean inside it created? I'm little confused as they say the #Bean is not auto scanned
No. Spring won't scan #Bean methods.
Here, you are creating the bean of AuthenticationService just like in any other java program using new keyword.
It is same as AuthenticationService authenticationService = new AuthenticationService();
If you want spring to create a bean of AuthenticationService in AppConfig class, use #Autowired annotation
#Autowired
private AuthenticationService authenticationService;
Hope this helps!
EDIT :
#M.Deinum corrected me that spring doesn't create beans based on #Autowired annotation. Beans are created automatically by spring if their classes are annotated with #Component/ #Configuration / #Service annotations.
#M.Deinum, Thank you.
If I do
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
myBeans = applicationContext.getBeansOfType(MyBean.class).values();
}
does that have exactly the same effect as putting this in my constructor?
#Inject
public MyClass(Collection<MyBean> myBeans) {
this.myBeans = myBeans;
}
in commot case yes (without #Lazy ,#Value , required...), they are do the same effect.
In a Spring application, the two annotations works the same way as Spring has decided to support some JSR-299 annotations in addition to their own.
But there are some annotation that doen't hendled by #Inject like - laze , required as it's part of spring but not part of jsr.
Looks like if - all that you get by #Inject for Collection myBeans you get in spring also , but it's not true for all getted by spring also loaded by #inject
here is blog about comparison #AUTOWIRED AND #INJECT SPRING INJECTION WITH #RESOURCE, #AUTOWIRED AND #INJECT
Spring #Autowired
I have a doubt on Spring #Autowired annotation.Please Help...
In Spring mvc ,when I tried #Autowired in this order
Controller--->Service--->Dao
ie,In Controller I autowired Service Class Object , In Service Class Autowire Dao Object.
This Injection chain works perfectly.
Similliarly In strutrs2+Spring ,I applied #Autowired Annotation in this way
Action--->Service-->Dao
This Injection chain also works fine.
If I call a funtion from outside this chain (eg:Custom Taglib class (from jsp)) to funtion in Service class Then in this Service class the Autowired dao object is null(ie,this call braks the chain).
My questions is
Is this #Autowired works in a Injection chain Only?
Beans that have #Autowired fields only have them set if they are sent through the Spring Bean Postprocessor -- that is, like you said, if you autowire them yourself. That is a big reason that constructor injection is much more preferred than field injection. Instead of doing
#Service
public class MyService {
#Autowired
private MyDao dao;
...
}
you should do
#Service
public class MyService {
private final MyDao dao;
#Autowired
public MyService(MyDao dao) {
this.dao = dao;
}
}
That way, when you're in a situation where you can't rely on a service to be post-processed (as in your case of using the jsp tag library), you can simply instantiate a new instance with a MyDao object and be on your merry way.
I am using Spring for my DI.
Is there an equivalent of #ManagedProperty? I want to inject the value from one view scoped bean into another one on the next page.
e.g
#Component
#Scope("view")
public class Page1Bean(){
private String value;
}
#Component
#Scope("view")
public class Page2Bean(){
#ManagedProperty(value = #{page1Bean}") //doesnt work in Spring
private Page1Bean bean;
}
#Resource or #Autowired should work. #Resource is the Java EE implementation, #Autowired is the spring specific annotation. I can't find the reference now, but it seems like I read once to prefer #Resource over #Autowired.
here's a blog post I found that talks about #Inject vs. #Resource vs. #Autowired
http://blogs.sourceallies.com/2011/08/spring-injection-with-resource-and-autowired/#more-2350