欢迎来到刘认真的博客

It's not me that's wrong. It's the whole world

Spring < context:annotation-config> 、< context:component-scan>、< mvc:annotation-driven />注解配置

Spring 中在使用注解(Annotation)会涉及到< context:annotation-config> 和 < context:component-scan>配置,下面就对这两个配置进行诠释。

1.context:annotation-config

< context:annotation-config> 是用于激活那些已经在spring容器里注册过的bean上面的注解,也就是显示的向Spring注册

1.AutowiredAnnotationBeanPostProcessor 

2.CommonAnnotationBeanPostProcessor

3.PersistenceAnnotationBeanPostProcessor

4.RequiredAnnotationBeanPostProcessor

 

这四个Processor,注册这4个BeanPostProcessor的作用,就是为了你的系统能够识别相应的注解。BeanPostProcessor就是处理注解的处理器。

 

  • 比如我们要使用@Autowired注解,那么就必须事先在 Spring 容器中声明 AutowiredAnnotationBeanPostProcessor Bean。传统声明方式如下
<bean class="org.springframework.beans.factory.annotation. AutowiredAnnotationBeanPostProcessor "/>
  • 如果想使用@ Resource 、@ PostConstruct、@ PreDestroy等注解就必须声明CommonAnnotationBeanPostProcessor。传统声明方式如下
<bean class="org.springframework.beans.factory.annotation. CommonAnnotationBeanPostProcessor"/>
  • 如果想使用@PersistenceContext注解,就必须声明PersistenceAnnotationBeanPostProcessor的Bean。
<bean class="org.springframework.beans.factory.annotation.PersistenceAnnotationBeanPostProcessor"/>
  • 如果想使用 @Required的注解,就必须声明RequiredAnnotationBeanPostProcessor的Bean。同样,传统的声明方式如下:
<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/> 

一般来说,像@ Resource 、@ PostConstruct、@Antowired这些注解在自动注入还是比较常用,所以如果总是需要按照传统的方式一条一条配置显得有些繁琐和没有必要,

 

于是spring给我们提供< context:annotation-config/>的简化配置方式,自动帮你完成声明。

 

思考1:假如我们要使用如@Component、@Controller、@Service等这些注解,使用能否激活这些注解呢?

答案:单纯使用< context:annotation-config/>对上面这些注解无效,不能激活!

 

2.context:component-scan

 

Spring 给我提供了context:component-scan配置,如下

<context:component-scan base-package=”XX.XX”/> 

该配置项其实也包含了自动注入上述processor的功能

因此当使用 < context:component-scan/> 后,

就可以将 < context:annotation-config/> 移除了。 

通过对base-package配置,就可以把controller包下 service包下 dao包下的注解全部扫描到了! 

如果配置了<context:component-scan>那么<context:annotation-config/>标签就可以不用再xml中配置了,因为前者包含了后者。另外<context:annotation-config/>还提供了两个子标签

  1. <context:include-filter>

  2. <context:exclude-filter>

  在说明这两个子标签前,先说一下<context:component-scan>有一个use-default-filters属性,改属性默认为true,这就意味着会扫描指定包下的全部的标有注解的类,并注册成bean.所以如果仅仅是在配置文件中这么写<context:component-scan base-package="tv.huan.weisp.web"/>Use-default-filters此时为true那么会对base-package包或者子包下的所有的进行java类进行扫描,并把匹配的java类注册成bean。

  可以发现这种扫描的粒度有点太大,如果你只想扫描指定包下面的Controller,该怎么办?此时子标签<context:incluce-filter>就起到了勇武之地。如下所示

  <context:component-scan base-package=" controller">  

    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>   

  </context:component-scan>  

  这样就会只扫描base-package指定下的有@Controller下的java类,并注册成bean。但是因为use-dafault-filters在上面并没有指定,默认就为true,所以当把上面的配置改成如下所示的时候,就会产生与你期望相悖的结果(注意base-package包值得变化)

  <context:component-scan base-package="web ">  

    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>   

  </context:component-scan>  

  此时,spring不仅扫描了@Controller,还扫描了指定包所在的子包service包下注解@Service的java类.此时指定的include-filter没有起到作用,只要把use-default-filters设置成false就可以了。这样就可以避免在base-packeage配置多个包名这种不是很优雅的方法来解决这个问题了。

