Difference Between ≪Context:Annotation-Config≫ and ≪Context:Component-Scan≫

Spring MVC: difference between <context:component-scan> and <annotation-driven /> tags?

<mvc:annotation-driven /> means that you can define spring beans dependencies without actually having to specify a bunch of elements in XML or implement an interface or extend a base class. For example @Repository to tell spring that a class is a Dao without having to extend JpaDaoSupport or some other subclass of DaoSupport. Similarly @Controller tells spring that the class specified contains methods that will handle Http requests without you having to implement the Controller interface or extend a subclass that implements the controller.

When spring starts up it reads its XML configuration file and looks for <bean elements within it if it sees something like <bean class="com.example.Foo" /> and Foo was marked up with @Controller it knows that the class is a controller and treats it as such. By default, Spring assumes that all the classes it should manage are explicitly defined in the beans.XML file.

Component scanning with <context:component-scan base-package="com.mycompany.maventestwebapp" /> is telling spring that it should search the classpath for all the classes under com.mycompany.maventestweapp and look at each class to see if it has a @Controller, or @Repository, or @Service, or @Component and if it does then Spring will register the class with the bean factory as if you had typed <bean class="..." /> in the XML configuration files.

In a typical spring MVC app you will find that there are two spring configuration files, a file that configures the application context usually started with the Spring context listener.

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

And a Spring MVC configuration file usually started with the Spring dispatcher servlet. For example.

<servlet>
<servlet-name>main</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>main</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

Spring has support for hierarchical bean factories, so in the case of the Spring MVC, the dispatcher servlet context is a child of the main application context. If the servlet context was asked for a bean called "abc" it will look in the servlet context first, if it does not find it there it will look in the parent context, which is the application context.

Common beans such as data sources, JPA configuration, business services are defined in the application context while MVC specific configuration goes not the configuration file associated with the servlet.

Hope this helps.

What's the difference between <mvc:annotation-driven /> and <context:annotation-config /> in servlet?

<context:annotation-config> declares support for general annotations such as @Required, @Autowired, @PostConstruct, and so on.

<mvc:annotation-driven /> declares explicit support for annotation-driven MVC controllers (i.e. @RequestMapping, @Controller, although support for those is the default behaviour), as well as adding support for declarative validation via @Valid and message body marshalling with @RequestBody/ResponseBody.

Difference between register() and @ComponentScan

There is no difference. It are different ways of registering a bean in the Spring application context. Like you can use XML or Java based configuration. In the end it is all metadata used to construct the ApplicationContext. The one with the registerBean is considered the (sort of) functional style of registering beans. This is mainly being utilized to be able to write the Kotlin bean registration DSL (AFAIK).

Although they work differently, i.e. registering components directly as opposed to scan the classpath for beans that match the selection criteria (default is to detect @Component). The end result is the same.

For all of them a BeanDefinition is being created by Spring. The exact type of BeanDefinition will differ based on the type of configuration. For XML and Properties based it will, generally, be a RootBeanDefinition, when detected with component scanning a ScannedBeanDefinition etc. For the registerBean it will be a ClassDerivedBeanDefinition.

BeanDefinitions are the recipes on how to create beans.

All the different ways as shown below will have the same end result. An ApplicationContext with a FooService.

public class FooService { ... }

XML

<bean id="fooService" class="FooService"/>

XML with Component Scan

@Service
public class FooService { ... }
<context:component-scan />

Java Config

@Bean
public FooService fooService() {
return new FooService();
}

Java Config with Component Scan

@Service
public class FooService { ... }
@ComponentScan
public FooConfig {}

Functional Style DSL

context.registerbean("fooService", FooService.class, () -> new FooService());

Properties Based

fooService.(class)=FooService

Then use the PropertiesBeanDefinitionReader to load it (going to be deprecated or removed as of Spring 5.3).

Spring: annotation-config base-package

Using <context:component-scan base-package="com.org.pkg1"/> doesn't imply that you are

enabling annotation scanning in the whole project

It's true that <context:component-scan> also enables <context:annotation-config>. But the latter only allows the recognition of annotations in the already registered beans (no matter if they come from a scan or from XML).

Answering your question:

Is that true, and if so, can it be avoided

No.

This is the official doc for annotation-scanning:

Activates various annotations to be detected in bean classes: Spring's
@Required and @Autowired, as well as JSR 250's @PostConstruct,
@PreDestroy and @Resource (if available), JAX-WS's @WebServiceRef (if
available), EJB 3's @EJB (if available), and JPA's @PersistenceContext
and @PersistenceUnit

How to use context:component-scan base-package on Dispatcher-servlet.xml

You have to write the name of the package that include all your spring annotated class. In your case you only have a controller and its package name is Controller, so this is the correct way to use it:

<context:component-scan base-package="Controller" />

If you have more that one package that includes spring annotated class use a common path to each package and use it in component scan, for example:

Let's say you have Entities, Repositories and Controllers classes. Put them respectively in myProject.Entities, myProject.Repositories and myProject.Controllers packages and use component scan like this:

<context:component-scan base-package="myProject" />


Related Topics



Leave a reply



Submit