Spring 4.3 Implicit Constructor Injection Behavior On Lazy Component - java

One of the new features in Spring 4.3 is implicit constructor injection in which we don't have to specify #Autowired anymore on top of the constructor.
My question is, how does the implicit constructor injection behave on lazy bean?
#Component
#Lazy
public class SomeClass {}
#Component
public class ClientClass {
// does SomeClass still lazily initialized???
public ClientClass(SomeClass someClass) { ... }
}

You've applied the annotation to the bean, which means that Spring will create a lazy proxy and inject it where SomeClass is required. The fact that the bean requirement comes from an implicit (singleton) constructor doesn't matter.

Related

Passivation of CDI SessionBean with Constructor Injection

I have following CDI Bean:
#SessionScoped
public class ReportService implements Serializable {
private static final long serialVersionUID = 1L;
private MyDao myDao;
#Inject
public ReportService(MyDao myDao) {
this.myDao = myDao;
}
}
#RequestScoped
public class MyDao extends AbstractDao<Order> {
protected MyDao() {
}
#Inject
public MyDao(EntityManager em) {
super(em);
}
}
If i start my webapplication (Tomcat with Weld) the following Exception is thrown:
WELD-001435: Normal scoped bean class
com.myorg.ReportService is not proxyable because it
has no no-args constructor - Managed Bean [class
com.myorg.ReportService] with qualifiers [#Any
#Default].
How is it possible to use constructor injection in a SessionScoped Bean?
Is it safe just to add a package-visible no-args constructor?
I already searched a lot, but i did not find any information about passivating a CDI Bean whitch uses Constructor Injection.
The error you are getting is based on CDI specification requirements, namely the need to have no-args constructor. When instantiating the object, CDI will of course prioritize a constructor annotated with #Inject, so don't worry about that.
The real reason why you need no-args one is for proxies. Weld/CDI will try to create one or more proxies of your object, which are basically an enriched delegates. In order to instantiate them, you want to invoke no-arg constructor - think of it as Java limiation, you shouldn't be instantiating objects without calling constructors. Therefore the spec mandates the need for no-arg constructor. As a matter of fact, Weld itself allows you to bypass this need in certain cases, but I strongly suggest against it.
Is it safe just to add a package-visible no-args constructor?
Yes, go ahead and do that.

The bean could not be injected as a 'Type' because it is a JDK dynamic proxy that implements: reactor.fn.Consumer

My Spring 4 application, which uses Reactor 2, fails to start with:
***************************
APPLICATION FAILED TO START
***************************
Description:
The bean 'orderHandlerConsumer' could not be injected as a 'fm.data.repository.OrderHandlerConsumer' because it is a JDK dynamic proxy that implements:
reactor.fn.Consumer
Action:
Consider injecting the bean as one of its interfaces or forcing the use of CGLib-based proxies by setting proxyTargetClass=true on #EnableAsync and/or #EnableCaching.
The OrderHandlerConsumer is really simple:
#Service
#Order(Ordered.HIGHEST_PRECEDENCE)
public class OrderHandlerConsumer implements Consumer<Event<OrderEnvelope>> {
#Override
public void accept(Event<OrderEnvelope> event) {
event.getData().getLatch().countDown();
}
}
Any ideas what might be going awry?
In your application class file where you define it as Spring application, add underneath it.
#SpringBootApplication
#EnableCaching(proxyTargetClass = true)
While the accepted answer will solve this issue, I think it will be more appropriate for me to explain why appling proxyTargetClass = true will fix this.
First of all, Spring, as a framework, utilizes proxing in order to supply the bean with some extended functionality, such as declaritive transactions via #Transactional, or caching by the means of #Cacheable and e.t.c. There are, in general, 2 ways(*) Spring can create proxy on top of your bean:
Jdk dynamic proxing
CGLib proxing
Offical documentation on this, in case you are interested.
Spring can create jdk dynamic proxy of the bean (in case proxing is required for this bean of course) if original class of the bean implements at least one interface. So spring basically create another implementation of this interface at runtime with some additional logic on top of original class.
What is the problem: if the bean is proxied by the means of jdk dynamic proxing , then you cannot inject this bean via its original class. So something like this:
#SpringBootApplication
#EnableTransactionManagement(proxyTargetClass = false)
public class StackoverflowApplication {
#Autowired private SomeService service;
public static void main(String[] args) {
SpringApplication.run(StackoverflowApplication.class, args);
}
}
#Service
class SomeService implements SomeInterface {
#Override
#Transactional
public void handle() { }
}
interface SomeInterface {
void handle();
}
wont work. Why? Well, becuase #Transactional tells Spring that it needs to create proxy of SomeService at runtime, and within #EnableTransactionManagement I specifically asked Spring to make it by the means of jdk dynamic proxy - spring will succeed, since jdk dynamic proxy can be created, but the problem is at runtime there is not bean of type SomeService, there is only a bean of type SomeInterface (by the way, if you inject service here not by the class, but by the interface - it will work, I assume you understand the reason by reading explaination above).
Solution: by applying #EnableTransactionManagement(proxyTargetClass = true) (notice true value here) you force spring to create CGlib proxy (this rule is applicable only for beans that utilize declarative transaction management, i.e. via annotations). In case of CgLib proxing, Spring will try to extend the original class, and add additional functionality at runtime in the generated child class. And in this case injection by class will work - because the bean extends class SomeService, so
#Autowired
private SomeService someService;
will work perfectly fine. But, in general, if possible, inject bean by interface, not by class. In this case both Cglib and jdk dynamic proxy will work. So, be aware of proxing mechanisms spring can use. Hope it helped, have a nice day.
You can assign a bean name to your OrderHandlerConsumer class so that Autowire resolution will be easier, Moreover, Instead of Autowiring with the concrete class, try to auto-wire with the interface. So that you can change #Service annotation to,
#Service(value="orderHandlerConsumer")
and try to Autowire with the interface type,
#Autowire
reactor.fn.Consumer orderHandlerConsumer;
Please try autowiring as below
class Test{
#Autowired
private Consumer orderHandlerConsumer;
}
If the target object to be proxied implements at least one interface
then a JDK dynamic proxy will be used. All of the interfaces
implemented by the target type will be proxied. If the target object
does not implement any interfaces then a CGLIB proxy will be created.
https://docs.spring.io/spring-framework/docs/3.0.0.M3/reference/html/ch08s06.html
You can call it two ways.
1st way is without mentioning the proxy [with default proxy], you can Autowire it by the interface like below.
#Autowired
private Consumer orderHandlerConsumer;
Spring AOP will create an instance for OrderHandlerConsumer.
2nd way is, mention the proxy in the bean as ScopedProxyMode.TARGET_CLASS.
then you can Autowire an instance without the interface [based on the class].
#Service
#Order(Ordered.HIGHEST_PRECEDENCE)
#Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class OrderHandlerConsumer implements Consumer<Event<OrderEnvelope>> {
#Override
public void accept(Event<OrderEnvelope> event) {
event.getData().getLatch().countDown();
}
}
and Autowire by the class like below.
#Autowired
private OrderHandlerConsumer orderHandlerConsumer;

