Spring Framework Autowired&Beans Example and Explanation - java

I'm totally lost on this topic . I've researched Spring Autowiring on internet trying to figure out what it does and everything I find is mostly saying "Spring Autowiring helps you autowire collaborating Beans " and thats it . I would greatly appreciate if someone can explain to me from scratch what is Spring Bean, What is Autowiring and how these two work together with examples and explanations of this examples. Don't just say that "Spring Autowiring is autowiring two beans " because I don't get it what it means .
What I understand right now is that lets say if have a simple class :
Public class Car(){
public int numberOfWheels;
}
and we declare this class as a Bean, we than can create the instance of the object of this class without saying "new" keyword. So we can just declare it in a bean and insert value of this "numberOfWheels" property outside the java class . I might be super wrong here or using very bad example , because I've been trying to learn Spring Framework and it's just been very hard for me , so any help would be greatly appreciated.

Well, Spring is a Dependency Injection framework, so you should start learning about this.
DEPENDENCY INJECTION
This is a technique whereby one object supplies the dependencies of another object. Such as, for example: object a of type A need is dependent of an object b of type B. In a code example:
Customer it's dependent of Person:
public class Person {
private String name;
private String lastName;
}
public class Customer {
private Person person;
}
In this case, any Customer object will have a Person object dependency.
Now, in Spring scope, all objects are named beans, so this is a bean, an Object that it's injected into Spring Context.
Spring provides a Dependency Injection mechanism that it's very easy. For our example, you can put put some of the following annotation: #Component, #Bean, #Service on class Person, and Spring will create an object of type Person with calling default constructor. Afer that, in class Customer, you can put #Autowired annotation on top of the Person person attribute. This annotation, will tell Spring to search for a specific bean of type Person that was injected into the Spring Context, and Spring using Reflection(searching by name) will find a Person object type that was creating by using one of the #Component, #Bean, #Service annotations. After that, Spring will pass the reference of the Person object that was found to the Customer object that requires it.

Spring Bean is an object which is instantiated and maintained automatically by Spring Framework. They usually depend on each other in some way, and the dependencies therefore must be resolved.
Autowiring is one of the ways how to resolve these dependencies. You don't manually specify which concrete dependency should be provided to the class, you just choose the way how Spring should automatically find the correct dependency (by matching the class's property name and name of the desired bean, for instance).
Spring's documentation is very extensive and you can find a lot of useful information there. For more info about Spring Beans, you can read this, if you want to know more about autowiring, try this.

To basically, Spring has a bean pool which means Spring creates java objects and put them into a pool. Whenever you want to use an object, you fetch object from pool using #Autowired annotation.
Spring basically uses Reflection to create objects by its own, instead of passing objects from class to class. This is what basically Autowire is.
This concept is called Dependency Injection. Spring injects components, services, repositories whenever you want.

Related

How to call Spring Framework repositories methods

