Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to understand Java reflection and dynamic proxy

2025-01-29 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article mainly introduces "how to understand Java reflection and dynamic proxy". In daily operation, I believe many people have doubts about how to understand Java reflection and dynamic proxy. The editor consulted all kinds of materials and sorted out simple and easy-to-use operation methods. I hope it will be helpful to answer the doubts of "how to understand Java reflection and dynamic proxy"! Next, please follow the editor to study!

Reflection

Reflection mechanism is a basic function provided by Java language, which gives the program the ability to introspect at run time. Simply put, through reflection, you can get, detect, and call the properties and methods of an object at run time.

Usage scene of reflection

There are many scenarios for reflection in reality, such as the following.

Use scenario 1: programming tools such as IDEA or Eclipse will prompt the code (property or method name) when writing code because of the use of reflection.

Use scenario 2: many well-known frameworks also use reflection in order to make the program more elegant and concise.

For example, Spring can be configured to load different classes and call different methods, as shown in the following code:

Java reflection and dynamic proxy, you'll understand it.

For example, when MyBatis builds a query using the Sql of an external class in Mapper, the code looks like this:

@ SelectProvider (type = PersonSql.class, method = "getListSql") List getList (); class PersonSql {public String getListSql () {String sql = new SQL () {{SELECT ("*"); FROM ("person");}} .toString (); return sql;}}

Use scenario 3: database connection pool, and different types of database drivers will also be called using reflection. The code is as follows:

String url = "jdbc:mysql://127.0.0.1:3306/mydb"; String username = "root"; String password = "root"; Class.forName ("com.mysql.jdbc.Driver"); Connection connection = DriverManager.getConnection (url, username, password)

Of course, there are many other similar use scenarios of reflection, which are not listed here. Readers can draw examples and think about the other scenarios that use reflection in normal development.

Basic use of reflection

Let's learn the basic use of reflection by calling a method in the class through reflection.

There are three situations in which methods in a class are called using reflection:

Call static method

Call public methods

Call private methods

Suppose there is an entity class MyReflect that contains the above three methods. The code is as follows:

Package com.interview.chapter4; class MyReflect {/ / static method public static void staticMd () {System.out.println ("Static Method");} / / Public method public void publicMd () {System.out.println ("Public Method");} / / Private method private void privateMd () {System.out.println ("Private Method");}}

Let's take a look at how to call these three types of methods using reflection.

① reflection calls static methods

Class myClass = Class.forName ("com.interview.chapter4.MyReflect"); Method method = myClass.getMethod ("staticMd"); method.invoke (myClass)

② reflection calls public methods

Class myClass = Class.forName ("com.interview.chapter4.MyReflect"); / / create instance object (equivalent to new) Object instance = myClass.newInstance (); Method method2 = myClass.getMethod ("publicMd"); method2.invoke (instance)

③ reflection calls private methods

Class myClass = Class.forName ("com.interview.chapter4.MyReflect"); / / create instance object (equivalent to new) Object object = myClass.newInstance (); Method method3 = myClass.getDeclaredMethod ("privateMd"); method3.setAccessible (true); method3.invoke (object)

Summary of reflection usage

The reflection gets the calling class through Class.forName (), the reflection gets the class instance through newInstance (), which is equivalent to new a new object, and the reflection gets the method through getMethod (). After getting the class method, use invoke () to call the class method. If the class method is private, the access restrictions of the method need to be modified through setAccessible (true), which is the basic use of reflection.

Dynamic agent

Dynamic agent can be understood to mean that what should be done by yourself is handed over to others to deal with it. This process is called dynamic agent.

Usage scenarios of dynamic agents

A well-known usage scenario for dynamic agents is aspect-oriented programming (AOP) in Spring. For example, dependency injection @ Autowired and transaction annotations @ Transactional are implemented using dynamic proxies.

Dynamic proxies can also encapsulate some RPC calls or implement a global interceptor through the proxy.

The relationship between dynamic Agent and reflection

The dynamic proxy provided by JDK natively is implemented through reflection, but the implementation of dynamic proxy can also be ASM (a short bytecode operation framework), cglib (based on ASM), and so on, which is not limited to reflection.

Let's look at the JDK native dynamic proxy and the implementation of cglib respectively.

1) JDK native dynamic proxy

Interface Animal {void eat ();} class Dog implements Animal {@ Override public void eat () {System.out.println ("The dog is eating");}} class Cat implements Animal {@ Override public void eat () {System.out.println ("The cat is eating");}} / / JDK proxy class class AnimalProxy implements InvocationHandler {private Object target / / proxy object public Object getInstance (Object target) {this.target = target; / / get proxy object return Proxy.newProxyInstance (target.getClass (). GetClassLoader (), target.getClass () .getInterfaces (), this);} @ Override public Object invoke (Object proxy, Method method, Object [] args) throws Throwable {System.out.println (before call) Object result = method.invoke (target, args); / / method call System.out.println ("after call"); return result;}} public static void main (String [] args) {/ / JDK dynamic proxy call AnimalProxy proxy = new AnimalProxy (); Animal dogProxy = (Animal) proxy.getInstance (new Dog ()); dogProxy.eat ();}

