当前位置:网站首页>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]所创,转载请带上原文链接,感谢
边栏推荐
- 代码生成器插件与Creator预制体文件解析
- Get twice the result with half the effort: automation without cabinet
- window系统 本机查找端口号占用方法
- Contract trading system development | construction of smart contract trading platform
- JVM内存分配 -Xms128m -Xmx512m -XX:PermSize=128m -XX:MaxPermSize=512m
- Gather in Beijing! The countdown to openi 2020
- 意外的元素..所需元素..
- C + + and C + + programmers are about to be eliminated from the market
- 游戏开发中的新手引导与事件管理系统
- WeihanLi.Npoi 1.11.0/1.12.0 Release Notes
猜你喜欢

ES6 learning notes (4): easy to understand the new grammar of ES6

如何对数据库账号权限进行精细化管理?

Use modelarts quickly, zero base white can also play AI!

How to turn data into assets? Attracting data scientists

What are PLC Analog input and digital input

一路踩坑,被迫聊聊 C# 代码调试技巧和远程调试

【自学unity2d传奇游戏开发】地图编辑器

Live broadcast preview | micro service architecture Learning Series live broadcast phase 3

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

Building a new generation cloud native data lake with iceberg on kubernetes
随机推荐
jenkins安装部署过程简记
An article will introduce you to HTML tables and their main attributes
如何对数据库账号权限进行精细化管理?
Staying up late summarizes the key points of report automation, data visualization and mining, which is different from what you think
Humor: hacker programming is actually similar to machine learning!
An article takes you to understand CSS pagination examples
Basic usage of GDB debugging
ES6 learning notes (4): easy to understand the new grammar of ES6
意外的元素..所需元素..
每个大火的“线上狼人杀”平台,都离不开这个新功能
Summary of front-end interview questions (C, s, s) that front-end engineers need to understand (2)
Behind the first lane level navigation in the industry
JNI-Thread中start方法的呼叫與run方法的回撥分析
Zero basis to build a web search engine of its own
How about small and medium-sized enterprises choose shared office?
Live broadcast preview | micro service architecture Learning Series live broadcast phase 3
An article takes you to understand CSS gradient knowledge
C + + and C + + programmers are about to be eliminated from the market
Take you to learn the new methods in Es5
Kubernetes and OAM to build a unified, standardized application management platform knowledge! (Internet disk link attached)