Spring bean lazy initialization

I was thinking about the lazy-initialization of beans in Spring. For me, it wasn't crystal clear that the "lazy" here means that a bean will be created when it's referenced.
I expected that the lazy initialization support in Spring is different. I thought this is a "method-call" based lazy creation. What I mean by this is, whenever any method is being called on the method, it will be created.
I think this could be easily solved by creating a proxy instance of the specific bean and do the initialization on any method call.
Am I missing something why this is not implemented? Is there any problem with this concept?
Any feedback/idea/answer will be appreciated.
You can achieve the behavior you want by scoping your bean with a proxyMode of ScopedProxyMode.TARGET_CLASS (CGLIB) or ScopedProxyMode.INTERFACES (JDK).
For example
public class StackOverflow {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Conf.class);
Bar bar = ctx.getBean(Bar.class);
System.out.println(bar);
System.out.println(bar.foo.toString());
}
}
#Configuration
class Conf {
#Bean
#Lazy
#Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
public Foo foo() {
System.out.println("heyy");
return new Foo();
}
#Bean
public Bar bar() {
return new Bar();
}
}
class Bar {
#Autowired
public Foo foo;
}
class Foo {
}
will print
com.example.Bar#3a52dba3
heyy
com.example.Foo#7bedc48a
demonstrating that the Foo bean was initialized through its #Bean factory method only after a method was invoked on the Foo instance injected by the Spring context in the Bar bean.
The #Scope annotation can be used in a class declaration as well.
bellow is my views:
Bean types in Spring Container:
There are two Scope bean type in Spring Container.One is Prototype, this type bean won't exist lazy-init concept, because these beans will be instantiated when clients invoke the getBean() method every time. Another is Singleton, these bean will be instantiated once, these beans can be lazily instantiated(just be instantiated when they're used, such as #Autowired, refrenced) if you define the bean use #Lazy or lazy-init=true.
How to implement lazy-init:
Yes, common implementation is Proxy Mode. Spring use JDK Dynamic Proxy and Cglib to implement Proxy, you can go further understanding about these techs.
Hope to help you.

