1. 程式人生 > >context:annotation-config與mvc:annotation-driven和context:component-scan詳解

context:annotation-config與mvc:annotation-driven和context:component-scan詳解

現在常用框架中SpringMVC.xml配置是:

<mvc:annotation-driven/>和<context:component-scan>

那麼<context:annotation-config/>呢?

【1】 <context:annotation-config/>

  • 如果你想使用@Autowired註解,那麼就必須事先在 Spring 容器中宣告 AutowiredAnnotationBeanPostProcessor Bean。

這裡寫圖片描述

  • 如果想使用@Resource 、@PostConstruct、@PreDestroy等註解就必須宣告CommonAnnotationBeanPostProcessor。

  • 如果想使用@PersistenceContext註解,就必須宣告PersistenceAnnotationBeanPostProcessor的Bean。

    JPA中你將會遇到這個註解。

  • 如果想使用 @Required的註解,就必須宣告RequiredAnnotationBeanPostProcessor的Bean

<context:annotation-config/>隱式地向 Spring容器註冊這4個BeanPostProcessor:

AutowiredAnnotationBeanPostProcessor、
RequiredAnnotationBeanPostProcessor、
CommonAnnotationBeanPostProcessor以及
PersistenceAnnotationBeanPostProcessor

<context:annotation- config/>是用來使上述註解起作用的,也就是說啟用已經在application context中註冊的bean。

之所以這樣說是因為<context:annotation-config />僅能夠在已經在已經註冊過的bean上面起作用。

對於沒有在spring容器中註冊的bean,它並不能執行任何操作,也就是說如果你並沒有spring容器中註冊過bean(spring配置檔案中配置bean就是註冊(也就是說spring中不存在你想使用的bean)),那麼上述的那些註解並不會在你未註冊過的bean中起作用。

這裡可能會有疑問,比如明明註冊了AutowiredAnnotationBeanPostProcessor

bean,那麼豈不是可以隨意使用@Autowired註解?

這裡需要注意的是,@Autowired註解在你使用的時候自動注入的前提是,spring容器中已經有了該bean!

那麼你可以隨意在某個controller或者service使用該註解。並非該註解可以無中生有立即造一個bean給你使用!!

【2】<context:component-scan>

<context:component-scan>做了<context:annotation-config>要做的事情,還額外支援@Component,@Repository,@Service,@Controller @RestController,@ControllerAdvice, and @Configuration註解。

並且<context:component-scan>掃描base-package並且在application context中註冊掃描到的使用註解注入的beans。

這裡著重注意第二段話,<context:component-scan>該註解可以掃描並註冊你使用註解諸如@controller @service @component..的bean!!!

也就是說,你不用xml中顯示配置,需要的時候儘管用@Resource或者@Autowired來自動注入!!!

所以配置<context:component-scan>就不需要配置<context:annotation- config/>

該標籤的XSD說明見下圖:

這裡寫圖片描述

【3】 <mvc:annotation-driven/>

至於該項看字首就應該知道是springmvc所需要的註解。

我們找到對應的實現類是:org.springframework.web.servlet.config.AnnotationDrivenBeanDefinitionParser

原始碼示例如下:

