• 周六. 10 月 12th, 2024

5G编程聚合网

5G时代下一个聚合的编程学习网

热门标签

【java_ The essential difference between dynamic agent and static agent

King Wang

1 月 3, 2022

Preface

There are many ways to distinguish between dynamic agent and static agent , But it’s not about the essence
This article mainly looks at this problem from the application layer from top to bottom

Application scenarios

Static proxy

 // Data preparation 
Order order = new Order();order.setUserId(1);
// Create a static agent 
OrderServiceStaticProxy orderServiceStaticProxy = new OrderServiceStaticProxy();
// Use static agent to save order number operation , Static agent agent saveOrder Method 
orderServiceStaticProxy.saveOrder(order);

A dynamic proxy

 // Data preparation 
Order order = new Order();order.setUserId(2);
// Create dynamic proxy objects 
IOrderService orderProxy = (IOrderService) new ServiceDynamicProxy(new OrderServiceImpl()).bind();
// Use dynamic agent to save order number operation 
orderProxy.saveOrder(order);

More application scenarios of dynamic agents

Look at the code difference

 // Create a static agent 
OrderServiceStaticProxy orderServiceStaticProxy = new OrderServiceStaticProxy();
 // Create dynamic proxy objects 
IOrderService orderProxy = (IOrderService) new ServiceDynamicProxy(new OrderServiceImpl()).bind();
myth ( Not exactly ): Static proxies are not interface oriented programming , prove :

Modify static proxy code

public class StaticProxy {

private Object target;
public StaticProxy(Object target) {

this.target = target;
}
public Object bind() {

return target;
}
public int saveOrder(Order order) throws Throwable {

IOrderService service;
if (target instanceof IOrderService) {

service = (IOrderService) target;
} else {

throw new RuntimeException(" The target class does not support this method ");
}
// Omit enhance logic 
return service.saveOrder(order);
}
}

Modified static agent application layer code , With dynamic agents As like as two peas , It will be mentioned below that when a proxy class is used to proxy multiple classes , The essence of the interface oriented feature of static proxy is existence bug Of

IOrderService orderProxy = (IOrderService) new StaticProxy(new OrderServiceImpl()).bind();

Essential difference 1. Expand the agency Method How difficult is it

1.1 Proxy the same class , And represent only one method

Dynamic agents and static agents have about the same amount of code , But dynamic agents are less efficient , Because dynamic agents Proxy.newProxyInstance() Will generate class File overhead is high .

1.2 Proxy the same class , There are many ways to expand agency
Static proxy
public class StaticProxy {

private Object target;
public StaticProxy(Object target) {

this.target = target;
}
public Object bind() {

return target;
}
public int saveOrder(Order order) throws Throwable {

IOrderService service;
if (target instanceof IOrderService) {

service = (IOrderService) target;
} else {

throw new RuntimeException(" The target class does not support this method ");
}
// Omit enhance logic 
return service.saveOrder(order);
}
/**
* Add a method to the proxy class that needs to be proxied , Every time you add a method , I'm going to write another method with the same name
*
*/
public int deleteOrder(Order order) throws Throwable {

IOrderService service;
if (target instanceof IOrderService) {

service = (IOrderService) target;
} else {

throw new RuntimeException(" The target class does not support this method ");
}
// Omit enhance logic 
return service.deleteOrder(order);
}
}
The realization of dynamic agent

It is very convenient to proxy all methods of a class , Set up before and after Method .

 @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

beforeMethod(argObject);
// Methods and parameters obtained by reflection 
Object object = method.invoke(target, args); // The original logic of the surrogate class , Get the return value of 
afterMethod();
return object;
}

If you only proxy a few methods of a class , There are two realizations
The first one is

 @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

if (method.getName().equals("XXX")) {

// before after
} else if...
else {

Object object = method.invoke(target, args); // The original logic of the surrogate class , Get the return value of 
}
return object;
}

The second kind
Containers can be written in classes , It’s better to write it in the configuration file

 @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

if ( Containers . Is there a (method.getName())) {

// before after
} else {

Object object = method.invoke(target, args); // The original logic of the surrogate class , Get the return value of 
}
return object;
}

Summary : Extend multiple methods of the same class , Dynamic agents are much better than static agents

Essential difference 2. Expand the agency class How difficult is it

2.1 The same proxy class proxies multiple proxied classes

Static proxy –> instanceof Judge to avoid misuse , Copy multiple methods ,bind() There will be Bug

 public Object bind() {

return target;
}
public int saveOrder(Order order) throws Throwable {

IOrderService service;
if (target instanceof IOrderService) {
 // Type check required 
service = (IOrderService) target;
} else {

throw new RuntimeException(" The target class does not support this method ");
}
return result;
}
/**
* Add a proxy class StorageService
*
*/
public int reduceStorage(Order order) throws Throwable {

StorageService service;
if (target instanceof StorageService) {

service = (StorageService ) target;
} else {

throw new RuntimeException(" The target class does not support this method ");
}
// Omit enhance logic 
return service.reduceStorage(order);
}
 IOrderService orderProxy = (IOrderService) new StaticProxy(new OrderServiceImpl()).bind();