In the above code, we print a simple message before and after all requests through dynamic proxies.

Note: JDK Proxy can only proxy classes that implement the interface (even extends inherited classes cannot be proxied).

2) cglib dynamic proxy

If you want to add a reference to cglib with the cglib implementation, if it is a maven project, add the following code directly:

Cglib cglib 3.2.12

For the specific implementation of cglib, please refer to the following code:

Class Panda {public void eat () {System.out.println ("The panda is eating");}} class CglibProxy implements MethodInterceptor {private Object target; / / proxy object public Object getInstance (Object target) {this.target = target; Enhancer enhancer = new Enhancer (); / / set the parent class to the instance class enhancer.setSuperclass (this.target.getClass ()) / / callback method enhancer.setCallback (this); / / create proxy object return enhancer.create ();} public Object intercept (Object o, Method method, Object [] objects, MethodProxy methodProxy) throws Throwable {System.out.println (before calling); Object result = methodProxy.invokeSuper (o, objects) / execute method call System.out.println ("after call"); return result;}} public static void main (String [] args) {/ / cglib dynamic proxy call CglibProxy proxy = new CglibProxy (); Panda panda = (Panda) proxy.getInstance (new Panda ()); panda.eat ();}

The results of the execution of the above procedures:

Before calling

The panda is eating

After calling

As can be seen from the above code, the call of cglib calls invokeSuper for dynamic proxy by implementing the intercept method of the MethodInterceptor interface. It can directly carry on the dynamic proxy to the ordinary class, and does not need to complete through the interface like the JDK proxy. It is worth mentioning that the dynamic proxy of Spring is also realized through cglib.

Note: the underlying cglib implements dynamic proxies through subclasses inheriting the proxied object, so the proxy class cannot be the final class (final), otherwise an error java.lang.IllegalArgumentException: Cannot subclass final class xxx will be reported.

Relevant interview questions

1. What problem does the dynamic agent solve?

Answer: first of all, it is a proxy mechanism. if we are familiar with the proxy pattern in the design pattern, we will know that the proxy can be seen as a wrapper of the calling target, so that our call to the target code does not occur directly, but through the proxy, through which the caller can be decoupled from the implementer. For example, to make RPC calls, you can provide a more friendly interface through proxies, and you can also use proxies to act as a global interceptor.

two。 What is the relationship between dynamic proxy and reflection?

A: reflection can be used to implement dynamic proxies, but there are other ways to implement dynamic proxies, such as ASM (a short bytecode manipulation framework), cglib and so on.

3. What is wrong with the following description?

Higher performance of A:cglib there are dynamic proxies using cglib in B:Spring there are dynamic proxies native to JDK in C:Spring D:JDK native dynamic agents have higher performance

A: d

Topic Analysis: there are two ways to implement Spring dynamic agents: cglib and JDK native dynamic agents.

4. Please complete the following code?

Class MyReflect {/ / Private method private void privateMd () {System.out.println ("Private Method");}} class ReflectTest {public static void main (String [] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {Class myClass = Class.forName ("MyReflect"); Object object = myClass.newInstance (); / / add this line of code method.setAccessible (true) Method.invoke (object);}}

Answer: Method method = myClass.getDeclaredMethod ("privateMd")

Topic analysis: this question is mainly about the acquisition of private methods, which is not obtained through getMethod (), but through getDeclaredMethod ().

Is it true that 5.cglib can represent any class? Why?

Answer: this sentence is not entirely true, because cglib can only proxy ordinary classes that can have subclasses. For the final class (final), cglib cannot implement dynamic proxies, because the underlying layer of cglib implements dynamic proxies by inheriting subclasses of proxy classes, so cglib cannot be used by inherited classes.

What is the difference between 6.JDK native dynamic proxy and cglib?

A: the difference between JDK native dynamic proxy and cglib is as follows:

JDK native dynamic proxy is implemented based on interface, does not need to add any dependencies, and can smoothly support the upgrade of JDK version.

Cglib does not need to implement interfaces, can directly proxy ordinary classes, and needs to add dependency packages for higher performance.

7. Why do JDK native dynamic proxies have to be done through interfaces?

A: this is due to the original design of JDK. Let's take a look at the source code of the dynamic proxy implementation method newProxyInstance ():

/ *. * @ param loader the class loader to define the proxy class * @ param interfaces the list of interfaces for the proxy class to implement *. * / @ CallerSensitivepublic static Object newProxyInstance (ClassLoader loader, Class [] interfaces, InvocationHandler h) throws IllegalArgumentException {/ / omit other code

Let's look at the declaration of the first two parameters:

Loader: the classloader, that is, target.getClass (). GetClassLoader ()

Interfaces: list of interface implementations of the interface proxy class

Looking at the above parameter description, we understand that the native dynamics of JDK can only be done by implementing the interface.

At this point, the study on "how to understand Java reflection and dynamic proxy" is over. I hope to be able to solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report