java Interview Common Mode Questions Agent Mode
- 2021-09-12 01:06:21
- OfStack
1. Static proxy
Static agent role analysis:
Abstract roles: 1. Use interfaces or abstract classes to implement them. Real role: The role being represented. Proxy role: Proxy real role, proxy real role, 1 will do a number of subsidiary operations. Caller: Use the proxy role to do some operations.We take tenants renting houses as an example, involving tenants, intermediaries and landlords. (The landlord is the agent object and the intermediary is the agent object)
Tenants rent houses in the east of the house through the intermediary, and the agent intermediary needs to find tenants to rent houses and obtain intermediary fees from them.
Code implementation:
Rent.java
That is, abstract roles
// Abstract role: renting a house
public interface Rent {
public void rent();
}
Host.java
That is, the real role
// Real character : The landlord, the landlord wants to rent the house
public class Host implements Rent{
public void rent() {
System.out.println(" House rental ");
}
}
Proxy.java
That is, the proxy role
// Agent role: Mediation
public class Proxy implements Rent {
private Host host;
public Proxy() { }
public Proxy(Host host) {
this.host = host;
}
// Rent a house
public void rent(){
seeHouse();
host.rent();
fare();
}
// House-viewing
public void seeHouse(){
System.out.println(" Show the tenants the house ");
}
// Collect agency fees
public void fare(){
System.out.println(" Collect agency fees ");
}
}
Client.java
Caller, that is, customer
// Customer class, 1 All customers will go to the agent!
public class Client {
public static void main(String[] args) {
// The landlord wants to rent a house
Host host = new Host();
// Intermediary helps landlord
Proxy proxy = new Proxy(host);
// You go to the agency!
proxy.rent();
}
}
Disadvantages of static proxy:
You need to create proxy classes manually, and if there are more objects to proxy, there are more and more proxy classes.
In order to solve this problem, there is a dynamic agent!
2. Dynamic Agent
When it comes to dynamic agent, you will definitely ask two ways to implement dynamic agent during the interview:
Let's look at the public first
UserService
Interface, and
UserServiceImpl
Implementation class:
/**
* @author csp
* @date 2021-06-03
*/
public interface UserService {
/**
* Login
*/
void login();
/**
* Logout
*/
void logout();
}
/**
* @author csp
* @date 2021-06-03
*/
public class UserServiceImpl implements UserService{
@Override
public void login() {
System.out.println(" User login ...");
}
@Override
public void logout() {
System.out.println(" User launch login ...");
}
}
JDK Dynamic Proxy
The code is as follows:
/**
* @author csp
* @date 2021-06-03
*/
public class JDKProxyFactory implements InvocationHandler {
// Target object ( Proxy object )
private Object target;
public JDKProxyFactory(Object target) {
super();
this.target = target;
}
/**
* Create a proxy object
*
* @return
*/
public Object createProxy() {
// 1. Get the class loader of the target object
ClassLoader classLoader = target.getClass().getClassLoader();
// 2. Obtain the implementation interface of the target object
Class<?>[] interfaces = target.getClass().getInterfaces();
// 3. No. 1 3 Parameters required 1 Implementation invocationHandler Interface object
Object newProxyInstance = Proxy.newProxyInstance(classLoader, interfaces, this);
return newProxyInstance;
}
/**
* A way to actually perform proxy enhancements
*
* @param proxy Proxy object .1 Do not use
* @param method Methods that need enhancement
* @param args Parameters in the method
* @return
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("JDK Dynamic proxy: login / Logic check before logout ......");
Object invoke = method.invoke(target, args);
System.out.println("JDK Dynamic proxy: login / Log print after logout ......");
return invoke;
}
public static void main(String[] args) {
// 1. Create an object
UserServiceImpl userService = new UserServiceImpl();
// 2. Create a proxy object
JDKProxyFactory jdkProxyFactory = new JDKProxyFactory(userService);
// 3. Invoke enhanced methods of proxy objects , Get the enhanced object
UserService userServiceProxy = (UserService) jdkProxyFactory.createProxy();
userServiceProxy.login();
System.out.println("==================================");
userServiceProxy.logout();
}
}
The output is as follows:
CGLIB Dynamic AgentJDK Dynamic Proxy: Logic Verification Before Login/Logout......
User Login...
JDK Dynamic Agent: Log printing after login/logout......
==================================
JDK Dynamic Proxy: Logic Verification Before Login/Logout......
User launch login...
JDK Dynamic Agent: Log printing after login/logout......
The code is as follows:
/**
* @author csp
* @date 2021-06-03
*/
public class CglibProxyFactory implements MethodInterceptor {
// Target object ( Proxy object )
private Object target;
// Pass the target object using the constructor
public CglibProxyFactory(Object target) {
super();
this.target = target;
}
/**
* Create a proxy object
*
* @return
*/
public Object createProxy() {
// 1. Create Enhancer
Enhancer enhancer = new Enhancer();
// 2. Object of the target object class
enhancer.setSuperclass(target.getClass());
// 3. Set callback action
enhancer.setCallback(this);
return enhancer.create();
}
/**
* A way to actually perform proxy enhancements
* @param o Proxy object
* @param method Methods to Enhance
* @param objects Parameters to enhance the method
* @param methodProxy Proxy for the method to be enhanced
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("cglib Dynamic proxy: login / Logic check before logout ......");
Object invoke = method.invoke(target, objects);
System.out.println("cglib Dynamic proxy: login / Log print after logout ......");
return invoke;
}
public static void main(String[] args) {
// 1. Create an object
UserServiceImpl userService = new UserServiceImpl();
// 2. Create a proxy object
CglibProxyFactory cglibProxyFactory = new CglibProxyFactory(userService);
// 3. Invoke enhanced methods of proxy objects , Get the enhanced object
UserService userServiceProxy = (UserService) cglibProxyFactory.createProxy();
userServiceProxy.login();
System.out.println("==================================");
userServiceProxy.logout();
}
}
The test results are as follows:
cglib Dynamic Proxy: Logic Verification Before Login/Logout......
User Login...
cglib Dynamic Agent: Log printing after login/logout......
==================================
cglib Dynamic Proxy: Logic Verification Before Login/Logout......
User launch login...
cglib Dynamic Agent: Log printing after login/logout......
Question 1: What is the difference between JDK dynamic agent and CGLIB dynamic agent?
JDK dynamic proxy essentially implements the interface of the proxy object, while CGLib essentially inherits the proxy object and covers the methods in it.
② JDK dynamic proxy can only generate proxies for classes that implement interfaces, while CGLib does not have this restriction. However, because CGLib uses an inherited implementation, CGLib cannot set the
final
Class,
private
Methods and
static
Method for proxy.
③ JDK dynamic agent is built in JDK, and CGLib dynamic agent needs to be introduced into the third party
jar
Bag.
④ In calling proxy methods, JDK dynamic proxy is called through reflection mechanism, and CGLib is called directly through FastClass mechanism. (After reading an article, it is introduced that the simple understanding of FastClass is to use an index subscript as a reference, which can directly locate the method to be called and call it)
In terms of performance, before JDK1.7, CGLib was faster than JDK in execution efficiency due to the use of FastClass mechanism. However, with the continuous optimization of JDK dynamic proxy, JDK dynamic proxy has been obviously faster than CGLib since JDK 1.7.
Interview 2: Why can JDK dynamic proxies only generate proxies for classes that implement interfaces?
The fundamental reason is that the class generated by JDK dynamic proxy has inherited the Proxy class, so it is no longer possible to use inheritance to proxy the class.