Java Learning - Preliminary understanding of reflection and dynamic proxies

"This is a summary of video material and video compilation for Chuanzhuan Big Data Course"

 

1 Reflection

The attributes, methods, constructors, etc. in a class object can be retrieved by reflection

  1 package thread.reflect;
  2 
  3 import org.junit.Before;
  4 import org.junit.Test;
  5 
  6 import java.lang.reflect.Constructor;
  7 import java.lang.reflect.Field;
  8 import java.lang.reflect.Method;
  9 
 10 public class MyReflect {
 11 
 12     public String className = null;
 13     @SuppressWarnings("rawtypes")
 14     public Class personClass = null;
 15     /**
 16      * Reflect Person Class
 17      * @throws Exception
 18      */
 19     @Before
 20     public void init() throws Exception {
 21         className = "thread.reflect.Person";
 22         personClass = Class.forName(className);
 23     }
 24     /**
 25      *Get a class file object
 26      */
 27     @Test
 28     public void getClassName() throws Exception {
 29         System.out.println(personClass);
 30     }
 31     /**
 32      *Another way to get a class file object
 33      */
 34     @Test
 35     public void getClassName2() throws Exception {
 36         System.out.println(Person.class);
 37     }
 38     /**
 39      *Create an instance object represented by a class file, and the underlying layer invokes the construction of empty parameters
 40      */
 41     @Test
 42     public void getNewInstance() throws Exception {
 43         System.out.println(personClass.newInstance());
 44     }
 45     /**
 46      *Get a non-private constructor
 47      */
 48     @SuppressWarnings({ "rawtypes", "unchecked" })
 49     @Test
 50     public void getPublicConstructor() throws Exception {
 51         Constructor constructor  = personClass.getConstructor(Long.class,String.class);
 52         Person person = (Person)constructor.newInstance(100L,"zhangsan");
 53         System.out.println(person.getId());
 54         System.out.println(person.getName());
 55     }
 56     /**
 57      *Get Private Constructors
 58      */
 59     @SuppressWarnings({ "rawtypes", "unchecked" })
 60     @Test
 61     public void getPrivateConstructor() throws Exception {
 62         Constructor con = personClass.getDeclaredConstructor(String.class);
 63         con.setAccessible(true);//Forced Cancellation Java Permission Detection
 64         Person person2 = (Person)con.newInstance("zhangsan");
 65         System.out.println("**"+person2.getName());
 66     }
 67     /**
 68      *Accessing non-private member variables
 69      */
 70     @SuppressWarnings({ "rawtypes", "unchecked" })
 71     @Test
 72     public void getNotPrivateField() throws Exception {
 73         Constructor  constructor  = personClass.getConstructor(Long.class,String.class);
 74         Object obj = constructor.newInstance(100L,"zhangsan");
 75 
 76         Field field = personClass.getField("name");
 77         field.set(obj, "lisi");
 78         System.out.println(field.get(obj));
 79     }
 80     /**
 81      *Accessing private member variables
 82      */
 83     @SuppressWarnings({ "rawtypes", "unchecked" })
 84     @Test
 85     public void getPrivateField() throws Exception {
 86         Constructor  constructor  = personClass.getConstructor(Long.class);
 87         Object obj = constructor.newInstance(100L);
 88 
 89         Field field2 = personClass.getDeclaredField("id");
 90         field2.setAccessible(true);//Forced Cancellation Java Permission Detection
 91         field2.set(obj,10000L);
 92         System.out.println(field2.get(obj));
 93     }
 94     /**
 95      *Get non-private member functions
 96      */
 97     @SuppressWarnings({ "unchecked" })
 98     @Test
 99     public void getNotPrivateMethod() throws Exception {
100         System.out.println(personClass.getMethod("toString"));
101 
102         Object obj = personClass.newInstance();//Constructor to get empty parameters
103         Method toStringMethod = personClass.getMethod("toString");
104         Object object = toStringMethod.invoke(obj);
105         System.out.println(object);
106     }
107     /**
108      *Get private member functions
109      */
110     @SuppressWarnings("unchecked")
111     @Test
112     public void getPrivateMethod() throws Exception {
113         Object obj = personClass.newInstance();//Constructor to get empty parameters
114         Method method = personClass.getDeclaredMethod("getSomeThing");
115         method.setAccessible(true);
116         Object value = method.invoke(obj);
117         System.out.println(value);
118 
119     }
120     /**
121      *
122      */
123     @Test
124     public void otherMethod() throws Exception {
125         //Currently loading this class The class loader object for the file
126         System.out.println(personClass.getClassLoader());
127         //Get all interfaces implemented by a class
128         Class[] interfaces = personClass.getInterfaces();
129         for (Class class1 : interfaces) {
130             System.out.println(class1);
131         }
132         //Reflects the direct parent of the current class
133         System.out.println(personClass.getGenericSuperclass());
134         /**
135          * getResourceAsStream This method obtains an input stream that is associated with the file represented by name.
136          */
137         //path No'/'The default at the beginning is to pull resources from the package in which this class resides to'/'Start with ClassPath Get under the root.It just passes through path Construct an absolute path, ultimately by ClassLoader Get resources.
138         System.out.println(personClass.getResourceAsStream("/log4j.properties"));
139         System.out.println(personClass.getResourceAsStream("log4j.properties"));
140 
141         //Judge Current Class Is the object representation an array
142         System.out.println(personClass.isArray());
143         System.out.println(new String[3].getClass().isArray());
144 
145         //Judge Current Class Is the object representation an enumeration class
146         System.out.println(personClass.isEnum());
147         System.out.println(Class.forName("thread.reflect.City").isEnum());
148 
149         //Judge Current Class Is object representation an interface
150         System.out.println(personClass.isInterface());
151         System.out.println(Class.forName("thread.reflect.MyInterface").isInterface());
152 
153 
154     }
155 
156 }
MyReflect

