#autowired field and also #autowired constructor - spring

I have a spring MVC application. I have a bean which is wired as a singleton and also a field which is also autowired but is of request scope.
For example:
class Hello {
#Autowired
BDepend b; // this is defined as a request scope bean
#Autowired
public Hello(ADepend a){
}
}
Here my class Hello is a singleton but BDepend is a request scope object.
How does spring handle right instance of Bdepend for each of the request since Hello is a singleton.

By default you will have runtime exception at application sturtup. Something like this:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'b': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton;
To use request scope objects inside of some singleton you need to obtain a fresh instace each time from application context. You can do it:
using application context directly
class Hello {
#Autowired
private ApplicationContext ctx;
#Autowired
public Hello(ADepend a){
}
public useB(){
BDepend instance = ctx.getBean(BDepend.class);
instance.doSomething();
}
}
or get a fresh instance via javax.inject.Provider.
class Hello {
#Autowired
private Provider<BDepend> provider;
#Autowired
public Hello(ADepend a){
}
public useB(){
BDepend instance = this.provider.get();
instance.doSomething();
}
}
or declare scoped proxy for this bean:
#Component
#Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
class BDepend {
}
class Hello {
#Autowired
private BDepend b;
#Autowired
public Hello(ADepend a){
}
public useB(){
b.doSomething();
}
}
or use scoped proxies system wide
<context:component-scan base-package="com.mycompany.beans" scoped-proxy="targetClass" />
Personally I prefer second option (javax.inject.Provider): it is clear from the code that your bean has different scope.

Related

Spring Autowired works before proxies are created

As far as I understood, Spring manages autowiring mechanism with AutowiredAnnotationBeanPostProcessor on postProcessBeforeInitialization stage. But how does it inject proxies that ought to be created on postProcessAfterInitialization stage?
EDIT 1
Suppose I have this Spring configuration
#Service
class RegularBean {
// injected on postProcessBeforeInitialization stage
#Autowired
private TransactionBean tBean;
// invoked in between of postProcessBeforeInitialization and postProcessAfterInitialization
#PostConstruct
void init() {
tBean.transactionMethod();
}
}
#Service
class TransactionBean {
// transactional proxy is created on postProcessAfterInitialization stage
#Transactional
public void transactionMethod() { ... }
}
Transactional proxy is created on postProcessAfterInitialization stage. But #PostConstruct is called right before it. Is injected tBean wrapped with transactional proxy? If it so, then why? Because it should not be. If it is not wrapped, then how transactions are going to be handled in the future?
Suppose that I replace field-injection with constructor-injection. Will it change the behavior somehow?
When you use autowiring on method or field ,Spring Container not always create and inject the required field/attribute instance. Spring internally create smart proxies and inject the proxies to your bean. This smart proxy will resolve the bean at later point and delegate call to actual bean during method invocation. This is a common strategy we use to resolve request and session scoped beans to singleton instance (Say service layer beans) using Scope annotation.
Adding small snippet to show Spring internally create proxies for Object. Consider a classic circular dependency case when we use Constructor injection.
#Component
public class CircularDependencyA {
private CircularDependencyB circB;
public CircularDependencyA(#Lazy CircularDependencyB circB) {
System.out.println("CircularDependencyA Ctr ->"+circB.getClass().getName());
this.circB = circB;
}
}
#Component
public class CircularDependencyB {
private CircularDependencyA circA;
public CircularDependencyB(CircularDependencyA circA) {
System.out.println("CircularDependencyB Ctr ->"+circA.getClass().getName());
this.circA = circA;
}
}
#Configuration
#ComponentScan(basePackages = { "com.example.springdemo.cd" })
public class TestConfig {
}
public class TestCircularDependency {
public static void main(String[] args) {
try(AnnotationConfigApplicationContext context
= new AnnotationConfigApplicationContext(TestConfig.class);){
}
}
}
Based on our hints Spring is creating Proxy(using CGLIB) for CircularDependencyB Object and see the op from the CircularDependencyA Constructor
CircularDependencyA Ctr ->com.example.springdemo.cd.CircularDependencyB$$EnhancerBySpringCGLIB$$e6be3b79
Thanks

Use spring Transactional in a Prototype bean

I would like to use spring transaction management capabilities within a prototype bean. I did the following:
I've used javax.inject.Provider to create my prototype bean.
I've annotated the method of the prototyped bean with the #Transactional annotation.
Is this the right way of doing it?
#Service
public class SomeService {
#Autowired
private Provider<SomePrototype> myPrototypeProvider;
public void execute() {
SomePrototype somePrototype = myPrototypeProvider.get();
somePrototype.someMethod();
}
}
#Component
#Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class SomePrototype {
#Autowired
private SomeSpringBean someSpringBean;
#Autowired
private SomeRepository someRepository;
#Transactional(propagation = Propagation.REQUIRED)
public void someMethod() {
Result result = someSpringBean.doSomething();
someRepository.save(result);
}
}
The initialisation of transaction-scoped bean requires a proxy. Therefore, if we define a transactional bean as prototype, every that bean is requested, a new proxy is created, and that is not efficient.
What is reason behind this requirement (to have transactional prototype bean)

