Spring Annotation processing:how It works--turn

Source: Internet
Author: User

It's so hard to find.

Original address: Https://dzone.com/articles/spring-annotation-processing-how-it-works

If you see an annotation, there must is some code somewhere to process it.

One of the things I emphasize when I teach Java classes was the fact that annotations was inert. In other words, they is just markers, potentially with some properties, but with no behavior of their own. So whenever you see an annotation on a piece of Java code, it means that there must is some other Java code somewhere that Looks for this annotation and contains the real intelligence to doing something useful with it.

Unfortunately, the issue with this line of reasoning are the it can be pretty difficult to identify exactly which Piece of code is processing the annotation, particularly if it is inside a library. and code that processes annotations can is confusing, as it uses reflection and have to is written in a very generic the. So I thought it would is worthwhile to look at a example that's doing well to see how it works.

I ' m going to walk through the from the InitDestroyAnnotationBeanPostProcessor Spring framework to show how it works. I ' ve chosen this one because it's relatively simple as these things go, it does something that's relatively easy to Explai N, and I happened to need it recently for some work I was doing.

Spring Bean Post Processing

First I would like-to-start with a little explanation of the purpose of Spring. One of the things the Spring framework does is "dependency injection". This changes the typically tie together modules within a piece of code. For example, let's say that we've written some application logic that needs a connection to the database. Rather than coding into the application logic the specific class that provides that connection, we can just express it as A dependency, either in the constructor or a setter method:

MyApplication {
    Data
    ...
    SetData (data) {
        This.   data;
    }
    ...
}

Of course, we can do this dependency injection ourselves, and we might want to if we ' re writing a simple library and want To avoid adding a dependency to Spring. But if we ' re wiring together a complicated application, Spring can be very handy.

Since there ' s no magic, if we ' re going to let Spring inject these dependencies for us, there ' s going to be a tradeoff. Spring is going to has "know" about the dependencies and about the classes and objects in our application. The the-the-prefers to handle-is-allowing spring to do the instantiation of the objects; Then it can keep track of them in a big data structure called the application context.

Post Processing and initialization

And here's where  initdestroybeanpostprocessor  comes in. If Spring was going to handle instantiation, there was going to being cases where some "extra work" needs-be-done after tha T instantiation is do, but before the application can start its real processing. One piece of "extra work" that needs doing was calling objects to tell them when they ' ve been fully set up, so they can do Any extra initialization they need. This was especially important if we use "setter" injection, as above, where dependencies was injected by Calling setxxx ()  methods, because those dependencies won ' t be available at the time the object ' s constructor is Calle D. So Spring needs-to-allow users to specify the name of some method that should is called after the object has been Initi Alized.

Spring have always supported using XML to define the objects that Spring should instantiate, and in that case there was An ' Init-method attribute that could is used to specify the method. Obviously in this case it still needed reflection to actually look up and call the method. But since annotations became available in Java 5, Spring have also supported tagging methods with annotations to identify t Hem as objects, Spring should instantiate, to identify dependencies, should is injected, and to identify Initializ Ation and destruction methods that should be called.

That last item was handled by the or one of its InitDestroyBeanPostProcessor subclasses. A post processor is a special kind of object, instantiated by Spring, that implements a post processor interface. Because it implements this interface, spring would call a method in it with each object Spring have instantiated, allowing I T to modify or even replace that object. This was part of Spring's approach to a modular architecture, allowing easier extension of capability.

How It Works

It so happens this JSR-250 identified some "common" annotations, including a @PostConstruct annotation that's designed to tag Init Ialization methods, and a @PreDestroy annotation for destruction methods. However, is designed to work InitDestroyBeanPostProcessor with any set of annotations, so it provides methods to identify the annotations:

    Setinitannotationtype (ClassAnnotationinitannotationtype) {  
        This.   Initannotationtype;
    }
...
    Setdestroyannotationtype (ClassAnnotationdestroyannotationtype) {  
        This.   Destroyannotationtype;
    }

Note that these is ordinary setter methods, so this object can itself is set up using Spring. In my case, I am using Spring's StaticApplicationContext , as I ' ve described previously.

Once Spring has instantiated the various objects and have injected all of the dependencies, it calls the postProcessBeforeInitialization method on all The post processors, for every object. This gives the post processor a chance to modify or replace the object before it ' s initialized. Because dependencies has been injected, the the place where InitDestroyAnnotationBeanPostProcessor calls the initialization method.

    Findlifecyclemetadata (Bean.  GetClass ()); 
    try {
        Metadata. invokeinitmethods (beanname); 
    }

Since we ' re interested in what the code deals with annotations, we ' re interested findLifecycleMetadata() in, Since that's where the class is Inspected. That method checks a cache, which are used to avoid performing reflection more than necessary, since it can be expensive. If the class hasn ' t been inspected yet, the method is buildLifecycleMetadata() called. The meat of this method looks like:

Reflectionutils. dowithlocalmethods (reflectionutils.  Methodcallback () {  
    @Override
    Dowith (illegalaccessexception {
        if (null) {
            if (method.  Getannotation (null) {  
                Lifecycleelement (method);
                Currinitmethods. Add (Element); 
            }
        }
        ...
    }
});

The is ReflectionUtils a handy class that simplifies using reflection. Amongst other things, it converts the numerous checked exceptions this go along with reflection into unchecked exceptions, Making things easier. This particular method iterates-only local methods (i.e. not methods that is inherited) and calls the callback for E Ach method.

After all of the. Setup, the part. Checks for the annotation is pretty boring; It just calls a Java reflection method to check for the annotation and, if it's found, stores that method away as an Initi Alization method.

Wrap up

The fact that ultimately, what's happening here is, is really, the point, the I try to make when I teach reflection. It can be challenging to debug code this uses annotations to control behavior because from the outside it ' s pretty opaque , so it's hard-to-envision what's happening (or not happening) and when. But at the end of the day, what's happening is really just Java code; It might not being immediately apparent where that code was, but it ' s there.

Spring Annotation processing:how It works--turn

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.