当前位置:网站首页>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]所创,转载请带上原文链接,感谢
边栏推荐
- 【自学unity2d传奇游戏开发】如何让角色动起来
- Summary of front-end performance optimization that every front-end engineer should understand:
- An article takes you to understand CSS gradient knowledge
- 如何对数据库账号权限进行精细化管理?
- Multi robot market share solution
- 嘉宾专访|2020 PostgreSQL亚洲大会阿里云数据库专场:王涛
- An article will take you to understand CSS alignment
- html+vue.js 實現分頁可相容IE
- 行为型模式之备忘录模式
- 统计项目代码行数
猜你喜欢
统计项目代码行数
Swagger 3.0 brushes the screen every day. Does it really smell good?
jenkins安装部署过程简记
image operating system windows cannot be used on this platform
Zero basis to build a web search engine of its own
事件监听问题
如何对数据库账号权限进行精细化管理?
mongo 用户权限 登录指令
Isn't data product just a report? absolutely wrong! There are university questions in this category
【字节跳动 秋招岗位开放啦】Ohayoo!放学别走,我想约你做游戏!!!
随机推荐
image operating system windows cannot be used on this platform
mongo 用户权限 登录指令
How to play sortable JS vuedraggable to realize nested drag function of forms
每个大火的“线上狼人杀”平台,都离不开这个新功能
Summary of front-end performance optimization that every front-end engineer should understand:
The AI method put forward by China has more and more influence. Tianda et al. Mined the development law of AI from a large number of literatures
【自学unity2d传奇游戏开发】如何让角色动起来
Try to build my mall from scratch (2): use JWT to protect our information security and perfect swagger configuration
What course of artificial intelligence? Will it replace human work?
What are manufacturing and new automation technologies?
游戏主题音乐对游戏的作用
An article will take you to understand CSS3 fillet knowledge
Markdown tricks
面试官: ShardingSphere 学一下吧
An article taught you to use HTML5 SVG tags
How to turn data into assets? Attracting data scientists
Swagger 3.0 brushes the screen every day. Does it really smell good?
事务的本质和死锁的原理
PHP application docking justswap special development kit【 JustSwap.PHP ]
【字节跳动 秋招岗位开放啦】Ohayoo!放学别走,我想约你做游戏!!!