Does registering bean inside #Component class respect #Scope?

This website says beans registered inside component classes are not cglib proxied and do not go through the spring container. So does this mean if I register a bean inside a component class (snippet below), adding #Scope("request") wont make any difference, and a new instance of AnotherBean will always be created whenever testBean.anotherBean() is called from some external class?
#Component
public class TestBean {
#Bean
#Scope("request")
public AnotherBean anotherBean() {
return new AnotherBean();
}
}
The bean that is not cglib proxied is the #Component itself, not the bean registered using the #Bean annotation. If you are not calling the anotherBean method explicitly, it won't make a difference because the proxy is used to return the bean when the method annotated with #Bean is called. See the example
The bean testBeanComponent is not cglib proxied :
#Component
public class TestBeanComponent {
#Bean
#Scope("request")
public AnotherBeanComponent anotherBeanComponent() {
return new AnotherBeanComponent();
}
}
The bean testBeanConfiguration is cglib proxied :
#Configuration
public class TestBeanConfiguration {
#Bean
#Scope("request")
public AnotherBeanConfiguration anotherBeanConfiguration() {
return new AnotherBeanConfiguration();
}
}
What it mean :
#Service
public class TestService {
#Autowired //Inject a normal bean
private TestBeanComponent testBeanComponent;
#Autowired //Inject a proxy
private TestBeanConfiguration testBeanConfiguration;
public void test() {
//Calling anotherBeanComponent always return a new instance of AnotherBeanComponent
testBeanComponent.anotherBeanComponent()
.equals(testBeanComponent.anotherBeanComponent()); // is false
//Calling anotherBeanConfiguration return the bean managed by the container
testBeanConfiguration.anotherBeanConfiguration()
.equals(testBeanConfiguration.anotherBeanConfiguration()); // is true
}
}
But if you are injecting the bean instead of using the method, everything will work as you expected :
#Service
public class TestService2 {
#Autowired //Inject a proxy with scope request
private AnotherBeanComponent anotherBeanComponent;
#Autowired //Inject a proxy with scope request
private AnotherBeanConfiguration anotherBeanConfiguration;
}

Why Spring #Autowired ApplicationContext appContext is null?

I have Spring bean with annotations:
#Named
#Scope("session")
And this bean property:
#Autowired
ApplicationContext appContext;
The Spring configuration file has entry (that works for other anotations/injections):
<context:component-scan base-package="my.package.name" />
Why appContext is null after such code and configuration?
I am trying to get ApplicationContext (to call getBean(...) on it) and this can be quite involved task (judging from other discussions) in previous Spring versions (e.g. one is required to get ServletContext in Spring web application to create ApplicationContext and getting ServletContext can be quite involved task for beans that don't directly access HTTP Request objects). In Spring 3.x, as I understand, simple #Autwired injection can be used. How AppContext can be accessed?
Here the first problem is you are using #Named which is Java EE annotation and as for as I know Spring yet to support Java EE annotations. Hence instead of using #Named try to use Spring annotation #Service, #Component, #Repository etc.
Here is the example for you I have used JSF Managed bean as well to show how to integrate beans.
#ManagedBean(name="myBacking")
#RequestScoped
public class MyBacking {
private String myText;
#ManagedProperty(value="#{mySpring}")
MySpringBean mySpring;
public String getMyText() {
myText = mySpring.getText();
return myText;
}
public void setMyText(String myText) {
this.myText = myText;
}
public MySpringBean getMySpring() {
return mySpring;
}
public void setMySpring(MySpringBean mySpring) {
this.mySpring = mySpring;
}
}
#Service("mySpring")
#Scope("request")
public class MySpringBean {
#Autowired
MySecond mySecond;
public String getText(){
return "Hello KP" + mySecond.appObj();
}
}
#Service
#Scope("request")
public class MySecond {
#Autowired
ApplicationContext applicationContext;
public String appObj(){
MyThrid mythird =(MyThrid)applicationContext.getBean("myThrid");
return "My Second Bean calld "+ mythird.getTxt();
}
}
#Service
public class MyThrid {
public String getTxt(){
return "from thrid Bean";
}
}

How to guarantee that Spring #Autowired injection can be accessible in the constructor

I have a Spring Bean which has a #Autowired setter getter injection. However, when i try to access injected bean, i get NullPointerException because the injected bean has not be really injected.
Is there any way to guarantee that the injection is done before constructure call?
#Component
#Scope("session")
public class A{
#Autowired
B;
public A()
{
//B is null here, because it has not been injected yet.
}
//Setter Getters
}
Use the #PostConstruct annotation. This will be called right after Spring initializes your bean.
#Autowired
B b;
public A() {
}
#PostConstruct
public void doAfterConstructorIsCalled() {
b.do();
}
It's from the javax.* API

Resources