Which classes area loaded as bean in Spring ?? - java

I am new to Spring framework.While reading dependency injection i found out two ways to inject beans anotationbased and xml based.
In xmlBased it is quite simple that you define one bean inside your application context xml file.
eg.
<bean id="wild" class="com.javapapers.spring.ioc.Wolf" />
<bean id="zoo" class="com.javapapers.spring.ioc.Zoo">
<property name="wild" ref="wild" />
</bean>
but in Annotation based configuration we just have to write
<context:component-scan base-package="com.javapapers.spring.ioc" />
I want to know how it will load "wild" and "zoo" .
Does it means it will load all beans or only specific which is written under #Service annotation..???
I also want to know how it is loaded ..??? is all beans gets initialized when application is loaded..??
Thanks ...!!

When you use <context:component-scan base-package="com.javapapers.spring.ioc" />, spring will instanciate all classes that are in the "com.javapapers.spring.ioc" package and have one of this annotation :
#Service
#Controller
#Repository
...
And yes, all beans gets initialized when you launch your application.
You can have more info in this page : here

Beans get initialized through an ApplicationContext, which is also a BeanFactory. With an XML configuration, you would need an implementation of that interface, ClassPathXmlApplicationContext. Your application needs to create such a class, register your XML file(s), and refresh the context. When that is done, Spring will start creating your beans by reading the configuration.
When it hits the <component-scan> element, Spring will scan your declared packages for any classes annotated with #Component or its specializations. From the docs:
In Spring 2.0 and later, the #Repository annotation is a marker for
any class that fulfills the role or stereotype (also known as Data
Access Object or DAO) of a repository. Among the uses of this marker
is the automatic translation of exceptions.
Spring 2.5 introduces further stereotype annotations: #Component,
#Service, and #Controller. #Component is a generic stereotype for any
Spring-managed component. #Repository, #Service, and #Controller are
specializations of #Component for more specific use cases, for
example, in the persistence, service, and presentation layers,
respectively.
Therefore, you can annotate your component classes with #Component,
but by annotating them with #Repository, #Service, or #Controller
instead, your classes are more properly suited for processing by tools
or associating with aspects. For example, these stereotype annotations
make ideal targets for pointcuts.
Thus, if you are choosing between using #Component or #Service for
your service layer, #Service is clearly the better choice. Similarly,
as stated above, #Repository is already supported as a marker for
automatic exception translation in your persistence layer.
When it finds those classes, it will create an instance of each of them.
As for how it does this, it's a little more complicated. The overall strategy is with reflection. However, because of your configuration, Spring will sometimes generate (java or cglib) proxies instead of clear instances so that it can add behavior.
All the steps are described in detail in the official documentation.

Will be loaded all beans annotated with
#Controller
#Component
#Service
#Repository
which are inside a packages com.javapapers.spring.ioc, and its subpackages.

Related

When to use dependency Injection in spring mvc?