/**
 * A {@link BeanDefinitionParser} that provides the configuration for the
 * {@code <annotation-driven/>} MVC namespace element.
 *
 * <p>This class registers the following {@link HandlerMapping}s:</p>
 * <ul>
 * <li>{@link RequestMappingHandlerMapping}
 * ordered at 0 for mapping requests to annotated controller methods.
 * <li>{@link BeanNameUrlHandlerMapping}
 * ordered at 2 to map URL paths to controller bean names.
 * </ul>
 *
 * <p><strong>Note:</strong> Additional HandlerMappings may be registered
 * as a result of using the {@code <view-controller>} or the
 * {@code <resources>} MVC namespace elements.
 *
 * <p>This class registers the following {@link HandlerAdapter}s:
 * <ul>
 * <li>{@link RequestMappingHandlerAdapter}
 * for processing requests with annotated controller methods.
 * <li>{@link HttpRequestHandlerAdapter}
 * for processing requests with {@link HttpRequestHandler}s.
 * <li>{@link SimpleControllerHandlerAdapter}
 * for processing requests with interface-based {@link Controller}s.
 * </ul>
 *
 * <p>This class registers the following {@link HandlerExceptionResolver}s:
 * <ul>
 * <li>{@link ExceptionHandlerExceptionResolver} for handling exceptions
 * through @{@link ExceptionHandler} methods.
 * <li>{@link ResponseStatusExceptionResolver} for exceptions annotated
 * with @{@link ResponseStatus}.
 * <li>{@link DefaultHandlerExceptionResolver} for resolving known Spring
 * exception types
 * </ul>
 *
 * <p>This class registers an {@link org.springframework.util.AntPathMatcher}
 * and a {@link org.springframework.web.util.UrlPathHelper} to be used by:
 * <ul>
 * <li>the {@link RequestMappingHandlerMapping},
 * <li>the {@link HandlerMapping} for ViewControllers
 * <li>and the {@link HandlerMapping} for serving resources
 * </ul>
 * Note that those beans can be configured by using the {@code path-matching} MVC namespace element.
 *
 * <p>Both the {@link RequestMappingHandlerAdapter} and the
 * {@link ExceptionHandlerExceptionResolver} are configured with instances of
 * the following by default:
 * <ul>
 * <li>A {@link ContentNegotiationManager}
 * <li>A {@link DefaultFormattingConversionService}
 * <li>A {@link org.springframework.validation.beanvalidation.LocalValidatorFactoryBean}
 * if a JSR-303 implementation is available on the classpath
 * <li>A range of {@link HttpMessageConverter}s depending on what 3rd party
 * libraries are available on the classpath.
 * </ul>
 *
 * @author Keith Donald
 * @author Juergen Hoeller
 * @author Arjen Poutsma
 * @author Rossen Stoyanchev
 * @author Brian Clozel
 * @author Agim Emruli
 * @since 3.0
 */
class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {

	public static final String HANDLER_MAPPING_BEAN_NAME = RequestMappingHandlerMapping.class.getName();

	public static final String HANDLER_ADAPTER_BEAN_NAME = RequestMappingHandlerAdapter.class.getName();

	public static final String CONTENT_NEGOTIATION_MANAGER_BEAN_NAME = "mvcContentNegotiationManager";

通過閱讀類註釋文件,我們發現這個類主要是用來向工廠中註冊了

  • RequestMappingHandlerMapping
  • BeanNameUrlHandlerMapping
  • RequestMappingHandlerAdapter
  • HttpRequestHandlerAdapter
  • SimpleControllerHandlerAdapter
  • ExceptionHandlerExceptionResolver
  • ResponseStatusExceptionResolver
  • DefaultHandlerExceptionResolver

上面幾個Bean例項。這幾個類都是用來做什麼的呢?

前兩個是HandlerMapping介面的實現類,用來處理請求對映的。

  • 其中第一個是處理@RequestMapping註解的。

中間三個是用來處理請求的。具體點說就是確定呼叫哪個controller的哪個方法來處理當前請求。

  • 第一個處理@Controller註解的處理器,支援自定義方法引數和返回值(很酷)。
  • 第二個是處理繼承HttpRequestHandler的處理器。
  • 第三個處理繼承自Controller介面的處理器。

後面三個是用來處理異常的解析器。

另外還將提供以下支援:

① 支援使用ConversionService例項對錶單引數進行型別轉換;
② 支援使用@NumberFormatannotation、@DateTimeFormat註解完成資料型別的格式化;
③ 支援使用@Valid註解對Java bean例項進行JSR 303驗證;
④ 支援使用@RequestBody和@ResponseBody註解

參考<mvc:annotation-driven/>標籤詳解:部落格地址