Java reflection in NLP-four steps
In the previous three articles, we will get the basic knowledge of reflection and the structure of the running class through reflection, such as, attributes, methods, parent classes, interfaces, annotations, and so on, this article describes how to call the specified attributes and methods of the running class through reflection. We will learn a typical running reflection, and the combination of dynamic proxy and AOP.
AOP
Dynamic proxy
First, we will introduce a situation where code segments 1, 2, and 3 all contain the same code segment. Previous methods are completed by complex pasting of repeated code segments,
This situation described above must be improved. We can pull out the repeated code, let code segments 1, 2, and 3 call the extracted repeated code segments in the form of method calls. In this way, compared with the figure above, the code segments 1, 2, 3 and repeated are separated, but the code segments 1, 2, and 3 are coupled with the code that is extracted, for example:
The ideal result is that code segments 1, 2, and 3 can be called using method A, and the program does not need to call the method or hard code, the dynamic agent of AOP can solve this problem well.
For the implementation of dynamic AOP proxies, jdk reflection and CGLib are commonly used. The difference between them is that the former can not represent classes without interfaces, while CGlib can. We will not talk about the specifics, this article mainly aims to apply the reflection mentioned in the previous three articles. All our dynamic proxies are implemented using the reflection provided by jdk itself. Next we will use the dynamic proxy of jdk to solve this problem.
Implementation
First, the proxy interface Hello:
package com.tgb.state;/** * * @author kang * */public interface Hello {public void say(String name);}
HelloImpl:
package com.tgb.state;public class HelloImpl implements Hello {@Overridepublic void say(String name) {System.out.println(this.getClass()+" Hello!"+name);}}
The extracted General Code class ServiceBean:
Package com. tgb. dynamic. jdk; import java. lang. reflect. method; import java. util. hashMap;/*** service bean, which is a function to be reused in aop * @ author kang **/public class ServiceBean {// HashMap of the object before the proxy object method is put in place
BeforeBeans = new HashMap
(); // The HashMap object after the proxy object method is put
AfterBeans = new HashMap
(); // Specifies the HashMap method of the object before the proxy object method.
BeforeMethods = new HashMap
(); // HashMap of the object method after the proxy object Method
AfterMethods = new HashMap
(); Public void before () throws Exception {for (HashMap. Entry
Entry: beforeBeans. entrySet () {String beanKey = entry. getKey (); Object beforeBean = entry. getValue (); String beforeMethodValue = beforeMethods. get (beanKey); // System. out. println ("beforeMethodValue:" + beforeMethodValue); // Method beforeMethod = beforeBean to be executed using reflection. getClass (). getMethod (beforeMethodValue); // System. out. println ("beforeMethod:" + beforeMethod); // The method beforeMethod to be executed by the execution Class Using Reflection. invoke (beforeBean);} // System. out. println (this. getClass () + "Before");} public void after () throws Exception {for (HashMap. entry
Entry: afterBeans. entrySet () {String beanKey = entry. getKey (); Object afterBean = entry. getValue (); String afterMethodValue = afterMethods. get (beanKey); // System. out. println ("afterMethodValue:" + afterMethodValue); // obtain the Method to be executed for the Class Using Reflection Method afterMethod = afterBean. getClass (). getMethod (afterMethodValue); // System. out. println ("afterMethod:" + afterMethod); // The afterMethod to be executed by the running Class Using Reflection. invoke (afterBean);} // System. out. println (this. getClass () + "After");} public HashMap
GetBeforeBeans () {return beforeBeans;} public void setBeforeBeans (HashMap
BeforeBeans) {this. beforeBeans = beforeBeans;} public HashMap
GetAfterBeans () {return afterBeans;} public void setAfterBeans (HashMap
AfterBeans) {this. afterBeans = afterBeans;} public HashMap
GetBeforeMethods () {return beforeMethods;} public void setBeforeMethods (HashMap
BeforeMethods) {this. beforeMethods = beforeMethods;} public HashMap
GetAfterMethods () {return afterMethods;} public void setAfterMethods (HashMap
AfterMethods) {this. afterMethods = afterMethods ;}}
Processing class MyInvokationHandler:
Package com. tgb. dynamic. jdk; import java. lang. reflect. invocationHandler; import java. lang. reflect. method; import java. lang. reflect. proxy;/*** processing class, used to load the reusable code class * @ author kang **/public class MyInvokationHandler implements InvocationHandler {private ServiceBean serviceBean; private Object target; public Object getTarget () {return target;} public void setTarget (Object target) implements this.tar get = target;} @ Overridepublic Object invoke (Object proxy, Method method, Object [] args) throws Throwable {serviceBean. before (); Object result = method. invoke (target, args); serviceBean. after (); return result;} public ServiceBean getServiceBean () {return serviceBean;} public void setServiceBean (ServiceBean serviceBean) {this. serviceBean = serviceBean ;}}
Dynamically generate the proxy class MyProxyFactory for the proxy object:
Package com. tgb. dynamic. jdk; import java. lang. reflect. proxy; public class MyProxyFactory {/*** generate Proxy object * @ return */@ SuppressWarnings ("unchecked") public static
T getProxy (Object target, MyInvokationHandler handler) {// set the target Object handler for MyInvokationHandler. setTarget (target); // create and return a dynamic Proxy object return (T) Proxy. newProxyInstance (target. getClass (). getClassLoader (), target. getClass (). getInterfaces (), handler );}}
By now, the overall class of aop dynamic proxy has been established. The careful colleagues found that the ServiceBean service class is a bit complicated because we abstract the service class here, so that the service class can also use reflection to dynamically load function classes that need to be reused. The reflection code in the class is what we learned in the first three articles.
Next let's take a look at the reusable function class HiImpl that needs to be dynamically loaded:
Package com. tgb. state; public class HiManage {public void hi () {System. out. println (this. getClass () + "Before method" + "hi method");} public void bye () {System. out. println (this. getClass () + "after method" + "bye method ");}}
Next let's take a look at our client code:
Package com. tgb. dynamic. jdk; import java. util. hashMap; import com.sun.org. apache. bcel. internal. generic. NEW; import com. tgb. state. hiManage; public class Client4 {public static void main (String [] args) {// --------------- load reusable function classes ------------------------ HashMap
BeforeBeans = new HashMap
(); HashMap
AfterBeans = new HashMap
(); HashMap
BeforeMethods = new HashMap
(); HashMap
AfterMethods = new HashMap
(); BeforeBeans. put ("HiManage", new HiImpl1 (); afterBeans. put ("HiManage", new HiImpl1 (); beforeMethods. put ("HiManage", "hi"); afterMethods. put ("HiManage", "bye"); ServiceBean serviceBean = new ServiceBean (); serviceBean. setBeforeBeans (beforeBeans); serviceBean. setAfterBeans (afterBeans); serviceBean. setBeforeMethods (beforeMethods); serviceBean. setAfterMethods (afterMethods); // ------------------ load reusable function classes; // set the reusable function classes after loading to MyInvokationHandler = new MyInvokationHandler () in the processing class (); handler. setServiceBean (serviceBean); // generate the proxy object Hello helloProxy = MyProxyFactory. getProxy (new HelloImpl (), handler); helloProxy. say ("zhangsan ");}}
Running result:
Class com. tgb. state. HiManage Before method hi Method
Class com. tgb. state. HelloImpl Hello! Zhangsan
Class com. tgb. state. HiManage's after method bye Method
Here, an aop dynamic proxy implemented using jdk reflection is completed. In 3, Hello and HelloImpl on the left are proxy classes, and ServiceBean on the far right is the abstract function class to be reused, we only abstract and encapsulate this abstract function class, and use reflection to allow this ServiceBean to dynamically load the specific function class to be reused, such as the HiManage class. Line 1 and line 2 both dynamically generate the Hello proxy class only when the client is called, and dynamically load the reusable feature class HiManage to jointly implement our dynamic AOP proxy.
Postscript
Through four articles in total, we learned the reflection knowledge through the specific demo code, including class Object creation and class object instance generation, and the specific structure of the class, such as constructor, attribute, method, annotation, parent class, and implementation interface. Finally, we introduce a typical application of aop dynamic proxy for reflection, we will introduce reflection first.