Reflection in Java and implementation of bean container

Source: Internet
Author: User

Reflection (Refection) in a programming language refers to the ability to dynamically load a class at program run time. It is related to introspection (introspection), which means that the program can get a description of a type, such as getting all the interface definitions of a class, all the parameters of an interface. When the programming language has these language features, it can solve the problem of code coupling to a large extent, so in the Java world, you can see that many libraries/frameworks use reflection technology.

A spring-like bean container implementation is a huge use of the reflection mechanism. The bean container maintains some bean objects, which are simply some common objects. The bean container can create these objects from the configuration, and when created, the bean container is responsible for injecting the dependent objects into the target object, known as Dependency injection (dependence injection), if the objects depend on other objects. In the module design, it also derives the concept of inversion of control (IoC, inverse of controls), which describes the application to control the framework when using a framework, not a framework to control/limit the application's architectural pattern.

This article simply describes how the bean container is implemented using reflection, and the final code references GitHub ioc-sample

Dynamic loading of classes

You can simply use Class.forName it to pass in the full name of a class:

Public class<?> loadclass (String fullName) throws ClassNotFoundException {      return class.forname (fullName);    }

The loading of classes involves class loader, which can be further deepened. Once you have loaded the class, you can create an instance of the class, but you have not yet completed the dependency injection function:

class<?> C = loadclass ("Com.codemacro.bean.test.Test1");    Object o = c.newinstance ();
Injection via set interface

Our class can contain set interfaces for setting up a member:

public class Test2 {public      Test1 test1;            public void SetTest1 (Test1 t) {        test1 = t;      }    }

Then the setXXX interface will be Test1 injected into Test2 :

props specifies which members need to be injected, for example {"Test1", "test1"},test1 means settest1,test1 refers to the bean name public    Object Buildwithsetters (String Name, class<?> C, map<string, string> props) {      try {        //Classsetmethods class get class<?> All setxx in this interface        classsetmethods setmethods = new Classsetmethods (c);        Object obj = c.newinstance ();        For (map.entry<string, string> entrys:props.entrySet ()) {          String pname = Entrys.getkey ();          String beanname = Entrys.getvalue ();          Get Setxxx This method          m = Setmethods.get (pname);          Object val = Getbean (beanname);          Call          M.invoke (obj, Val);        }        Beans.put (name, obj);        return obj;      } catch (Exception e) {        throw new RuntimeException ("Build bean Failed", e);      }    }

ClassSetMethodIntrospect all the interfaces in a class setXXX(xx) :

Public Classsetmethods (class<?> c) {      method[] methods = C.getmethods ();      for (Method m:methods) {        String mname = M.getname ();        class<?>[] Ptypes = M.getparametertypes ();        if (Mname.startswith ("set") && ptypes.length = = 1 && m.getreturntype () = = Void.type) {          String name = M Name.substring ("set". Length ());          This.methods.put (name, M);}}}    

Above, you can see the ability of introspection in Java, for example, Class<?>.getMethods Method.getReturnType Method.getParameterTypes .

Inject by constructor function

Similar to the following in spring:

<bean id= "Examplebean" class= "examples. Examplebean ">  <constructor-arg type=" int "value=" 2001 "/>  <constructor-arg type=" Java.lang.String "value=" Zara "/>

You can inject dependent beans through constructor parameters into the target object:

list<string> params = new arraylist<string> ();    Params.add ("Test1");    Bf.buildwithconstructor ("Test2", Test2.class, params);

Its implementation:

Public Object Buildwithconstructor (String name, class<?> C, list<string> beannames) {      try {        constructor<?>[] ctors = C.getconstructors (); Get class constructor list        assert ctors.length = = 1;        constructor<?> cc = ctors[0];         class<?>[] Ptypes = Cc.getparametertypes (); Get constructor parameter Type list        assert ptypes.length = = Beans.size ();        object[] args = new Object[ptypes.length];        for (int i = 0; i < beannames.size (); ++i) {           Args[i] = Getbean (Beannames.get (i));//construct the argument list of the call constructor        }        objec T obj = cc.newinstance (args); Creates an object        beans.put (name, obj) through a constructor;        return obj;      } catch (Exception e) {        throw new RuntimeException ("Build bean Failed", e);      }    }

The use Convention for this interface beanNames is to save the bean name and correspond to the constructor parameter one by one.

through annotation injection

We can annotate a data member with an annotation that needs to be injected automatically. Here I simply get the member type of the annotation callout and find the bean that corresponds to that type as the injected object. Of course, complex points can also specify the name of the bean to inject, or a derived class implementation that automatically finds the type.

An empty annotation can:

@Retention (retentionpolicy.runtime)    @Target (elementtype.field) public    @interface Inject {    }

Realize:

Public Object Buildwithinject (String name, class<?> c) {      try {        Object obj = c.newinstance ();        field[] fields = C.getdeclaredfields ();  Gets the member for all definitions of the class for        (Field f:fields) {          Inject Inject = f.getannotation (Inject.class);//Gets the annotated if of the data member          (Inject ! = NULL) {//If annotated with inject annotation            Object bean = Getbeanbytype (F.gettype ());//Find the corresponding bean            f.set (obj, Bean) based on the type of the member;//Inject          } else {            throw new RuntimeException ("Not Found Bean" + f.getname ())}        }        Beans.put (name, obj);        return obj;      } catch (Exception e) {        throw new RuntimeException ("Build bean Failed", e);      }    }

getBeanByTypeis to Class match all the beans. When used:

public class Test2 {      @Inject public      Test1 test1;      ...    }

Finish.

Original address: http://codemacro.com/2015/05/31/java-refect-ioc/
Written by Kevin Lynx posted athttp://codemacro.com

Reflection in Java and implementation of bean container

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.