Spring Annotaion Support detailed introduction and simple example, annotaionsupport

Source: Internet
Author: User

Spring Annotaion Support detailed introduction and simple example, annotaionsupport

Recently, I am reading the spring official website. I found the BeanPostProcessor interface when I look at Spring container extension points when I look at Spring IOC. The following is a detailed description of the official website:

BeanPostProcessor interface defines the callback method, you can provide your own (or override the default container) instantiation logic, dependency parsing logic, and so on. If you want to configure and initialize a bean after some custom logic Spring containers are instantiated, you can insert one or more BeanPostProcessor implementations.

You can configure multiple BeanPostProcessor instances. You can control the order of BeanPostProcessors by setting attributes. You can set this attribute to only implement the command interface of BeanPostProcessor. If you write your own BeanPostProcessor, you should also consider implementing the theOrdered interface. For more information, see BeanPostProcessor's Javadoc and command interface.

BeanPostProcessor has two methods: postProcessBeforeInitialization and postProcessAfterInitialization. if an object implements this interface, it will be before the container initializes the init method (like the afterPropertiesSet () of InitializingBean and other public init methods) or execute a callback after Spring bean initialization.

Classes that implement the BeanPostProcessor interface are treated differently by containers. All BeanPostProcessors directly reference the instantiated bean at startup as the startup phase of the special ApplicationContext. Next, all BeanPostProcessorsare registration classification methods apply to all further bean containers. Because the implementation of AOP auto-proxying aBeanPostProcessor itself, whether it is BeanPostProcessors or beas, they are eligible to get the auto-proxying direct reference, so there is no way to knit in.

Classes that implement the BeanPostProcessor interface are treated differently by containers. All BeanPostProcessors directly reference the instantiated bean at startup as the startup phase of the special ApplicationContext. Next, all BeanPostProcessorsare registration classification methods apply to all further bean containers. Because the implementation of AOP auto-proxying aBeanPostProcessor itself, whether it is BeanPostProcessors or beas, they are eligible to get the auto-proxying direct reference, so there is no way to knit in.

BeanPostProcessor using callback APIs or annotations and custom implementation is a common SpringIoC container extension. RequiredAnnotationBeanPostProcessor is an example of Spring-a Spring distribution that implements BeanPostProcessor. Ensure that a (arbitrary) annotation (configuration) on the bean attribute is dependent on the injection value.

You said that I was a little excited when I saw one of the above two major features of AOP Spring. The next Spring Annotation is usually implemented using this interface. Now I can't help but want to see what the RequiredAnnotationBeanPostProcessor class is doing. Source Code directly