另外在我参与的项目中可以发现在base-package指定的包中有的子包是不含有注解了,所以不用扫描,此时可以指定<context:exclude-filter>来进行过滤,说明此包不需要被扫描。综合以上说明

  Use-dafault-filters=”false”的情况下:<context:exclude-filter>指定的不扫描,<context:include-filter>指定的扫描

 

 

总结:

(1)< context:annotation-config />不仅能够在已经在已经注册过的bean上面起作用。

    对于没有在spring容器中注册的bean,它并不能执行任何操作。 
(2)除了具有的功能之外,还具有自动将带有@component,@service,@Repository等注解的对象注册到spring容器中的功能。 

思考2:如果同时使用这两个配置会不会出现重复注入的情况呢?

答案:因为< context:annotation-config />和 < context:component-scan>同时存在的时候,前者会被忽略。如@autowire,@resource等注入注解只会被注入一次!

 

 

3.< mvc:annotation-driven/>

<mvc:annotation-driven>会自动注册RequestMappingHandlerMapping与RequestMappingHandlerAdapter两个Bean,这是Spring MVC为@Controller分发请求所必需的

 <!-- 注册了url处理映射 控制器 适配器 -->
    <mvc:annotation-driven></mvc:annotation-driven>

    <!-- 注解注入 -->
    <context:component-scan base-package="com.etc.controller"></context:component-scan>

< mvc:annotation-driven/>从 标签的shecma就能看出来,mvc,主要就是为了Spring MVC来用的,提供Controller请求转发,json自动转换等功能。相比上面的两个shecma是context开头,那么主要是解决spring容器的一些注解。

< mvc:annotation-driven /> 是一种简写形式,完全可以手动配置替代这种简写形式,简写形式可以让初学都快速应用默认配置方案。 会自动注册DefaultAnnotationHandlerMapping与AnnotationMethodHandlerAdapter 两个bean,是spring MVC为@Controllers分发请求所必须的。 
并提供了:数据绑定支持,@NumberFormatannotation支持,@DateTimeFormat支持,@Valid支持,读写XML的支持(JAXB),读写JSON的支持(Jackson)。

在实际开发使用SpringMVC开启这个配置,否则会出现一些功能不能正常使用!

 

 

 

web.xml配置

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <web-app xmlns="http://java.sun.com/xml/ns/javaee"
 3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4          xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
 5          version="3.0">
 6   <display-name>Archetype Created Web Application</display-name>
 7 
 8   <!-- 配置Servlet -->
 9   <servlet>
10     <servlet-name>springmvc</servlet-name>
11     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
12     <init-param>
13       <param-name>contextConfigLocation</param-name>
14       <param-value>classpath:springmvc.xml</param-value>
15     </init-param>
16     <load-on-startup>1</load-on-startup>
17   </servlet>
18   <servlet-mapping>
19     <servlet-name>springmvc</servlet-name>
20     <url-pattern>/</url-pattern>
21   </servlet-mapping>
22 
23   <!-- spring -->
24   <!-- spring监听器 -->
25   <listener>
26     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
27   </listener>
28 
29   <!-- 加载applicationContext.xml配置文件 -->
30   <context-param>
31     <param-name>contextConfigLocation</param-name>
32     <param-value>classpath:applicationContext.xml</param-value>
33   </context-param>
34 
35 </web-app>

 

springmvc.xml  (Springmvc配置)

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
 4        xmlns:context="http://www.springframework.org/schema/context"
 5        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
 6     <!-- 注册了url处理映射 控制器 适配器 -->
 7     <mvc:annotation-driven></mvc:annotation-driven>
 8 
 9     <!-- 注解注入 -->
10     <context:component-scan base-package="com.etc.controller"></context:component-scan>
11 
12     <!-- 逻辑视图与物理视图的映射 -->
13     <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
14         <property name="prefix" value="/WEB-INF/jsp/"></property>
15         <property name="suffix" value=".jsp"></property>
16     </bean>
17 </beans>

 

applicationContext.xml  (Spring配置)

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4        xmlns:context="http://www.springframework.org/schema/context"
 5        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
 6 
 7 
 8     <!--<context:annotation-config></context:annotation-config>-->
 9 
10     <!-- 注解注入-->
11     <context:component-scan base-package="com">
12         <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"></context:exclude-filter>
13     </context:component-scan>
14 </beans>

 

posted @ 2019-07-25 15:35  刘认真  阅读(403)  评论(0编辑  收藏  举报