Go Application of Java reflection in real development

Source: Internet
Author: User
Tags object object object serialization throwable

    • One: Java class loading and initialization
      • Class 1.1 Loader (class-loaded tools)
      • 1.2 The preparation required for Java to work with a class
    • II: Java in Rtti
      • 2.1: Why run-time type information is used (that is, RTTI)
      • How 2.2:rtti is represented at run time
      • 2.3:class Object
      • 2.3:rtti Form Summary:
    • Three: Java uses reflection to get run-time type information
      • 3.1: Get the way
      • 3.2: Dynamic Agent
    • Four: Java reflection in the actual development of the application
      • 4.1: Create a unified interception layer in a Web project
      • 4.2: For WebService service: and servlet do agree to intercept, use reflection to invoke the same purpose of the method (add some desired processing, such as verifying the user). The core is also the reflection call method

Body

Runtime type recognition (RTTI, Run-time type information) is a very useful mechanism in Java, in Java, there are two ways of RTTI, one is traditional, that is, assuming that all types are known at compile time; is to use the reflection mechanism to try to determine the type information at run time.

This blog post will combine the thinking in Java demo and the actual development of the examples encountered in the Java reflection and access to the type of information to do a general collation. The article is mainly divided into three pieces:

    • Java class loading and initialization
    • Rtti in Java
    • Java uses reflection to obtain run-time type information
Back to top one: Java class loading and initialization

