Java reflection-four steps and four steps of java
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:
<span style="font-family:KaiTi_GB2312;">package com.tgb.state;/** * * @author kang * */public interface Hello {public void say(String name);}</span>
HelloImpl:
<span style="font-family:KaiTi_GB2312;">package com.tgb.state;public class HelloImpl implements Hello {@Overridepublic void say(String name) {System.out.println(this.getClass()+" Hello!"+name);}}</span>
The extracted General Code class ServiceBean:
<Span style = "font-family: KaiTi_GB2312;"> package com. tgb. dynamic. jdk; import java. lang. reflect. method; import java. util. hashMap;/*** service bean, is a function to be reused in aop * @ author kang **/public class ServiceBean {// HashMap of the object before the proxy object method is stored <String, object> beforeBeans = new HashMap <String, Object> (); // HashMap <String, Object> afterBeans = new HashMap <String, object> (); // HashMap <String, String> beforeMethods = new HashMap <String, String> (); // HashMap <String, String> afterMethods = new HashMap <String, String> (); public void before () throws Exception {for (HashMap. entry <String, Object> 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 <String, Object> 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 <String, Object> getBeforeBeans () {return beforeBeans;} public void setBeforeBeans (HashMap <String, Object> beforeBeans) {this. beforeBeans = beforeBeans;} public HashMap <String, Object> getAfterBeans () {return afterBeans;} public void setAfterBeans (HashMap <String, Object> afterBeans) {this. afterBeans = afterBeans;} public HashMap <String, String> getBeforeMethods () {return beforeMethods;} public void setBeforeMethods (HashMap <String, String> beforeMethods) {this. beforeMethods = beforeMethods;} public HashMap <String, String> getAfterMethods () {return afterMethods;} public void setAfterMethods (HashMap <String, String> afterMethods) {this. afterMethods = afterMethods ;}}</span>
Processing class MyInvokationHandler:
<Span style = "font-family: KaiTi_GB2312;"> 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; }}</span>
Dynamically generate the proxy class MyProxyFactory for the proxy object:
<Span style = "font-family: KaiTi_GB2312;"> package com. tgb. dynamic. jdk; import java. lang. reflect. proxy; public class MyProxyFactory {/*** generate Proxy Object * @ return */@ SuppressWarnings ("unchecked") public static <T> 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) ;}</span>
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:
<Span style = "font-family: KaiTi_GB2312;"> 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") ;}}</span>
Next let's take a look at our client code:
<Span style = "font-family: KaiTi_GB2312;"> 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 <String, Object> beforeBeans = new HashMap <String, object> (); HashMap <String, Object> afterBeans = new HashMap <String, Object> (); HashMap <String, String> beforeMethods = new HashMap <String, string> (); HashMap <String, String> afterMethods = new HashMap <String, String> (); 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") ;}}</span>
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.