Reflection is Java’s ability to dynamically obtain class information (such as class name, methods, fields, constructors, etc.) and manipulate classes at runtime.
Can access private objects/fields of a class, convenient for unit testing.
1
2
3
Field nameField = personClass.getDeclaredField("name");
nameField.setAccessible(true); // If the field is private, accessibility needs to be setSystem.out.println("Name before: "+ nameField.get(person));
Dynamic proxy, improves code reusability.
Spring framework.
Relationship between Generics, Reflection, and Type Inference
Dynamic Proxy
Advantage: Dynamically generates proxy classes, no need to manually define multiple proxy classes.
Define an interface UserService, in which I define method A that I want to be proxied.
Create a proxy class UserServiceProxy, which implements the InvocationHandler interface, meaning it overrides the invoke() method. Specifically, it adds the desired logic before or after calling method A. Inside invoke, method A is called via reflection.
The UserServiceImpl class implements the methods of the UserService interface.
In the main program, first create a UserServiceImpl class object, then use the newProxyInstance method to create a UserService class object, which is a proxy. The parameters of the method are: the class loader of UserService, the interface of UserService, and a UserServiceProxy class object.
userService can then call method A to achieve the desired logic.
Car car =new Car();
InvocationHandler carHandler =new DynamicProxyHandler(car); // Dynamically generate proxy class based on the passed objectVehicle carProxy = (Vehicle) Proxy.newProxyInstance(
car.getClass().getClassLoader(),
car.getClass().getInterfaces(),
carHandler);
carProxy.drive();
Motorcycle motorcycle =new Motorcycle();
InvocationHandler motorcycleHandler =new DynamicProxyHandler(motorcycle); // Dynamically generate proxy class based on the passed objectVehicle motorcycleProxy = (Vehicle) Proxy.newProxyInstance(
motorcycle.getClass().getClassLoader(),
motorcycle.getClass().getInterfaces(),
motorcycleHandler);
motorcycleProxy.drive();
Static proxy requires implementing a CarProxy and a Motorcycle proxy class separately for the Vehicle interface, and passing a Car and Motor object respectively.
CGLib Proxy
When the Spring framework chooses which proxy method to use, it uses JDK Proxy if there is an interface, and CGLib if there is no interface.
For example, if there is a class that does not implement an interface, and you want to add some functionality to its methods, you can use CGLIB.
Define the implementation class.
Define an Interceptor class that implements the MethodInterceptor interface, and implement the desired proxy logic within it.
Use Enhancer to set its superclass to the target class, and then set the callback, which is the method interceptor. This allows CGLIB to dynamically generate a subclass of the target class as the proxy class at runtime.
Scenario
JDK Proxy
CGLib Proxy
Proxy generation speed
Faster (directly generates interface proxy)
Slower (needs to generate subclass and enhance bytecode)
Method invocation speed
Slower (reflection invocation)
Faster (directly calls subclass method)
Memory usage
Low (lightweight proxy class)
Higher (generates subclass occupies more metaspace)