I am working on a Spring MVC project where I am dealing with different types of services,Repositories i.e classes annotated with #Service and #Repository. I am confused with a couple of questions:
When to use #AutoWired annotation?
I have seen various repositories using this:
CourseRepository crepo=new CourseRepository();
and I have seen this also
#AutoWired
private CourseRepository crepo;
Which one of the above options should be used to get an instance of
repository in Service class?
Can I use #AutoWired for classes which are not annotated with #Repository or
#Service?
I am a beginner in this java world.Any help will be highly appreciated.
Thanks
You use new for data objects, which in most modern architectures are passive (they're not "active records"). Everything else is a service object, and you should inject those. (The one place that you do use new is with an #Bean method, which is a "factory" that creates the service object; in this case you normally pass the dependencies as method parameters.)
Note that it is recommended to use constructor injection instead of field injection; it makes your code easier to test, and it eliminates the possibility of certain kinds of errors. In fact, if using constructor injection, it's not required to have any Spring annotations in your service classes at all; beans can be registered using #Import instructions or #Bean methods on a configuration class.
You should #Autowire the dependencies instead of instantiating it yourself. Doing so, service and repo layer will be loosely coupled. Moreover, a mock repository can be easily injected in service's JUnit test class if dependency is autowired. To conclude, use below:
#Autowired
private CourseRepository crepo;
A class not annotated with any of below stereotype annotations will not be in Spring's IoC (Inversion of Control) container. Hence, no point in autowiring in a class that is not annotated with any of below annotations.
#Component, #Controller, #Service, #Repository
Dependency injection means that the framework is the one who handles the classes instantiation and the object of that class is going to be injected (thanks to #Autowired annotation) in the class where you need it. In other words, you do not need to instantiate service and repository classes by yourself using new operator, you just need to tell the framework that those classes need to be injected and that's why you use #Autowired annotation.

Can we use #autowired on an entity object in spring?

I have a entity class called Customer, I am using this entity object in another class to set the data. When I use this object below like
#Autowired
Customer customer
Spring is complaining that please configure the bean in your classes.
Can we use auto wiring with entity objects?
You can only autowire only those beans whose life-cycle are managed by Spring IoC container.
These beans are defined in xml form with </bean> tag, or with some special annotations like #Bean, #Component, #Service, #Repository etc.
On the other hand,
in simple terms, entities are some java objects that you will need to create, update by yourself according to your business logic and save/update/remove them in/from DB. Their life-cycle cannot be managed by Spring IoC container.
So, you should never feel like you need to autowire an entity if you are doing it right!
In fact, Spring support #Autowire only for Spring Beans. A java class becomes Spring Bean only when it is created by Spring, otherwise it is not.
A workaround might be to annotate your class with #Configurable but you would have to use AspectJ
Please look in the Spring documentations on how to use #Configurable
Also, I wonder why you would autowire an entity class ?
I would warn you not to mix Spring Bean and JPA entities in one class/usecase because:
Spring Beans are instantiated and managed by Spring
Entities are managed by JPA provider
If you mean JPAs #Entity-annotation, Spring is simply telling you, that there isn't a bean in its context.
On startup/runtime classes in the application will be scanned and each class annotated with spring annotations like #Component, #Service etc. will be instantiated as beans and put into a global context (Spring applicationcontext).
This context is then used to lookup and inject those beans into other beans when #Autowired is found during scanning.
Opposed to this, #Entity is used during the creation of the Persistence-Context of JPA (as far as I remember) which isn't aware of Spring and it's context.
Most of the solutions to make both contexts aware of each other a mostly a little bit hacky.

Does annotating a repository interface as #Component have any cons?

I have this interface:
public interface liteRepository extends CrudRepository<liteEntity, Long>, JpaSpecificationExecutor<liteEntity> {...}
It works, all is well.
However, intellij does not register this class as a spring component. If I annotate this interface with #Component, then intellij recognizes this as a spring bean and I can #Autowire this repository in my integration tests.
My code still works after annotation, but I'm not confident that I am not messing with things that I should not be messing with.
Question:
Is there any harm in adding the #Component annotation to this interface?
The only thing that #Component annotation means is that the class is eligible for becoming a Spring bean during Spring's component-scan.
So, if you want it to be a Spring bean and you did not define it as a Spring bean anywhere else, you can safely add the #Component annotation.
Of course, this will only work if you have the actual component scan configured somewhere(for, example <context:component-scan base-package="..."> in some Spring config file), which I am assuming you already heave, since the bean is properly getting autowired after you add the annotation.

<context:componentscan> how does it work?

Can "context: componentscan" scan custom annotations? If so, where does it store the scanned beans in application context after scanning? How can I access the results?
We register beans or components in XML configuration file. So Spring can detect those beans, components. Spring also support to auto scan, detect and instantiate beans from pre-defined project package via the annotation. So we don't have to declare in the configuration anymore. For example:
<context:component-scan base-package="abc.controller, abc.service" />
in your Controller or Service, you just have to add annotation like:
#Controller
public class SampleController
#Service
public class SampleService
Spring will know that your SampleController and SamplerService and you can use it as you want.
Some detail here: http://docs.spring.io/spring-javaconfig/docs/1.0.0.M4/reference/html/ch06s02.html

Turn off Autowiring for Spring #Service

I have a custom annotation that is declared as a Spring managed Service:
#Service
public #interface MyServiceAnnotation {
// my service url
String url();
}
The above declaration enables my services to be autowired as Spring Managed beans.
#MyServiceAnnotation(url="/path/serviceLocation")
public class SomeService {
doWork();
}
However, there are certain services that have their bean definitions in an applicationContext.xml. Adding the #MyServiceAnnotation to such beans makes them both Autowiring enabled, as well as inject dependecy through the xml file.
Due to issues related to legacy code, I don't want to remove the xml bean definitions and make them all autowired.
So, is there a way in which I could turn off autowiring in this case, and still use #MyServiceAnnotation? Ideally I would like to have the #Service annotation on MyServiceAnnotation, the existing services would still use the #MyServiceAnnotation but would get their dependencies injected based on the xml. All the new services would be autowired without the xml bean definitions.
One possible approach is to create NonSpringManagedMyServiceAnnotation that is same as MyServiceAnnotation, but without the #Service annotation on it. The downside of this is that I'd have to duplicate rest of the code from MyServiceAnnotation, which I don't want to.
This is one approach, may not be that optimal though. I am assuming you would have specified a component-scan tag in your xml to scan the classes having the Spring stereotype annotations, these tags support a exclude-filter sub-tag to ignore specific patterns. If the files that you specify follow a specific pattern(specific packages, specific names etc) then you may simply be able to specify this sub-tag to ignore classes holding your annotation.
<context:component-scan base-package="mypackage">
<context:exclude-filter type="regex" expression=".*ToBeIgnoredNaming"/>
</context:component-scan>
I think you should try to maintain separation of concern.
Adding #Service on your annotation makes it a de facto Spring service : since this is not the behavior you want, you may simply have a simple #MyAnnotation (with url property) on each services (legacy and new).
Then you add Spring's #Service annotation on each new service to enable bean registration by annotation.

Categories