Use reflection for socket calls

Business Interface

1 package thread.reflect.socket;
2 
3 public interface Business {
4     int getPrice(String goods);
5 }

 

Business implementation

1 package thread.reflect.socket;
2 
3 public class BusinessImpl implements Business {
4     @Override
5     public int getPrice(String good) {
6         return good.equals("clothes")?10:20;
7     }
8 }

 

Processing class for server-side socket s

 1 package thread.reflect.socket;
 2 
 3 import java.io.*;
 4 import java.lang.reflect.Method;
 5 import java.net.Socket;
 6 
 7 public class ServerTask implements Runnable{
 8     private Socket socket;
 9     public ServerTask(Socket socket){
10         this.socket = socket;
11     }
12 
13     @Override
14     public void run() {
15         InputStream in;
16         OutputStream out;
17         try {
18             in = socket.getInputStream();
19             out = socket.getOutputStream();
20 
21             BufferedReader br = new BufferedReader(new InputStreamReader(in));
22             String request = br.readLine();
23             String[] split = request.split(":");
24             String className = split[0];
25             String methodName = split[1];
26             String methodParam= split[2];
27 
28             Class<?> forName = Class.forName(className);
29             System.out.println("calling class: " + forName);
30             Object newInstance = forName.newInstance();
31             Method method = forName.getMethod(methodName,String.class);
32             System.out.println("calling method: " + method);
33             Object invoke = method.invoke(newInstance, methodParam);
34             int value = Integer.parseInt(invoke.toString());
35             System.out.println("results: " + value);
36 
37 
38             PrintWriter pw = new PrintWriter(new BufferedOutputStream(out));
39             pw.println(value);
40             pw.flush();
41 
42             br.close();
43             pw.close();
44             socket.close();
45 
46         } catch (Exception e) {
47 
48             e.printStackTrace();
49         }
50 
51     }
52 
53 }

 

Server-side Run Class

 1 package thread.reflect.socket;
 2 
 3 import java.net.InetSocketAddress;
 4 import java.net.ServerSocket;
 5 import java.net.Socket;
 6 
 7 public class Server {
 8     public static void main(String[] args) throws Exception {
 9         ServerSocket server = new ServerSocket();
10         server.bind(new InetSocketAddress("localhost",9898));
11         while(true){
12             Socket socket = server.accept();
13             new Thread(new ServerTask(socket)).start();
14         }
15     }
16 }

Client Run Class

 1 package thread.reflect.socket;
 2 
 3 import java.io.*;
 4 import java.net.Socket;
 5 
 6 public class Client {
 7     public static void main(String[] args) throws Exception {
 8         Socket socket = new Socket("localhost", 9898);
 9         OutputStream out = socket.getOutputStream();
10         InputStream in = socket.getInputStream();
11 
12         PrintWriter pw = new PrintWriter(new BufferedOutputStream(out));
13         pw.println("thread.reflect.socket.BusinessImpl:getPrice:clothes");
14         pw.flush();
15 
16         BufferedReader br = new BufferedReader(new InputStreamReader(in));
17         String readLine = br.readLine();
18 
19         System.out.println("client get result: " + readLine);
20 
21         socket.close();
22 
23 
24 
25     }
26 }

 

2 Dynamic Proxy

