当前位置:网站首页>How does cglib implement multiple agents?
How does cglib implement multiple agents?
2020-11-06 21:04:00 【Java technology stack】
because Cglib Own design , Can't be realized in Proxy Put another layer of packaging on the outside Proxy(JDK Proxy Sure ), The following errors are usually reported :
Caused by: java.lang.ClassFormatError: Duplicate method name "newInstance" with signature "..........
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
... 10 more
Error source code :
net.sf.cglib.proxy.Enhancer#generateClass(ClassVisitor v)
...... Omit code
// The following part of the bytecode , Each generation Proxy Instances will be inserted .JVM Error will be reported when verifying bytecode .
if (useFactory || currentData != null) {
int[] keys = getCallbackKeys();
emitNewInstanceCallbacks(e);
emitNewInstanceCallback(e);
emitNewInstanceMultiarg(e, constructorInfo);
emitGetCallback(e, keys);
emitSetCallback(e, keys);
emitGetCallbacks(e);
emitSetCallbacks(e);
}
adopt dump The byte code is more intuitive :


In the generated bytecode ,newInstance The method is repetitive .
dump Method :System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "./");
How to deal with it ?
Implementing multiple agents , There's a lame way , for example JDK and Cglib Use a combination of . Or you can use it directly JDK agent . But sometimes , Operations on classes don't work .
I refer to Spring How to do it , A simple multi proxy is implemented .
Spring The scene of : A target method is more than one AOP Intercept , In this case, multiple agents are needed .
Spring The code to create the agent is located in :org.springframework.aop.framework.CglibAopProxy#getProxy
Spring AOP Interceptor class :org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor
Of the class intercept Method is the core of implementing multiple agents .
Every time the target method is called , According to the target method , Generate a call object with multiple intercept points of the target method .
// Generate call object
CglibMethodInvocation c = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy);
// call
c.proceed();
Then call the parent class proceed Method , It's actually a filter mode :
public Object proceed() throws Throwable {
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// Skip this interceptor and invoke the next in the chain. recursive .
return proceed();
}
}
else {
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
Pay attention to the last line , This is where the intercept point is called invoke Method , The specific implementation class of this intercept point :AspectJAroundAdvice.
Take a look at his invoke Method :
public Object invoke(MethodInvocation mi) throws Throwable {
ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
// AOP I'm familiar with it ProceedingJoinPoint Parameters !!!!
ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
JoinPointMatch jpm = getJoinPointMatch(pmi);
return invokeAdviceMethod(pjp, jpm, null, null);
}
Usually , We write... In the business AOP When intercepting code , Will be exposed to this ProceedingJoinPoint Parameters , And then call him. proceed Method calls the target method .
This ProceedingJoinPoint Class proceed Method will eventually call back DynamicAdvisedInterceptor Right proceed Method . Until all intercept points are executed . Finally execute the method of the target class .
therefore , Every intercepted method you set , If this method is intercepted many times , So there's going to be multiple MethodInterceptor( No cglib Of ) Instances form call chains . And then through ProceedingJoinPoint Pass it on to you for interception .
So much bedding , Let's make a simple one ourselves , Can not be like Spring So complicated !!!!
Simple implementation Cglib Multiple agents
Let's talk about the idea first : It's actually very simple , Just put a filter chain in the interceptor , The user intercepts multiple calls in the filter . These interceptors , Just like you add @Around Method of annotation , It's just that we don't have Spring It's just convenient .
Draw a picture UML chart :

The code is as follows :
Test.java & SayHello.java
public class Test {
public static void main(String[] args) {
Object proxy = ProxyFactory.create().getProxy(new SayHello());
proxy.toString();
}
static class SayHello {
@Override
public String toString() {
return "hello cglib !";
}
}
}
ProxyFactory.java & Interceptor.java
public class ProxyFactory {
private ProxyFactory() {}
public static ProxyFactory create() {
return new ProxyFactory();
}
public Object getProxy(Object origin) {
final Enhancer en = new Enhancer();
en.setSuperclass(origin.getClass());
List<Chain.Point> list = new ArrayList<>();
list.add(new Point1());
list.add(new Point2());
en.setCallback(new Interceptor(new Chain(list, origin)));
return en.create();
}
private class Interceptor
implements MethodInterceptor {
Chain chain;
public Interceptor(Chain chain) {
this.chain = chain;
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy)
throws Throwable {
return chain.proceed();
}
}
}
Chain.java & Point.java
public class Chain {
private List<Point> list;
private int index = -1;
private Object target;
public Chain(List<Point> list, Object target) {
this.list = list;
this.target = target;
}
public Object proceed() {
Object result;
if (++index == list.size()) {
result = (target.toString());
System.err.println("Target Method invoke result : " + result);
} else {
Point point = list.get(index);
result = point.proceed(this);
}
return result;
}
interface Point {
Object proceed(Chain chain);
}
}
Point1.java & Point2.java
public class Point1 implements Chain.Point {
@Override
public Object proceed(Chain chain) {
System.out.println("point 1 before");
Sleep.sleep(20);
Object result = chain.proceed();
Sleep.sleep(20);
System.out.println("point 1 after");
return result;
}
}
public class Point2 implements Chain.Point {
@Override
public Object proceed(Chain chain) {
System.out.println("point 2 before");
Sleep.sleep(20);
Object result = chain.proceed();
Sleep.sleep(20);
System.out.println("point 2 after");
return result;
}
}
function Test main result :

In line with expectations .
author : Mona · Ludao
source :https://www.cnblogs.com/stateis0/p/9744123.html Recent hot article recommends :
1.Java 15 Official release , 14 A new feature , Refresh your mind !!
2. Finally, I got it through open source projects IntelliJ IDEA Activation code , It's delicious !
3. I use Java 8 Wrote a piece of logic , I can't understand it , You try ..
4. To hang up Tomcat ,Undertow It's very powerful !!
5.《Java Development Manual ( Song Mountain version )》 The latest release , Download it quickly !
I think it's good , Don't forget to like it + Forward !
版权声明
本文为[Java technology stack]所创,转载请带上原文链接,感谢
边栏推荐
- 代码重构之法——方法重构分析
- Introduction to the structure of PDF417 bar code system
- Summary of front-end performance optimization that every front-end engineer should understand:
- Even liver three all night, jvm77 high frequency interview questions detailed analysis, this?
- Network programming NiO: Bio and NiO
- Multi robot market share solution
- Bitcoin once exceeded 14000 US dollars and is about to face the test of the US election
- Contract trading system development | construction of smart contract trading platform
- Using an example to understand the underlying processing mechanism of JS function
- 美团内部讲座|周烜:华东师范大学的数据库系统研究
猜你喜欢

美团内部讲座|周烜:华东师范大学的数据库系统研究

ES6 learning notes (2): teach you to play with class inheritance and class objects

ORA-02292: 违反完整约束条件 (MIDBJDEV2.SYS_C0020757) - 已找到子记录

Even liver three all night, jvm77 high frequency interview questions detailed analysis, this?

消息队列(MessageQueue)-分析

Gather in Beijing! The countdown to openi 2020

Look! Internet, e-commerce offline big data analysis best practice! (Internet disk link attached)

行为型模式之解释器模式

Will blockchain be the antidote to the global epidemic accelerating the transformation of Internet enterprises?

What is alicloud's experience of sweeping goods for 100 yuan?
随机推荐
What are the common problems of DTU connection
Basic usage of GDB debugging
统计项目代码行数
Axios learning notes (2): easy to understand the use of XHR and how to package simple Axios
Chainlink brings us election results into blockchain everipedia
意派Epub360丨你想要的H5模板都在这里,电子书、大转盘、红包雨、问卷调查……
How to play sortable JS vuedraggable to realize nested drag function of forms
Zero basis to build a web search engine of its own
Application of restful API based on MVC
Outsourcing is really difficult. As an outsourcer, I can't help sighing.
Share with Lianyun: is IPFs / filecoin worth investing in?
jenkins安装部署过程简记
What are Devops
Gather in Beijing! The countdown to openi 2020
StickEngine-架构11-消息队列(MessageQueue)
使用 Iceberg on Kubernetes 打造新一代雲原生資料湖
Basic usage of Vue codemirror: search function, code folding function, get editor value and verify in time
检测证书过期脚本
In depth to uncover the bottom layer of garbage collection, this time let you understand her thoroughly
electron 實現檔案下載管理器