Spring Annotation Support/** Copyright 2002-2013 the original author or authors. ** Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file License t in compliance with the License. * You may obtain a copy of the License ** http://www.apache.org/licenses/LICENSE-2.0 ** Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "as is" BASIS, * without warranties or conditions of any kind, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package org. springframework. beans. factory. annotation; import java. beans. property Descriptor; import java. lang. annotation. annotation; import java. lang. reflect. method; import java. util. arrayList; import java. util. collections; import java. util. list; import java. util. set; import java. util. concurrent. concurrentHashMap; import org. springframework. beans. beansException; import org. springframework. beans. propertyValues; import org. springframework. beans. factory. beanFactory; import org. sp Ringframework. beans. factory. beanFactoryAware; import org. springframework. beans. factory. beanInitializationException; import org. springframework. beans. factory. config. beanDefinition; import org. springframework. beans. factory. config. configurableListableBeanFactory; import org. springframework. beans. factory. config. instantiationAwareBeanPostProcessorAdapter; import org. springframework. beans. factory. suppor T. mergedBeanDefinitionPostProcessor; import org. springframework. beans. factory. support. rootBeanDefinition; import org. springframework. core. conventions; import org. springframework. core. ordered; import org. springframework. core. priorityOrdered; import org. springframework. core. annotation. annotationUtils; import org. springframework. util. assert;/*** {@ link org. springframework. beans. factory. config. beanP OstProcessor} implementation * that enforces required JavaBean properties to have been configured. * force checks if the Required properties of the JavaBean are configured * Required bean properties are detected through a Java 5 annotation: * Required bean properties are automatically detected through annotation in Java 5 * by default, spring's {@ link Required} annotation. ** <p> The motivation for the existence of this BeanPostProcessor is to allow * BeanPostProcessor indicates that * Developers to annotate the setter properties of their own classes with an * arbitrary JDK 1.5 annotation to indicate that the container must check * for the configuration of a dependency injected value. this neatly pushes * The developer comments the setter attribute with an arbitrary JDK 1.5 annotation of their own class, indicating that the container must check the configuration value of dependency injection. * Responsibility for such checking onto the container (where it arguably belongs), * This cleverly gives the check responsibility to the Spring container (it should belong) * and obviates the need (<B> in part </B>) for a developer to code a method that * simply checks that all required properties have actually been set. * This eliminates the need for developers to write a simple method to check whether the required properties have been set. * <p> Please note that an 'init 'method may still need implemented (and may * Still be desirable), because all that this class does is enforce that a * Please note that the initialization method must still be implemented (and still desirable) * 'requestred' property has actually been configured with a value. it does * because all this Class enforces whether the 'requestred' attribute has been configured with a value * <B> not </B> check anything else... in particle, it does not check that a * it does not check the actual thing, especially, it does not check whether the configured value is null * configured value is not {@ code null }. ** <p> Note: A default Re QuiredAnnotationBeanPostProcessor will be registered * by the "context: annotation-config" and "context: component-scan" XML tags. * When you use "context: annotation-config" or "context: the component-scan "XML tag registers RequiredAnnotationBeanPostProcessor * Remove or turn off the default annotation configuration there if you intend * to specify a custom RequiredAnnotationBeanPostProcessor bean definition by default. * If you want to specify The custom RequiredAnnotationBeanPostProcessor bean implementation can remove or disable the default annotation configuration ** @ author Rob Harrop * @ author Juergen Hoeller * @ since 2.0 * @ see # setRequiredAnnotationType * @ see Required * /public class RequiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter implements MergedBeanDefinitionPostProcessor, priorityOrdered, BeanFactoryAware {/*** Bean definition attribute t Hat may indicate whether a given bean is supposed * to be skipped when refreshing this post-processor's required property check. * The attributes defined by this bean indicate the required attributes of the bean provided by check when post-processor is executed * @ see # shouldSkip */public static final String SKIP_REQUIRED_CHECK_ATTRIBUTE = Conventions. getQualifiedAttributeName (RequiredAnnotationBeanPostProcessor. class, "skipRequiredCheck"); private Class <? Extends Annotation> requiredAnnotationType = Required. class; private int order = Ordered. LOWEST_PRECEDENCE-1; private incluablelistablebeanfactory beanFactory;/*** Cache for validated bean names, skipping re-validation for the same bean * Cache the name of the bean that has been confirmed, skip the same bean */private final Set <String> validatedBeanNames = Collections. newSetFromMap (new ConcurrentHashMap <String, Boolean> (64 ));/*** Set the 'requestred' annotation type, to be used on bean property * setter methods. * set The required annotation type and use the setter method of bean properties * <p> The default Required annotation type is the Spring-provided * {@ link required} annotation. * The default required annotation type is Spring-provided annotation * <p> This setter property exists so that developers can provide their own * (non-Spring-specific) annotation type to indicate that a property va Lue * is required. * This property is set here to allow developers to provide their own defined annotaion type to indicate that this property value is required */public void setRequiredAnnotationType (Class <? Extends Annotation> requiredAnnotationType) {Assert. notNull (requiredAnnotationType, "'requiredannotationtype 'must not be null"); this. requiredAnnotationType = requiredAnnotationType;}/*** Return the 'requestred' annotation type. */protected Class <? Extends Annotation> getRequiredAnnotationType () {return this. requiredAnnotationType;} @ Override public void setBeanFactory (BeanFactory beanFactory) {if (beanFactory instanceof ConfigurableListableBeanFactory) {this. beanFactory = (ConfigurableListableBeanFactory) beanFactory;} public void setOrder (int order) {this. order = order ;}@ Override public int getOrder () {return this. order;} @ Over Ride public void postProcessMergedBeanDefinition (RootBeanDefinition beanDefinition, Class <?> BeanType, String beanName) {}@ Override public PropertyValues postProcessPropertyValues (PropertyValues pvs, PropertyDescriptor [] pds, Object bean, String beanName) throws BeansException {// use the cache to determine whether the bean is validated if (! This. validatedBeanNames. contains (beanName) {// do not skip if (! ShouldSkip (this. beanFactory, beanName) {List <String> invalidProperties = new ArrayList <String> (); for (PropertyDescriptor pd: pds) {// if it is marked as required and this property has no attribute value (or other processing entries) if (isRequiredProperty (pd )&&! Pvs. contains (pd. getName () {// Add this attribute invalidProperties. add (pd. getName () ;}}// <span style = "color: # ff0000;"> If invalid properties are not empty. Throw an exception </span> if (! InvalidProperties. isEmpty () {throw new BeanInitializationException (buildExceptionMessage (invalidProperties, beanName) ;}// Add the bean name to be verified to this. validatedBeanNames. add (beanName);} return pvs;}/*** Check whether the given bean definition is not subject to the annotation-based * required property check as published med by this post-processor. * The post-processor (post-processing program) is used to check whether the defined bean is annotated Based on the che. Control of properties required by ck * <p> The default implementations check for the presence of the * {@ link # SKIP_REQUIRED_CHECK_ATTRIBUTE} attribute in the bean definition, if any. * This default check implementation has the bean defined by SKIP_REQUIRED_CHECK_ATTRIBUTE. * It also suggests skipping in case of a bean definition with a "factory-bean" * reference set, assuming that instance-based factories pre-populate the bean. * It is also recommended to skip this step if this bean defines "Factory-bean" reference, suppose that the instance-based factories pre-configured bean * @ param beanFactory the BeanFactory to check against * @ param beanName the name of the bean to check against * @ return {@ code true} skip the bean; {@ code false} to process it * if true is returned, skip this bean. If false is returned, process it */protected boolean shouldSkip (descriablelistablebeanfactory beanFactory, String beanName) {// if this beanFacotry is empty or the bean factory does not contain a bean definition with a given name. Returns false if (beanFactory = null |! BeanFactory. containsBeanDefinition (beanName) {return false;} BeanDefinition beanDefinition = beanFactory. getBeanDefinition (beanName); // judge the factory beanName of this bean. if it is not null, true if (beanDefinition is returned. getFactoryBeanName ()! = Null) {return true;} Object value = beanDefinition. getAttribute (SKIP_REQUIRED_CHECK_ATTRIBUTE); return (value! = Null & (Boolean. TRUE. equals (value) | Boolean. valueOf (value. toString ();}/*** Is the supplied property required to have a value (that is, to be dependency-injected )? * Is there a value for the required propery provided (this is a dependency injection )? * <P> This implementation looks for the existence of a * {@ link # setRequiredAnnotationType "required" annotation} * on the supplied {@ link PropertyDescriptor property }. * This implementation is to find the ProertyDescriptor provided is to provide the "required" annotation * @ param propertyDescriptor the target PropertyDescriptor (never {@ code null }) * @ return {@ code true} if the supplied property has been marked as being required; * returns true if the provided property Marked as required </span> * {@ code false} if not, or if the supplied property does not have a setter method * returns false, if it is not marked as required or the provided property does not have a setter Method */protected boolean isRequiredProperty (PropertyDescriptor propertyDescriptor) {Method setter = propertyDescriptor. getWriteMethod (); return (setter! = Null & AnnotationUtils. getAnnotation (setter, getRequiredAnnotationType ())! = Null);}/*** Build an exception message for the given list of invalid properties. * use the exception properties to construct the exception information * @ param invalidProperties the list of names of invalid properties * @ param beanName the name of the bean * @ return the exception message */private string buildExceptionMessage (List <String> invalidProperties, string beanName) {int size = invalidProperties. size (); StringBuilder sb = new StringBuilder (); sb. append (size = 1? "Property": "Properties"); for (int I = 0; I <size; I ++) {String propertyName = invalidProperties. get (I); if (I> 0) {if (I = (size-1) {sb. append ("and");} else {sb. append (",") ;}} sb. append ("'"). append (propertyName ). append ("'");} sb. append (size = 1? "Is": "are"); sb. append ("required for bean '"). append (beanName ). append ("'"); return sb. toString ();}}

As shown in the code above. We can draw the following conclusions:

The above has implemented Spring for the org. springframework. beans. factory. annotation. Required label. This is just a small example. However, we can see from the package structure below Spring that this is a very common implementation of Spring for its own Annotation:

From the above example, I can see that Spring is an implementation of Annotaion. This document does not describe how the Exception Message is transmitted. However, this is not the scope of this article. If you are interested, you can check it yourself.

Thank you for reading this article. I hope it will help you. Thank you for your support for this site!

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.