In the previous code invocation phase, we implemented the business by invoking service with action.

Because the business previously implemented in the service may not be able to meet the requirements of the first customer, we need to modify the methods in the service, but the methods of the service are not only used in our module, but also called in other modules. When other modules call, the existing service methods can already be usedIt's enough to meet business needs, so we can't just modify the service for our business, causing other modules to influence it.

What about that?

The method implementation in our service can be extended by dynamic proxy to add more business to the original method instead of actually modifying the method in the service, which is called dynamic proxy.

Dynamic Agent: On the basis of not modifying the original business, re-expand to achieve new business based on the original business method.

For example:

1. Old Business

Buyer calls action to purchase clothes. The price of clothes in the database is 50 yuan. The purchasing process is a simple call.

2. New Business

The coupon can be used at the original price, but this function has not been implemented before. We proxy the original interface method through the proxy class, and modify the return value on the basis of this method.

 

Agent implementation process:

1. Write proxy classes and proxy methods to implement proxy Proxy.newProxyInstance in proxy methods

2. The required parameters in the proxy are: the class loader soneObjectclass.getClassLoader() of the class being proxied, all the implementation interfaces of the class being proxied new Class[] {Interface.class}, and the handle method new InvocationHandler()

3. Replicate the invoke method in the handle method. The input of the invoke method has three parameters: Object proxy (proxy class object), Method (proxy class method), Object[] args (incoming parameter of proxy class method). In this method, we can customize the development of new business.

4. Obtain proxy classes and forcefully convert to proxy interfaces

5. Finally, as if we were not proxied, we could call an interface's approved method. After the method was called, the method name and parameter list would be passed into the invoke method of the proxy class to do the logical process of the new business.

 

IBoss Business Interface Definition Class

1 package thread.proxy.bossProxy;
2 
3 public interface IBoss {
4     int sales(String size);
5 
6     String giveBack(String size);
7 }

Boss Business Interface Implementation Class

 1 package thread.proxy.bossProxy;
 2 
 3 public class Boss implements IBoss{
 4 
 5     @Override
 6     public int sales(String size) {
 7         System.err.println("Tmall Xiaoqiang flagship store clothes A Size:"+size);
 8         //The price of this dress, read from the database
 9         return 50;
10     }
11 
12     @Override
13     public String giveBack(String size) {
14         return "Return";
15     }
16 }

Boss Business Call Class

 1 package thread.proxy.bossProxy;
 2 
 3 import org.junit.Test;
 4 
 5 public class SalesAction {
 6     /**
 7      * Call method directly without proxy
 8      * Method specifies what business can only be invoked, what return value can be specified, and what return value can only be output
 9      */
10     @Test
11     public void saleByBossSelf() throws Exception {
12         IBoss boss = new Boss();
13         System.out.println("The boss owns himself!");
14         int money = boss.sales("xxl");// The boss sells his own clothes and doesn't need customer service. As a result, he doesn't have a chat record
15         System.out.println("Clothing prices:" + money);
16     }
17 }

Agent Boss Business Implementation Class

 1 package thread.proxy.bossProxy;
 2 
 3 import java.lang.reflect.InvocationHandler;
 4 import java.lang.reflect.Method;
 5 import java.lang.reflect.Proxy;
 6 
 7 public class ProxyBoss {
 8 
 9     @SuppressWarnings("unchecked")
10     public static <T> T getProxy(final int discountCoupon,final Class<?> interfaceClass, final Class<?> implementsClass)
11             throws Exception {
12         return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(),
13                 new Class[] { interfaceClass }, new InvocationHandler() {
14                     public Object invoke(Object proxy, Method method,
15                                          Object[] args) throws Throwable {
16                         Integer returnValue = (Integer) method.invoke(
17                                 implementsClass.newInstance(), args);// Value returned after calling the original object
18                         return returnValue - discountCoupon;
19                     }
20                 });
21     }
22 }

Proxy Boss Business Call Class

 1 package thread.proxy.bossProxy;
 2 
 3 import org.junit.Test;
 4 
 5 public class ProxySalesAction {
 6 
 7     @Test
 8     public void saleByProxy() throws Exception {
 9         IBoss boss = ProxyBoss.getProxy(10,IBoss.class,Boss.class);// Instantiate the proxy's methods into interfaces
10         System.out.println("Agent business!");
11         int money = boss.sales("xxl");// Call the interface's methods, but the way they are actually called is unchanged
12         System.out.println("Clothing prices:" + money);
13     }
14 
15 }

Keywords: PHP socket Java Junit log4j

Added by soulroll on Sun, 04 Aug 2019 02:45:27 +0300