Spring How to autowire a component without using #Component or other derivatives

I would like to autowire a component (still using the #Autowired annotation), but not require it to have the #Component (or other similar annotations) on it. How would I do this?
public class A {
#Autowired
private class B b;
}
#Component
public class B {
}
This would be convenient in order to allow autowiring of class A without requiring the creation of A, unless we needed it (in otherwise on the fly by reflection using the class name).
Injection and autowiring do not require #Component. They require beans. #Component states that the annotated type should have a bean generated for it. You can define beans in other ways: with a <bean> declaration in an XML context configuration, with a #Bean method in a #Configuration class, etc.
Your last sentence doesn't make much sense. You can't process injection targets in a bean without creating a bean. You also can't inject a bean without creating it. (Applied to scopes, bean may refer to the target source/proxy and not the actual instance.) Perhaps you want #Lazy.
I don't sure, If I correctly understood to your question. But if you want inject bean B without marking bean A via some annotation, or xml definition, you can use SpringBeanAutowiringSupport
public class A {
#Autowired
private class B b;
public A{
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
}
}

#Autowired does not create members in constructor

I have a bean that is created from context, after which a autowired member is created:
#Service
public class FileDownloadService extends WFWFileDownloadService {
#Autowired
ConfigurationManager configurationManager;
When I use in code manual constructor call:
FileDownloadService fileDownloadService = new FileDownloadService();
I see configurationManager is null, so I have to make manual wiring:
public FileDownloadService() {
configurationManager = new ConfigurationManagerImpl();
}
What am I doing wrong to make autowiring working with manual creating?
When you call the constructor directly, you're just creating an object and not a bean. The support of the #Autowired annotation is a feature of bean.
Ask the Spring context for the bean.
If you attempt to get the bean by using new operator, you will get all autowired beans inside that class as null.
Your service class is annotated with #Service, so to use it you should autowire this service class also.
Sample code to access service bean in other classes is :
#Controller or #Component
public class OtherClass {
#Autowired FileDownloadService fileService;
public void download() {
fileService.downloadFile();
}
}
In order this class to be able to autowire other beans, this class itself should be annotated with #Controller or #Component.
The Answer is simple:
If you manually create the Object, there is no wiring involved. How should Spring know, that you are in need for wiring? Instead of using new, you could use the getBean() method of the application context (Bean Factory). http://static.springsource.org/spring/docs/current/javadoc-api/index.html?org/springframework/beans/factory/BeanFactory.html
http://static.springsource.org/spring/docs/current/javadoc-api/index.html?org/springframework/beans/factory/BeanFactory.html

Categories