1. 程式人生 > >為什麼SpringAOP使用JDK動態代理時好像沒有代理Object.[equals()、hashCode()、toString()]這三個方法

為什麼SpringAOP使用JDK動態代理時好像沒有代理Object.[equals()、hashCode()、toString()]這三個方法

*

Spring的AOP是通過JDK動態代理或者CGLib來生成目標物件的代理物件,然後將增強功能(Aspect【包括了Advice和Pointcut】)織入到符合條件(Pointcut)的類的方法(JoinPoint)上。


//這是JDK動態代理過程中要代理的4個方法
 private static Method m1;
 private static Method m3;
 private static Method m0;
 private static Method m2;

 m1 = Class.forName("java.lang.Object").getMethod("equals"
, new Class[] { Class.forName("java.lang.Object") }); m3 = Class.forName("pers.mine.SpringAOP.vo.KongFuInterface").getMethod("random", new Class[0]); m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]); m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);

但是spring代理過程中並沒有將相應程式碼插入[equals()、hashCode()、toString()]三個方法中,為什麼呢?
答案在org.springframework.aop.framework.JdkDynamicAopProxy類中
這個類實現了InvocationHandler介面,說明SpringAOP是通過這個類實現動態代理的
在這個類的invoke方法中有

try {
            if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
                // The target does not implement the equals(Object) method itself.
                return equals(args[0]);
            }
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { // The target does not implement the hashCode() method itself. return hashCode(); } else if (method.getDeclaringClass() == DecoratingProxy.class) { // There is only getDecoratedClass() declared -> dispatch to proxy config. return AopProxyUtils.ultimateTargetClass(this.advised); } else if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) { // Service invocations on ProxyConfig with the proxy config... return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); } Object retVal; if (this.advised.exposeProxy) { // Make invocation available if necessary. oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } // May be null. Get as late as possible to minimize the time we "own" the target, // in case it comes from a pool. target = targetSource.getTarget(); if (target != null) { targetClass = target.getClass(); } // Get the interception chain for this method. List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); // Check whether we have any advice. If we don't, we can fallback on direct // reflective invocation of the target, and avoid creating a MethodInvocation. if (chain.isEmpty()) { // We can skip creating a MethodInvocation: just invoke the target directly // Note that the final invoker must be an InvokerInterceptor so we know it does // nothing but a reflective operation on the target, and no hot swapping or fancy proxying. Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); } else { // We need to create a method invocation... invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); // Proceed to the joinpoint through the interceptor chain. retVal = invocation.proceed(); } // Massage return value if necessary. Class<?> returnType = method.getReturnType(); if (retVal != null && retVal == target && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { // Special case: it returned "this" and the return type of the method // is type-compatible. Note that we can't help if the target sets // a reference to itself in another returned object. retVal = proxy; } else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) { throw new AopInvocationException( "Null return value from advice does not match primitive return type for: " + method); } return retVal; } finally { if (target != null && !targetSource.isStatic()) { // Must have come from TargetSource. targetSource.releaseTarget(target); } if (setProxyContext) { // Restore old proxy. AopContext.setCurrentProxy(oldProxy); } }

可以看到一開始開始使用if語句過濾了equals()、hashCode()兩個方法
toString()有點特殊[先寫到這,後續細究吧]。。。

相關推薦

為什麼SpringAOP使用JDK動態代理好像沒有代理Object.[equals()hashCode()toString()]方法

* Spring的AOP是通過JDK動態代理或者CGLib來生成目標物件的代理物件,然後將增強功能(Aspect【包括了Advice和Pointcut】)織入到符合條件(Pointcut)的類的方法(JoinPoint)上。 //這是JDK

淺析Object基類提供的Virtual Object.Equals, Static Object.Equals and Reference.Equals方法

override sting 簡單 了解 字段 發生 虛方法 覆蓋 出現   當我們去查看object.cs源代碼文件的時候,會發現object基類提供了三種判斷相等性的方法。弄清楚每種方法存在的原因,也就是具體解決了什麽問題,對我們理解.net判斷對象相等性的邏輯很有幫助

網站太強大了,沒有找不到的資源

不知道大家有沒有這樣的經歷。想搜尋某一樣東西的時候,開啟一款搜尋引擎,經過長時間的瀏覽,得到的結果卻不如人意。今天就告訴大家這三款神奇又好用的搜尋資源網站,讓你沒有找不到的資源。   一、Google www.google.cn   一款可

啟動白屏時間過長的解決辦法,第方法賊好用

你會很奇怪,為什麼有些app啟動時,會出現一會兒的黑屏或者白屏才進入Activity的介面顯示,但是有些app卻不會如QQ手機端,的確這裡要做處理一下。這裡先了解一下為什麼會出現這樣的現象,其實很簡單,簡歷一個簡單的例子就可以理解了。 其實,黑屏或者白屏這裡並不是不正常,而是還沒載入到佈局檔案,

MapReduce關於key的定義hashCode()equals(Object obj)compareTo(CustomCombineKey other)

1. mapreduce中自定義mapout、reduceinput的key key需實現WritableComparable<KEY> 介面 1.1 重寫下面的三個方法 1.2 重寫

java程式碼優化(二)——如何覆蓋Object的公用方法equalshashcodecompareTotoString

覆蓋equals方法時請遵守通用約定 什麼情況需要覆蓋equals方法? 當需要比較的類有自己的邏輯特點時,而Object的equals方法不能達到預期的效果時,就需要覆蓋equals比較類的屬性值。 覆蓋equals方法的通用約定 自反性——對於任何非null的物件

wait,notify,notifyAll,sleep這些方法都跟執行緒的狀態變化有關,為什麼jdk把前方法放在Object類裡面,而把sleep放在Thread類裡面?

首先,雖然這些方法都跟執行緒的狀態變化有關,但wait(),notify(),notifyAll()這三個方法在用法上就跟sleep()方法不太一樣,wait(),notify(),notifyAll()必須在sychronized同步程式碼塊中使用,且要用當前執行緒持有的鎖

SpringBoot配置攔截器實現HandlerInterceptor接口沒有提示重寫方法的問題

mage http hand virt 圖片 就是 新的 分享圖片 重寫 查看源碼發現沒報錯的原因是:發現HandlerInterceptor接口類中的三個方法都是default修飾. java默認實現了該方法,再看版本信息5.1.6 Java 8中引入了一個新的

CS4:用戶在使用IE訪問FTP server 遇到 502代理錯誤,沒有彈出輸入用戶憑據對話框

images tmg proc view site 彈出 request 劃線 mar 客戶問題概括:用戶在使用IE 訪問FTP server 時遇到 502代理錯誤。用戶在瀏覽器使用 ftp://ftpServerName 訪問自檢FTP server 時沒有提示輸入用戶

Spring通過註解annotation方式注入Bean,採用動態代理,那麼JDK代理和CGLIB代理區別?

切面程式設計是Spring中非常重要的一個模組,切面程式設計的實現原理是動態代理,那麼動態代理又有兩種實現方式:一種方法是直接實現JDK中的InvocationHandler介面,另一種方法是繼承CGLIB。 首先如果不是很清楚兩者的區別的話,記住一般情況下Invocati

java實現動態代理遇到的問題

java中實現動態代理,用InvocationHandler和Proxy就可以了。 所謂的動態代理,就是真正執行操作的物件不是原始的物件,就像A拜託B買東西,然後B買好東西后包裝好給A。 例: void iTest() throws Exception {

Spring 動態代理是如何解決迴圈依賴的?為什麼要使用三級快取?

### 前言 在研究 [『 Spring 是如何解決迴圈依賴的 』](https://mp.weixin.qq.com/s/UlUQ95gVt8I8wmVOEjn1aw) 的時候,瞭解到 Spring 是藉助*三級快取*來解決迴圈依賴的。 同樣在上一節留下了疑問: 1. 迴圈依賴為什麼要使用三級快取?而

動態代理相對於靜態代理的優勢

oid 無需 int class ash 總結 proxy etc ride 整理自知乎;整理自知乎;整理自知乎 靜態代理與動態代理 代理模式是一種設計模式,典型的分為靜態代理和動態代理。 先講靜態代理 首先給個場景,現有個FontProvider接口,用於獲取字體

Nginx反向代理tomcat日誌獲取真實IP

director div tom log sna tomcat XML localhost 如果 對於nginx+tomcat這種架構,如果後端tomcat配置保持默認,那麽tomcat的訪問日誌裏,記錄的就是前端nginx的IP地址,而不是真實的訪問IP。因此,需

【設計模式】代理模式:靜態代理動態代理,spring aop

spring 實現接口 找到 master 代碼 -s result java 統一 代理模式分為靜態代理和動態代理。我們拿鏈家來舉例子,我們本人是真實的對象,有真實的業務需求:需要去找房子;鏈家是中介,是代理類,他來幫我執行找房子的這個操作。 靜態代理:   1.實現一個

動態代理與子類代理

llb ram 9.png str width row and lib cal 1.動態代理 java.lang.reflect.Proxy 對象 幫我們生成一個代理對象來完成這個記錄日誌的工作 動態代理:被代理的對象一定要實現接口 loader: 類加載器,跟被代理

java 代理模式(靜態代理動態代理Cglib代理) 轉載

cas 代理人 缺點 intercept 必須 lan itcast 技術 有時 Java的三種代理模式 1.代理模式 代理(Proxy)是一種設計模式,提供了對目標對象另外的訪問方式;即通過代理對象訪問目標對象.這樣做的好處是:可以在目標對象實現的基礎上,增強額外的功能操

Java動態代理XML正則

類的方法 編寫 編碼 new 就是 返回 st2 spl 5.2.1 15.1 動態代理 在之後學習Spring框架時,Spring框架有一大核心思想,就是AOP,(Aspact-Oriented-Programming 面向切面編程) 而AOP的原理就是J

nginx做靜態代理css載入不出問題解決

有次專案中用到了前後端分離,nginx做了前端的靜態代理。當配置nginx後,訪問頁面時出現了以下的bug css檔案實際上已經被加載出來了,但是頁面卻沒有顯示效果。報錯是這樣的: Resource interpreted as Stylesheet but transfer

java中代理,靜態代理動態代理以及spring aop代理方式,實現原理統一彙總 Spring中AOP的兩種代理方式(Java動態代理和CGLIB代理

若代理類在程式執行前就已經存在,那麼這種代理方式被成為 靜態代理 ,這種情況下的代理類通常都是我們在Java程式碼中定義的。 通常情況下, 靜態代理中的代理類和委託類會實現同一介面或是派生自相同的父類。 一、概述1. 什麼是代理我們大家都知道微商代理,簡單地說就是代替廠家賣商品,廠家“委託”代理為