当前位置:网站首页>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]所创,转载请带上原文链接,感谢
边栏推荐
- 2020年第四届中国 BIM (数字建造)经理高峰论坛即将在杭举办
- 检测证书过期脚本
- An article will take you to understand CSS3 fillet knowledge
- Live broadcast preview | micro service architecture Learning Series live broadcast phase 3
- To teach you to easily understand the basic usage of Vue codemirror: mainly to achieve code editing, verification prompt, code formatting
- What course of artificial intelligence? Will it replace human work?
- How about small and medium-sized enterprises choose shared office?
- An article takes you to understand CSS gradient knowledge
- Basic usage of Vue codemirror: search function, code folding function, get editor value and verify in time
- 【自学unity2d传奇游戏开发】如何让角色动起来
猜你喜欢
游戏主题音乐对游戏的作用
From overseas to China, rancher wants to do research on container cloud market
ORA-02292: 违反完整约束条件 (MIDBJDEV2.SYS_C0020757) - 已找到子记录
【转发】查看lua中userdata的方法
意派Epub360丨你想要的H5模板都在这里,电子书、大转盘、红包雨、问卷调查……
mongo 用户权限 登录指令
An article will introduce you to HTML tables and their main attributes
Use modelarts quickly, zero base white can also play AI!
C + + and C + + programmers are about to be eliminated from the market
An article will take you to understand CSS3 fillet knowledge
随机推荐
An article will take you to understand CSS3 fillet knowledge
Use modelarts quickly, zero base white can also play AI!
Ronglian completed US $125 million f round financing
嘉宾专访|2020 PostgreSQL亚洲大会阿里云数据库专场:曾文旌
EOS founder BM: what's the difference between UE, UBI and URI?
What is alicloud's experience of sweeping goods for 100 yuan?
Building a new generation cloud native data lake with iceberg on kubernetes
IPFs rudder filecoin landing at the same time, fil currency price broke a thousand
Introduction to Google software testing
開源一套極簡的前後端分離專案腳手架
Tron smart wallet PHP development kit [zero TRX collection]
ORA-02292: 违反完整约束条件 (MIDBJDEV2.SYS_C0020757) - 已找到子记录
游戏主题音乐对游戏的作用
【字节跳动 秋招岗位开放啦】Ohayoo!放学别走,我想约你做游戏!!!
Humor: hacker programming is actually similar to machine learning!
DC-1靶機
From overseas to China, rancher wants to do research on container cloud market
大数据处理黑科技:揭秘PB级数仓GaussDB(DWS) 并行计算技术
StickEngine-架构11-消息队列(MessageQueue)
【自学unity2d传奇游戏开发】地图编辑器