I know that there are questions similar to this one, but none of them have helped me. I'm following along this tutorial, and the part I can't wrap my mind around is:
#SpringBootApplication
public class Application {
private static final Logger log =
LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
#Bean
public CommandLineRunner demo(CustomerRepository repository) {
return (args) -> {
// save a couple of customers
...
// more lines, etc...
What I don't understand is where the repository passed into demo comes from. I know that the Autowired annotation can do something like that, but it isn't used at all here.
The more specific reason I ask is because I'm trying to adapt what they do here to an application I'm working on. I have a class, separate from all of the persistence/repository stuff, and I want to call repository methods like save and findAll. The issue is that the repository is an interface, so I can't instantiate an object of it to call the methods. So do I have to make a new class that implements the interface and create an object of that? Or is there an easier way using annotations?
When creating a #Bean, adding the repository in the parameters of the bean is enough to wire the repos in your bean. This works pretty much like adding #Autowired annotation inside a class that is annotated as #Component or something similar.
Spring works mostly with interface, since that is simplier to wire vs wiring concrete classes.
Can you try #Repository before the declaration of class? Worked for me in a Spring MVC structure.
#Repository
public class EntityDAOImpl implements EntityDAO{
...
}
The thing to wrap your head around is a Spring Boot application at startup time aims to resolve its dependancy tree. This means discovering and instantiating Beans that the application defines, and those are classes annotated with #Service, #Repository, etc.
This means the default constructor (or the one marked with #Autowire) of all beans is invoked, and after all beans have been constructed the application starts to run.
Where the #Bean annotation comes into play is if you have a bean which does not know the values of it's constructor parameters at compile time (e.g. if you want to wire in a "started at" timestamp): then you would define a class with an #Configuration annotation on it, and expose an #Bean method in it, which would return your bean and have parameters that are the beans dependencies. In it you would invoke the beans constructor and return the bean.
Now, if you want a certain method of some class to be invoked after the application is resolved, you can implement the CommandLineRunner interface, or you can annotate a method with #PostConstruct.
Some useful links / references:
https://docs.spring.io/spring-javaconfig/docs/1.0.0.m3/reference/html/creating-bean-definitions.html
https://www.baeldung.com/spring-inject-prototype-bean-into-singleton
Running code after Spring Boot starts
Execute method on startup in Spring

How to tell if a class is Spring loaded in java?

I have been given a task to assign a property from .properties file to a non Spring bean class using #Value annotation. To do this, I created a method on a #Component annotated class and set the property into it, then called that method from the non Spring bean class. I thought this would work, however, still showing as null.
I was told this is because the #Component annotated class I used is not spring loaded. Question, how can I tell if a class is Spring loaded bean? I have been searching on google but can't find anything helpful aside from examples with #Component or #Configuration annotations. Thanks.
Spring Container is responsible for creating or managing beans. It all satisfy the dependencies by injecting them either through constructor or setter method. But in your case you want the #Value injection in your non spring bean which is really not possible as per my understanding. Because here the spring does not creating the object then how it satisfy the dependencies of it.
You have two options for this situation.
Either annotate class using #Component
Either read property file using Properties
https://www.mkyong.com/java/java-properties-file-examples/

How does Java Spring #Autowired work with interface inheriting from several interfaces?

I have a Java Spring Framework project. After a bit of googling I found a way to include custom JPA methods into a JpaRepository. The injection of my repository into my service class using #Autowired works, but I can't understand how Spring handles the injection in this case. Could someone explain how Spring does the injection of CalendarEventRepository into CalendarEventService when the method implementations are in separate classes. It finds the JpaRepository implementation somewhere and my own custom implementation class with my custom method. Howcome their methods are accessible through the same reference variable calendarEventRepository? Bonus question: how does Spring find and instantiate the implementation for JpaRepository?
public interface CalendarEventRepository extends JpaRepository<CalendarEvent, Long>, CalendarEventRepositoryCustom { }
public interface CalendarEventRepositoryCustom {
public List<CalendarEvent> findCalendarEventsBySearchCriteria(CalendarEventSearchCriteria searchCriteria);
}
public class CalendarEventRepositoryImpl implements
CalendarEventRepositoryCustom {
public List<CalendarEvent> findCalendarEventsBySearchCriteria(CalendarEventSearchCriteria searchCriteria) {
}
}
public class CalendarEventService {
#Autowired
CalendarEventRepository calendarEventRepository;
...
calendarEventRepository.delete(calendarEvent);
...
return calendarEventRepository.findCalendarEventsBySearchCriteria(searchCriteria);
...
}
Thanks in advance!
When you are using Spring JPA repository interface (extend JpaRepository class), the important thing is that the implementation of the interface is generated at runtime. Method names are used by Spring to determine what the method should (since you have written the name findCalendarEventsBySearchCriteria correctly, it means that you already know that). In your particular case, CalendarEventRepository extends CalendarEventRepositoryCustom and therefore has a method findCalendarEventsBySearchCriteria(...), and also extends JpaRepository<CalendarEvent, Long>, which means that it should be treated as JPA repository, and the corresponding implementation should be generated.
To enable the generation of the repository implementation, you need to either include <jpa:repositories base-package="..." /> to your XML configuration file, or #Configuration #EnableJpaRepositories(basePackage = "...") When you have these, that's all the information Spring needs to generate (instantiate) repository and add it to application contexts, and the inject it into other beans. In your case, #Autowired CalendarEventRepository calendarEventRepository; specifies where it should be injected. I guess it more answers bonus question than the main one, but seems better to start with it.
I haven't yet touched CalendarEventRepositoryImpl. You should use such class if you want to drop the mentioned generation of repository implementation for particular methods. Spring looks for a class which name equals to repository interface's name + "Impl". If such class exists, Spring merges its methods with generated ones. So, see for yourself whether auto-generated findCalendarEventsBySearchCriteria method fits your needs or you want to implement it yourself. If the generated one fits, you should consider removing CalendarEventRepositoryImpl at all.
Could someone explain how Spring does the injection of
CalendarEventRepository into CalendarEventService when the method
implementations are in separate classes.
Answer: First, and most important - all Spring beans are managed - they "live" inside a container, called "application context".
Regardless of which type of configuration you are usin (Java or xml based) you enable "Component Scanning" this helps Spring determine which resource to inject.
How spring determines which bean to inject:
Matches the names.
Matches the type.
You even use Qualifiers to narrow down the search for spring.
It finds the JpaRepository implementation somewhere and my own
custom implementation class with my custom method. Howcome their
methods are accessible through the same reference variable
calendarEventRepository?
This is more of a java core question of inheritance. Since JpaRepository, CalendarEventRepositoryCustom and CalendarEventRepository are the base classes (implementations) of your CalendarEventRepositoryImpl so any method/field that is public or protected is available to CalendarEventRepositoryImpl class.
Here you are using "Program though interface" your reference variable here is calendarEventRepository which is an interface (parent) and that is why you are able to access the fields/methods.
Bonus question: how does Spring find and instantiate the
implementation for JpaRepository?
In spring configuration (java based) you tell spring to search for JPARepositories as below:
#EnableJpaRepositories(
basePackages = {
"com.package"}
, entityManagerFactoryRef = "EntityManagerFactory", transactionManagerRef = "jpaTransactionManager"
)
This is how spring gets to know which beans to create.
I recommend reading out Spring in Action (2nd to 4th Edition) by Craig Walls.
You can as well go through the https://spring.io/docs
Annotations (Autowired, Inject, your custom) works because of AOP. Read a bit about AOP and you will know how that works.

How to add POJO to Spring context to enable injecting dependencies?

I have a class that would otherwise be a very generic POJO but I would like to inject a dependency in it because I would like to avoid passing that dependency as a (constructor) parameter:
//no managed context annotation because it's a simple POJO
public class QueuedBatch {
//however, I would like to inject the context managed bean below
#Autowired
AsyncActionQueue asyncActionQueue;
Currently, no exception is thrown at deploy time but asyncActionQueue is null at runtime so I get a NullPointer when I hit the POJO.
How can I annotate my POJO to add it to the Spring managed context so that I can inject dependencies into it? AsyncActionQueue is a singleton and I would rather not be passing it to QueuedBatch as a (constructor) parameter.
This post is similar, except that I want to add my POJO into the managed context.
As the comments suggested you have 2 ways of dealing with this
Pass the AsyncActionQueue as a parameter in the constructor of QueuedBatch. This doesnt require Spring to know anything about QueuedBatch, but enforces the dependency to be provided when an instance of QueuedBatch is created.
Annotate the QueuedBatch class with #Component. And ensure that the package which contains QueuedBatch is included in the component scan when initializing the spring context. In this way, it becomes a spring managed bean allowing AsyncActionQueue to be autowired into it. You may change the scope of QueuedBatch component based on your requirement.

Spring bean initializing dependencies with new keyword?

I have some legacy code where the class is a Spring bean defined and initialized through xml. It is a singleton with a field member which is a class dependency. There is a setter method for it, so I am assuming its supposed to be set via Spring, although I didn't find any xml defining it. There is also a get() method for the dependency, it has a null check and if its null it manually creates it outside of Spring like so
Class Test{
Dependency d;
setD(Dependency d){this.d=d;}
getD(){
if(this.d==null){
this.d = new Dependency();
}return this.d
}
}
I am trying to understand why this Spring bean is initializing a dependency outside of Spring and what are the implications if any, is this just bad/old design? or Am I not understanding something with how Spring works.
I would say it's a bad design, probably author wanted to provide fall-back for the case when D was not injected in spring. Another idea is an attempt to make D a lazy dependency. You should explore what's inside D.
Generally you can use #Required to mark the members that always should be injected. Or just use simple and nice constructor injection. If you're concerned about lazy injection, that's how Spring works by default.

Categories

Resources