// The realization of hidden danger 
StaticProxy staticProxy = (StaticProxy) new StaticProxy(new OrderServiceImpl()).bind();
staticProxy.reduceStorage(); // This statement is exposed to the caller , Call and throw exception 

A dynamic proxy –> Confirm the interface to be proxy according to the parameters ,bind() The interface passed in by the method determines how many classes need to be proxied

 /**
* Directly through the incoming interface Class object , Add agent class
*/
public Object bind(){

// Get the... Of the proxy class class file 
Class cls = target.getClass();
ClassLoader classLoader = cls.getClassLoader();
Class[] interfaces = cls.getInterfaces(); // It can also be passed in as a parameter 
return Proxy.newProxyInstance(classLoader, interfaces,this);
}

The proxy class returned by the above dynamic proxy , Eliminate the hidden danger of static proxy . because Dynamic proxy is the proxy interface , Static proxies are concrete classes , If you want an agent , Proxy two classes , There are hidden dangers in static proxy .jdk The premise of eliminating hidden danger by dynamic proxy is , Both classes are interface implementation classes . If not , use cglib Dynamic agents can compensate for jdk The limitations of dynamic agents .

 /**
* invoke It's the routing of all the proxy methods , Don't do it instanceof The validity check of
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

if (method.getName().equals("XXX")) {

// before after
} else if...
else {

Object object = method.invoke(target, args); // The original logic of the surrogate class , Get the return value of 
}
return object;
}

Summary : Dynamic proxy can add the proxy class when the application layer passes in parameters , There is no big difference between the complexity of business logic , The key is to expand the ability of agent class , Dynamic agents are much better than static agents

Advantages of dynamic agents

1. Proxy a single object only in business logic , And enhance the way

The implementation of static agent is complex , Dynamic agents concentrate code on filter Can finish

 // filter Stop the swearing in the comments , agent request
HttpServletRequest proxyInstance = (HttpServletRequest) Proxy.newProxyInstance(
req.getClass().getClassLoader(),
new Class[]{
HttpServletRequest.class}, // Agent incoming servlet Of request
new InvocationHandler() {
 // Anonymous Proxy implementation 
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

if (method.getName().equals("getParameter")) {

String value = (String) method.invoke(req, args); // req yes filter Intercepted request 
// Remove all spaces , Pay attention to the return value 
value = value.replace(" ", "");
// Replace the swearing with... According to the length * Number , list It's a collection of stored swearing 
for (String s : list) {

if (value.contains(s)) {

StringBuilder temp = new StringBuilder();
for (int i = 0; i < s.length(); i++) {

temp.append("*");
}
value = value.replace(s, temp.toString());
}
}
return value;
}
return method.invoke(req, args);
}
});

2. The method can be dealt with in depth

Static proxy
The internal implementation of the method of the proxied class cannot be modified

public class StaticProxy {

private Connection connection;
public StaticProxy(Connection connection) {

this.connection = connection;
}
public Object bind(){

return connection;
}
/**
* Cannot modify... Within agent close() Internal implementation
*/
public void close() throws SQLException {

beforeMethod();
connection.close();
afterMethod();
}
}

A dynamic proxy –> Extract parameters , Modify the internal implementation

 @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

Object result = null;
if (method.getName().equals("close")) {

before();
if(method.getParameterCount() == 2) {

result = method.invoke(target, args[0], null); // Shield in parameter 
}
if(method.getParameterCount() == 3) {

// Modify the internal implementation 
result = new AnotherInst();
}
after(args[args.length - 1]);
return result ;
} else {

return method.invoke(target, args);
}
}

3. No adapter is needed to proxy the entire class

Static proxy –> Proxy entire class ( Database connection ), It’s expensive
If you want an agent MySQL Of Connection, You also need to copy the implementation into the proxy class , It’s a very complicated process

 // Turn into Connection The object of , It takes a lot of money to use it normally , It's equivalent to introducing an adapter 
proxyConnection = (Connection) proxy;

 Insert picture description here
A dynamic proxy

 // Agent class created by builder mode 
proxy = new ConnectionProxy.Builder(connection)
.buildConnectionPool(this)
// Put your own interface with Connection Interface fusion , Give it together jdk Dynamic proxy agent 
.buildAimClass(Connection.class, MyInterface.class)
.build();
// Turn into Connection The object of , Can be used for jdbc Of api
proxyConnection = (Connection) proxy;

发表回复