When learning Rtti, the first thing you need to know is how classes in Java are loaded, and how Java can get the information it needs in the JVM based on these class files (note: I can't think of a better description here, I hope the reader could give a better description)

Class 1.1 Loader (class-loaded tools)

The class loader subsystem contains a loader chain with only a "native ClassLoader" that is part of the JVM implementation that can be used to record classes within a local jar package, and to mount additional ClassLoader if it involves loading a class on a network, or a Web server application.

1.2 Java uses a class for the preparation required 1.2.1 dynamic loading

All classes are used for the first time and are dynamically loaded into the JVM. Creates a reference to a static member of a class that loads the class. The Java program is not fully loaded at the beginning of the run, the class is loaded in place, which is the dynamic loading

①: First check if this class is loaded

②: If not loaded, then go to the class name to find the. class file, load the class's bytecode, and verify the existence of bad code,

The test code is as follows:

Candy.javapublic class Candy {static {System.out.println ("Loading candy");    }}//cookie.javapublic class Cookie {static {System.out.println ("Loading cookie");    }}//gum.javapublic class Gum {static {System.out.println ("Loading Gum"); }}//testmain.javapublic class Testmain {public static void main (string[] args) {System.out.println ("inside Mai        n ");        New Candy ();        System.out.println ("After create Candy"); try {class.forname ("com.        Runtimetypeinformation.gum ");        } catch (ClassNotFoundException e) {System.out.println ("Could not find Class");        } System.out.println ("after Class.forName");        New Cookie ();            System.out.println ("After new Cookie ()"); } static void Printclassinfo (Class C) {System.out.println ("Class Name:" +c.getname () + "is int Erface?           : "+ c.isinterface () +" simple Name "+ c.getsimplename ()         ); }

The output can be clearly seen, the class object is loaded only when needed, and static initialization occurs when the class is loaded

1.2.2 Links

Validates the bytecode in the class and allocates storage space for the static domain. If necessary, all references to other classes created by this class will be parsed

1.2.3 Initialization

If the class has a superclass, initialize it, execute the static initializer and the static code block. Initialization is deferred until the first reference to a static method or a non-static method is performed

Back to Top II: Java in Rtti

2.1: Why run-time type information is used (that is, RTTI)

In real-world development, demand is not immutable (it's a constant change), and every new add-on needs to be more efficient if the amount of code churn is smaller. Like what:

Package com. Runtimetypeinformation.circle;import Java.util.arrays;import Java.util.list;abstract class Shape {    void Draw () {        System.out.println (this+ ". Draw ()");    Abstract public String toString ();} Class Circle extends shape{    @Override public    String toString () {        return ' Circle ';    }    } Class Triangle extends shape{    @Override public    String toString () {        return ' Triangle ';    }    } public class shapes{public    static void Main (string[] args) {        //digression, arrays.aslist variable parameter list, can convert multiple objects passed in to a list< c16/>list<shape> shapes = arrays.aslist (new Triangle (), New Circle ());        for (Shape shape:shapes) {            shape.draw ();}}    }

When I want to add a new shape, such as a rectangle, I just need to write a new class to inherit shape, without needing to modify the call. "polymorphic"is used here (although the Shpe method is called, the JVM can

Know exactly which sub-class to call the method)

When you first learn about polymorphism , you may be simply aware of the fact that abortion is the case, so now let's look at how Java is handled.

① when the triangle,circle is placed in the list<shape>, it is transformed upward into Shape, losing the specific type

② when the Shape object is taken out of the device, the list is actually stored in object, which automatically turns the result into shape at run time, which is the work of Rtti ( identifying the type of an object at runtime )

At this time, if the customer needs to change again, said do not want to draw the result of a circle . In response to this requirement, we can use Rtti to query the specific type that a shape reference points to (how to use it, and then look down)

How 2.2:rtti is represented at run time

Java's core idea is: " everything is the object ", for example, we have the shape of abstract, get round class, triangle class. But we're doing an abstraction for these classes, and getting class to describe the general nature of the class

I used to draw pictures (a bit of excuse), if we can get the object's class, we can use Rtti to get concrete Java class. As for how to get the class and how to use classes to get the exact category, continue to look down.

2.3:class Object

Each class has a corresponding class object (saved in the. class file), and the specific object is given by class, please refer to "Loading and initializing of the first section class"

How the 2.3.1 Class object gets

①:class.forname ("Fully qualified class name"), gets the class object, and the side effect is "the class is loaded if the corresponding class is not loaded." Cannot find the "classnotfoundexception" thrown

②: If there is an object, you can directly use the object to get the corresponding class object such as

Shape shape  = new Circle (); Shape.getclass ()

③; The class literal constant: Shape.class. Recommend this method, the first is that the compiler will do the check, the second is the root in addition to the forname call, improve efficiency

Common methods for 2.3.2:class objects

Method Name Description
Forname () (1) Gets a reference to the class object, but the referenced class is not loaded (the first object of the class is not generated) and the class is loaded.
(2) In order to produce a class reference, forname () is initialized immediately.
Object-getclass () Gets a reference to the class object that returns a class reference that represents the actual type of the object.
GetName () The fully qualified class name (including the package name), which is the full name of the class.
Getsimplename () Get class name (excluding package name)
Getcanonicalname () Get the fully qualified class name (including the package name)
Isinterface () Determines whether the class object represents an interface
Getinterfaces () Returns an array of class objects that represent all interfaces implemented by classes referenced by the class object.
GETSUPERCALSS () Returns a Class object that represents the direct base class inherited by the class referenced by the class object. Apply this method to discover an object's complete inheritance structure at run time.
Newinstance () Returning a Oject object is a way to implement a virtual constructor. A class created using this method must have a constructor with no arguments .
GetFields () Gets all the public fields of a class, including all public fields that inherit from the parent class. Similar to GetMethods and GetConstructors.
Getdeclaredfields A field that obtains its own claims for a class, which includes public, private, and proteced, by default but does not include any fields declared by the parent class. Similar to Getdeclaredmethods and Getdeclaredconstructors.
2.3.3 Generalization of class

The class reference represents the exact type of object it points to, and after java1.5, allows the developer to qualify the class object that the class reference points to, that is, to add generics.

public static void Main (string[] args) {        class<integer> intclass = int.class;        Intclass = Integer.class;    }

This allows for type checking in the compiler, which can, of course, loosen the limit when referring to generics through the wildcard character: class<?>

Objective:

①: In order to be able to do type checking in the compiler

②: when class<circle> Circle = Circle.getclass (); Circle.newinstance () will be given a specific type. But note here:

public class shapes{public    static void Main (string[] args) throws Instantiationexception, Illegalaccessexception { C1/>class<circle> circles = Circle.class;        Circle Circle = Circles.newinstance ();//First: Generalization class.newinstance can directly get concrete object        class< Super circle> shape = Circles.getsuperclass ();        Object shape1 = Shape.newinstance ();//second: Its parent class can only be received with the contravariant generic class, Newinstance get the object type     }}

2.3:rtti Form Summary:

①: Traditional type conversion, such as the Shape.draw () we used in the above demo;

②: Use class to get run-time information.

③: Get Specific objects

Back to top three: Java uses reflection to get run-time type information

If you do not know the specific type of an object reference (such as an object that has already been transformed), Rtti can get it. But the premise is that this type of compiler must be known (those are compile-time agnostic?). A disk file or a network connection to get a string of bytes representing the class)

The ability to create and run objects on a remote platform across the network this is known as RMI (remote method invocation), and the following is a detailed introduction to how RMI is implemented

Reflection provides a mechanism for checking available methods and returning method names to call methods.

3.1: Get the way

A jar package is provided in Java, and the Java.lang.reflect and class objects together support the concept of reflection.

3.1.1 Java.lang.reflect:

The class library contains the Field Method Constructor. These types of objects are created at the JVM runtime to represent the corresponding members of the unknown class. Thus:

①: Create an object with constructor and read fields in field with Get set

②: Calling method with Method.invoke ()

③: Using GetFields (), GetMethods (), getconstuctors () to get the corresponding array

The difference between 3.1.2 Rtti and RMI

Examine the object to see which class the object belongs to, and load the class file

①:rtti will open and check the . class file at compile time

②:rmi is not visible at compile time. class file. Only open and check . class files at run time

3.2: Dynamic Proxy 3.2.1 I assume you're right. "proxy mode"There is a certain understanding (or simply say, the proxy mode is to add a layer before the interface and implementation, for stripping the interface of some additional operations) below is the sample code for the proxy mode:
Public interface Subject   {public     void dosomething ();   }   public class Realsubject implements Subject   {public     void dosomething ()     {       System.out.println ("Call DoSomething () ");     }   }   public class Proxyhandler implements Invocationhandler   {     private Object proxied;          Public Proxyhandler (Object proxied)     {       this.proxied = proxied;     }          public object invoke (object proxy, method, object[] args) throws Throwable     {       //before the target object is transferred, some functions can be performed to handle the c20/>//the method of transferring specific target objects    return Method.invoke (proxied, args);          After you have transferred the target object, you can perform some function processing  }    }

The 3.2.2 Dynamic agent is the dynamic creation of the agent and the dynamic processing of calls to the methods it proxies. You can refer to "thorough understanding of Java Dynamic Agent", "deep analysis of the JDK dynamic agent mechanism." Can be understood as a more flexible proxy model

① Dynamic Agent Usage steps:

  1. Customize your own Invocationhandler by implementing the Invocationhandler interface;

2. Get dynamic proxy class via Proxy.getproxyclass

3. Get the method of constructing proxy class by reflection mechanism, method signature is GetConstructor (Invocationhandler.class )4. Get the proxy object through the constructor and pass the custom Invocationhandler instance object as a parameter passed in5. Calling the target method through the proxy object
public class Myproxy {public interface ihello{void SayHello (); } Static class Hello implements ihello{public void SayHello () {System.out.println ("Hello world!!")        ; }}//Custom Invocationhandler static class Hwinvocationhandler implements invocationhandler{//target object P        Rivate Object Target;        Public Hwinvocationhandler (Object target) {this.target = target; public object invoke (object proxy, Method method, object[] args) throws Throwable {System.out.println            ("------Insert the pre-notification code-------------");            Perform the corresponding target method Object rs = Method.invoke (Target,args);            SYSTEM.OUT.PRINTLN ("------insert post-processing code-------------");        Return RS; }} public static void Main (string[] args) throws Nosuchmethodexception, Illegalaccessexception, Invocationtargetexc Eption, Instantiationexception {//Generate $proxy0 class file System.getproperties (). put ("Sun.misc.ProxyGenerator. Savegeneratedfiles "," true "); Ihello Ihello = (Ihello) proxy.newproxyinstance (IHello.class.getClassLoader (),//Loading interface class loader new Class[]{ihe Llo.class},//A set of interfaces new Hwinvocationhandler (new Hello ()));   Custom Invocationhandler Ihello.sayhello (); }}

②: The principle of dynamic agent, to enumerate the references: (essentially, the reflection is used)

1, JDK dynamic agent implementation principle

2. Analysis and extension of dynamic agent mechanism in Java

③ Dynamic Agent Application and remark Description:

The JDK implementation dynamic Proxy requires the implementation class to define the business method through the interface (I'll briefly say Cglib to implement dynamic proxies ). The second is that the dynamic agent is very important to reflect a very important module, many frameworks are inseparable from dynamic agents, such as spring. Therefore, the reader is recommended to study a bit more.

④:cglib Implementing dynamic Proxies

Reference Documentation: cglib Dynamic Agent Introduction (I.)

Cglib is a powerful, high-performance code-generation package. It is widely used by many AOP frameworks, such as spring AOP and DYNAOP, to provide them with methods of interception (interception). The most popular or mapping tool hibernate also uses the Cglib to proxy single-ended single-ended (many-to-one-to-single) associations (deferred fetching of collections, implemented by other mechanisms). Easymock and Jmock are packages that test Java code by using mock-up (Moke) objects. They all create mock-up (Moke) objects for classes that do not have interfaces by using Cglib.
The bottom of the Cglib package is to convert bytecode and generate new classes by using a small, fast bytecode processing framework asm. In addition to the Cglib package, scripting languages such as groovy and BeanShell are also bytecode that uses ASM to generate Java. When you discourage direct use of ASM, because it requires you to be familiar with the internal structure of the JVM including the format and instruction set of the class file

"Extending Java classes at runtime and implementing Java Interfaces", supplementing the Java dynamic Agent mechanism requires that the interface be implemented, and cglib for those classes that do not implement the interface, the principle is to inherit these classes, become subclasses, cover some methods, So cglib does not take effect on final classes.

Cglib implementation of Dynamic Agent Demo: Reference cglib Dynamic Agent principle and implementation

This is the class to proxy:

public class SayHello {public   void say () {    System.out.println ("Hello everyone");   }  }  

The core of the proxy class

public class Cglibproxy implements methodinterceptor{   Private enhancer enhancer = new enhancer ();   Public Object GetProxy (class Clazz) {    //sets the class    Enhancer.setsuperclass (Clazz) that requires the subclass to be created;    Enhancer.setcallback (this);    Dynamically creating subclass instances with bytecode technology    return enhancer.create ();   }   Implement the Methodinterceptor interface method public   object Intercept (Object obj, Method method, object[] args,     methodproxy Proxy) throws Throwable {    System.out.println ("predecessor Agent");    Calling a method in the parent class through the proxy class    Object result = Proxy.invokesuper (obj, args);    System.out.println ("post Agent");    return result;   }  }  

Test results:

public class Docglib {public   static void Main (string[] args) {    Cglibproxy proxy = new Cglibproxy ();    Create a proxy class by generating subclasses    SayHello Proxyimp = (SayHello) proxy.getproxy (sayhello.class);    Proxyimp.say ();   }  }  

Back to top four: Java reflection applied in real development

Generally, we do not use reflection in general business requirements, but when we are in more dynamic code, we can choose to implement reflection (such as Object serialization and JavaBean). The main logic I have explained above, so the next more is the code show:

In the actual development, the class information is obtained at run time, and the method is called by Reflection Method.invoke (). This is done out of the design idea of AOP . For example, I have a traditional Web project, I can pass the HTTP direct request to the background servlet, if I want to add a log, or in the request session to add a message , if there is only one request, I can directly in the Htttp Plus , but there are actually a lot of requests, which is why I pulled a layer out of the sevlet and called the servlet through reflection

Of course, many frameworks actually provide us with a blocking configuration (this is something)

4.1: Create a unified interception layer in a Web project
DoPost (..)                {//This is the Setvlet unified interception layer in the project, let's take a look at actioninvoker.invoke ... else if (requesttype.equalsignorecase ("image")) {                    try {actionclassinfo actionclassinfo = Actioninvoker.getclassinfo (action, request, response);                    Actionclassinfo.setargs (QUERYSTRINGMAP);                    Object object = Actioninvoker.invoke (Actionclassinfo);                    Response.AddHeader ("accept-ranges", "bytes");                    byte[] bytes = (byte[]) object;                    Response.AddHeader ("Content-type", "application/png");                    Response.AddHeader ("Content-length", String.valueof (Bytes.length));                Response.getoutputstream (). Write (bytes, 0, bytes.length);                } catch (Exception e) {e.printstacktrace ();                } catch (Throwable e) {e.printstacktrace ();                    } finally {Response.getoutputstream (). Flush (); RespoNse.getoutputstream (). Close (); }            }    }

The Actioninvoker.invoke () method code is as follows : In this method, I can add the processing I want, such as first to determine whether there is a cache, the core is only Method.invoke

public object Invoke (Actionclassinfo action) throws Exception {        //Execute method before        Object cache = null;        For (object Object:action.getProxys ()) {            if (object instanceof Intercepter) {                cache = ((intercepter) Object). bef Ore (action);                if (cache! = NULL && object instanceof Rediscachehandler) {                    return cache;    The cached result is returned directly}}        }        method = Action.getmethod ();        Object business = Action.getclazz ();        Map<object, object> args = Action.getargs ();        Method.setaccessible (true);        Object result = Method.invoke (business, args);        Executes the method after the for        (Object Object:action.getProxys ()) {            if (object instanceof intercepter)                result = ((intercep ter) object). After (result, action);        }        return result;    }

4.2: For WebService service: and servlet do agree to intercept, use reflection to invoke the same purpose of the method (add some desired processing, such as verifying the user). The core is also the reflection call method

(Original address: HTTPS://WWW.CNBLOGS.COM/LDH-BETTER/P/7148975.HTML#_LABEL1_0)

Go Application of Java reflection in real development

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.