網(wǎng)站首頁 編程語言 正文
在開發(fā)中有時(shí)候會(huì)碰到需要展示tips說明信息的功能,比如打開道具列表,點(diǎn)擊相應(yīng)的道具并展示該道具的屬性等詳細(xì)信息,這時(shí)就有可能會(huì)出現(xiàn)tips的UI超出屏幕邊界的問題。
?
因此這里做一個(gè)自適應(yīng)的道具tips
首先需要設(shè)計(jì)tips的UI。
因?yàn)樾枰猆I隨著文本的長度自適應(yīng),確保始終能夠顯示全部的文本信息,因此Text的RectTransform也需要隨著文本高度自動(dòng)增加height,這里就會(huì)用到preferredHeight。
同時(shí)在Text自適應(yīng)后,其外部的背景bg也需要根據(jù)Text來自動(dòng)改變。
為了滿足以上的兩個(gè)需求,這里設(shè)計(jì)Tips的prefab為如下結(jié)構(gòu):
?
?
從以上結(jié)構(gòu)可知,Tips相對(duì)于TipsBg是自適應(yīng)的,并且保持上下左右完全對(duì)稱。注意這里設(shè)置TipsBg的pivot為“0,1”,默認(rèn)以鼠標(biāo)點(diǎn)擊位置為起點(diǎn)來顯示tips:
??
這樣的結(jié)構(gòu)就可以實(shí)現(xiàn)一個(gè)效果:當(dāng)改變TipsBg的RectTransform的寬高時(shí),由于Tips的sizeDelta會(huì)始終保持如上的數(shù)值不變,因此Tips的寬高也會(huì)自動(dòng)的改變,。
所以只需要在運(yùn)行時(shí)改變TipsBg的RectTransform的寬高即可。
那么如何設(shè)置TipsBg的寬高呢?
當(dāng)為Text設(shè)置文本內(nèi)容后,text.preferredHeight指的是針對(duì)該內(nèi)容,組件Text希望RectTransform能夠提供的height。如果rect.height == text.preferredHeight,則該文本可以完全顯示出來
這樣就可以計(jì)算出TipsBg期望的高度:
float yHeight = tipsTxt.preferredHeight + Mathf.Abs(tipsTxtRect.sizeDelta.y); //獲取tipsTxt的理想height,并計(jì)算tipsBg的目標(biāo)height
tipsBgRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, yHeight);
默認(rèn)情況下不需要改變TipsBg的寬度,所以寬度暫時(shí)不需要重新設(shè)置
注意:在設(shè)置RectTransform的寬高時(shí)使用UGUI自帶的方法:SetSizeWithCurrentAnchors。該方法會(huì)以UI當(dāng)前的pivot為起點(diǎn)來設(shè)置寬高,并且在設(shè)置完成后會(huì)自動(dòng)根據(jù)當(dāng)前的anchors分布來調(diào)整RectTransform面板中的顯示數(shù)據(jù)。
而且在獲取UI對(duì)象的position時(shí)也是該UI的pivot在世界空間下的坐標(biāo),而不是該UI四個(gè)anchor交叉點(diǎn)的坐標(biāo)。
基于pivot這樣的特性,在設(shè)置TipsBg的position時(shí),就可以在改變pivot的基礎(chǔ)上,直接將鼠標(biāo)點(diǎn)擊位置賦值給TipsBg,而不需要另外計(jì)算TipsBg超出邊界的數(shù)值,從而計(jì)算TipsBg的目標(biāo)position。
在設(shè)置完TipsBg的寬高后就有可能會(huì)出現(xiàn)tips邊界超出屏幕的問題,
那么如何檢測該tips是否超出了屏幕邊界并調(diào)整位置呢?
基于pivot的特性,直接把鼠標(biāo)位置賦值給TipsBg.position,因此就可以很容易計(jì)算出UI是否超出了屏幕邊界:
//通過設(shè)置TipsBg的pivot,而不是position,來避免超出屏幕邊界
if (Input.mousePosition.x + tipsBgRect.rect.width <= Screen.width) //默認(rèn)向右顯示
tipsBgPivot.x = 0; //當(dāng)該UI在X軸上的最大值依然在屏幕以內(nèi)時(shí)
else
tipsBgPivot.x = 1;
if (Input.mousePosition.y - tipsBgRect.rect.height >= 0) //默認(rèn)向下顯示
tipsBgPivot.y = 1;
else
tipsBgPivot.y = 0;
運(yùn)行時(shí)效果如下:紅點(diǎn)處為鼠標(biāo)點(diǎn)擊位置
通過改變TipsBg的pivot來調(diào)整UI位置,使其不超出屏幕邊界
雖然以上方法可以避免一部分超出邊界的情況,但如果文本過長,屏幕過小,調(diào)整之后依然會(huì)超出邊界,該如何呢?
首先需要獲取UI對(duì)象四個(gè)角的坐標(biāo)值:rectTransform.GetWorldCorners。該方法獲取到的坐標(biāo)點(diǎn)是以左下角為起點(diǎn),順時(shí)針方向依次輸出。通過檢測各個(gè)點(diǎn)的坐標(biāo)即可知道是否超出了邊界。
當(dāng)依然超出邊界時(shí),有兩種方式:一是改變TipsBg的寬度值,使得Tips的text.preferredHeight降低,從而避免;如果寬度已無法再調(diào)整,此時(shí)就只能改變Text的字體大小來改變text.preferredHeight
//雖然設(shè)置pivot后可以避免超出邊界的情況,但如果文本過長,依然有可能會(huì)超出邊界
//但這里只考慮垂直方向上依然超出邊界的情況,水平方向則不考慮——因?yàn)樗椒较虻膶挾瓤梢宰灾髟O(shè)定
//解決辦法:當(dāng)Y軸方向超出邊界時(shí),改變TipsBg的寬度,從而降低tipsTxt.preferredHeight
//獲取tipsBgRect的四角的坐標(biāo)
tipsBgRect.GetWorldCorners(worldCornersPos);
//從屏幕左下角開始順時(shí)針查看各個(gè)corner的Y軸坐標(biāo)值
if (worldCornersPos[0].y < 0 || worldCornersPos[1].y > Screen.height) //說明超出邊界
{
//Debug.Log("<color=yellow> " + width + " " + fontSize + " " + allTips[index] + " </color>");
if(width < Screen.width * 0.5f) //當(dāng)寬度尚且可以繼續(xù)調(diào)節(jié)時(shí)
{
tipsBgRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, Mathf.Min(width + 100, Screen.width * 0.5f)); //寬度最大不超過屏幕的一半
//當(dāng)tipsTxtRect的寬度改變后,其tipsTxt.preferredHeight也會(huì)即時(shí)改變——這一點(diǎn)很方便,很重要
tipsBgRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, tipsTxt.preferredHeight + Mathf.Abs(tipsTxtRect.sizeDelta.y));
//繼續(xù)下一次檢測
AutoAdjustTipsBounds(Mathf.Min(width + 100, Screen.width * 0.5f), fontSize);
}
else //寬度已無法再調(diào)節(jié),此時(shí)需要改變字體大小
{
tipsTxt.fontSize = fontSize - 1;
tipsBgRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, Screen.width * 0.5f);
tipsBgRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, tipsTxt.preferredHeight + Mathf.Abs(tipsTxtRect.sizeDelta.y));
//繼續(xù)下一次檢測
AutoAdjustTipsBounds(Screen.width * 0.5f, fontSize - 1);
}
}
通過以上遞歸方法的檢測,就可以一直調(diào)整到完全顯示在屏幕內(nèi)部的效果
完整代碼如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.IO;
using System.Text;
public class TipsAdjust : MonoBehaviour
{
Text tipsTxt;
RectTransform tipsTxtRect, tipsBgRect;
string[] allTips; //所有的tips信息
int index = 0; //對(duì)應(yīng)的tip索引
GameObject go; //為方便顯示點(diǎn)擊的位置,這里用紅點(diǎn)代替
float oldWidth = 0; //TipsBg的RectTransform原本的寬度
int oldFontSize = 0; //text組件的字體大小——可能用于自適應(yīng)調(diào)整
Vector2 tipsBgPivot = Vector2.zero;
Vector3[] worldCornersPos = new Vector3[4];
void Start()
{
//獲取組件對(duì)象
GameObject tipsObj = GameObject.Find("Tips");
tipsTxtRect = tipsObj.GetComponent<RectTransform>();
tipsTxt = tipsObj.GetComponent<Text>();
tipsBgRect = this.GetComponent<RectTransform>();
//初始化文本
string content = File.ReadAllText(Application.dataPath + "/Resources/Poems.txt");
allTips = content.Split(new string[] { "##" }, System.StringSplitOptions.None);
//注意:使用string.Split分割string時(shí)如果使用string類型的參數(shù),需要用上述的模式
//為方便顯示鼠標(biāo)點(diǎn)擊位置,這里使用紅點(diǎn)代替
go = GameObject.Instantiate(Resources.Load("Prefabs/RedPoint")) as GameObject;
go.transform.parent = this.transform.parent; //如果不設(shè)置parent,則新實(shí)例化的obj會(huì)脫離canvas層級(jí)而存在,因此不會(huì)顯示在畫面上
go.SetActive(false); //暫時(shí)不顯示
oldWidth = tipsBgRect.rect.width; //存儲(chǔ)原始寬度值
oldFontSize = tipsTxt.fontSize; //字體原始大小
}
void Update()
{
if (Input.GetMouseButtonDown(0))
OnItemBtnClick();
}
void OnItemBtnClick()
{
//為tips賦值
++index;
if (index >= allTips.Length) index = 0;
tipsTxt.text = allTips[index];
//設(shè)置Tips的寬高
//由于Tips相對(duì)于TipsBg是自適應(yīng)的,因此這里只需要計(jì)算TipsBg的寬高,Tips就會(huì)自適應(yīng)達(dá)到效果
tipsTxt.fontSize = oldFontSize; //針對(duì)自適應(yīng)有可能會(huì)改變字體大小,所以這里重新設(shè)置
tipsBgRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, oldWidth); //自適應(yīng)有可能會(huì)改變原有寬度,所以這里重新設(shè)置
float yHeight = tipsTxt.preferredHeight + Mathf.Abs(tipsTxtRect.sizeDelta.y); //獲取tipsTxt的理想height,并計(jì)算tipsBg的目標(biāo)height
tipsBgRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, yHeight);
//注意:
//由于TipsBg和Tips之間UI的設(shè)計(jì),因此tips的rect是肯定小于TipsBg的,
//所以可以明確知道tipsTxtRect.sizeDelta.y < 0。這里為了計(jì)算方便,直接使用Maths.Abs
//為了讓效果更明顯,這里直接展示鼠標(biāo)點(diǎn)擊位置
go.transform.position = Input.mousePosition;
if (!go.activeInHierarchy) go.SetActive(true);
AutoAdjustTipsBounds(oldWidth, oldFontSize);
}
//檢測是否超出屏幕邊界,并自適應(yīng)調(diào)整位置
void AutoAdjustTipsBounds(float width, int fontSize)
{
//通過設(shè)置TipsBg的pivot,而不是position,來避免超出屏幕邊界
if (Input.mousePosition.x + tipsBgRect.rect.width <= Screen.width) //默認(rèn)向右顯示
tipsBgPivot.x = 0; //當(dāng)該UI在X軸上的最大值依然在屏幕以內(nèi)時(shí)
else
tipsBgPivot.x = 1;
if (Input.mousePosition.y - tipsBgRect.rect.height >= 0) //默認(rèn)向下顯示
tipsBgPivot.y = 1;
else
tipsBgPivot.y = 0;
//設(shè)置TipsBg的pivot以及position,由于TipsBg和Tips之間自適應(yīng)的關(guān)系,Tips也會(huì)自動(dòng)實(shí)現(xiàn)效果
tipsBgRect.position = Input.mousePosition;
tipsBgRect.pivot = tipsBgPivot;
//雖然設(shè)置pivot后可以避免超出邊界的情況,但如果文本過長,依然有可能會(huì)超出邊界
//但這里只考慮垂直方向上依然超出邊界的情況,水平方向則不考慮——因?yàn)樗椒较虻膶挾瓤梢宰灾髟O(shè)定
//解決辦法:當(dāng)Y軸方向超出邊界時(shí),改變TipsBg的寬度,從而降低tipsTxt.preferredHeight
//獲取tipsBgRect的四角的坐標(biāo)
tipsBgRect.GetWorldCorners(worldCornersPos);
//從屏幕左下角開始順時(shí)針查看各個(gè)corner的Y軸坐標(biāo)值
if (worldCornersPos[0].y < 0 || worldCornersPos[1].y > Screen.height) //說明超出邊界
{
//Debug.Log("<color=yellow> " + width + " " + fontSize + " " + allTips[index] + " </color>");
if(width < Screen.width * 0.5f) //當(dāng)寬度尚且可以繼續(xù)調(diào)節(jié)時(shí)
{
tipsBgRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, Mathf.Min(width + 100, Screen.width * 0.5f)); //寬度最大不超過屏幕的一半
//當(dāng)tipsTxtRect的寬度改變后,其tipsTxt.preferredHeight也會(huì)即時(shí)改變——這一點(diǎn)很方便,很重要
tipsBgRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, tipsTxt.preferredHeight + Mathf.Abs(tipsTxtRect.sizeDelta.y));
//繼續(xù)下一次檢測
AutoAdjustTipsBounds(Mathf.Min(width + 100, Screen.width * 0.5f), fontSize);
}
else //寬度已無法再調(diào)節(jié),此時(shí)需要改變字體大小
{
tipsTxt.fontSize = fontSize - 1;
tipsBgRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, Screen.width * 0.5f);
tipsBgRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, tipsTxt.preferredHeight + Mathf.Abs(tipsTxtRect.sizeDelta.y));
//繼續(xù)下一次檢測
AutoAdjustTipsBounds(Screen.width * 0.5f, fontSize - 1);
}
}
}
}
?以上就實(shí)現(xiàn)了道具tips不超出邊界的需求。運(yùn)行效果如下:?
? ? ? ? ? ? ? ? ? ? ? ??
完整項(xiàng)目鏈接如下:AutoAdjustTipsProject.zip-Unity3D文檔類資源-CSDN下載
PS:
1.UGUI中rectTransform.sizeDelta 和 rectTransform.rect.size的區(qū)別:
“rect.size”代表的是該UI對(duì)象的真實(shí)寬高,不論瞄點(diǎn)如何設(shè)置;
“sizeDelta”表示UI對(duì)象的寬高比對(duì)應(yīng)的anchor矩形大或者小多少
驗(yàn)證:
如圖,Test01的四個(gè)錨點(diǎn)都在中心處,Test02的四個(gè)錨點(diǎn)則分散在四個(gè)角落:
?此時(shí)使用如下代碼分別輸出兩個(gè)對(duì)象的rect.size 和 sizeDelta:
GameObject test01 = GameObject.Find("Test01");
GameObject test02 = GameObject.Find("Test02");
RectTransform rect01 = test01.GetComponent<RectTransform>();
RectTransform rect02 = test02.GetComponent<RectTransform>();
Debug.Log("<color=green> rect01: " + rect01.sizeDelta + " " + rect01.rect.size + " </color>");
Debug.Log("<color=green> rect02: " + rect02.sizeDelta + " " + rect02.rect.size + " </color>");
?運(yùn)行結(jié)果如下:
?從以上結(jié)果可知:
1.當(dāng)UI對(duì)象的四個(gè)anchor匯聚在一處時(shí)(不論是否匯聚在中心,只要四個(gè)錨點(diǎn)不分散即可),此時(shí)sizeDelta與rect.size相同
2.當(dāng)在代碼中手動(dòng)設(shè)定UI對(duì)象的sizeDelta時(shí):
rect02.sizeDelta = new Vector2(-50, -50);
Debug.Log("<color=green> rect02: @@@@@@@@@@ " + rect02.sizeDelta + " " + rect02.rect.size + " </color>");
運(yùn)行結(jié)果如下:
而此時(shí)Test02對(duì)象的RectTransform:
Game視圖中的結(jié)果為:
總結(jié):
1.當(dāng)需要獲取UI對(duì)象的真實(shí)寬高時(shí)使用“rect.size”,而不要使用“sizeDelta”
2.如果要設(shè)置UI對(duì)象的寬高,則使用rect.SetSizeWithCurrentAnchors,不要直接的設(shè)置rect.size,該變量不具備set屬性
rect02.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 200); //設(shè)置寬度
rect02.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 300); //設(shè)置高度
Game視圖效果以及Test02的RectTransform變化如下:
??
注意:
1.當(dāng)使用SetSizeWithCurrentAnchors設(shè)置UI對(duì)象的寬高時(shí),是以當(dāng)前UI對(duì)象的pivot為中心點(diǎn)來設(shè)置的,例如以上Test02的pivot為“0.5,0.5”,由于屏幕空間以左下角為原點(diǎn),X向右遞增,Y向上遞增,所以“0.5,0.5”代表的是矩形屏幕的正中心點(diǎn)。在此基礎(chǔ)上拉伸UI對(duì)象的寬和高
倘若設(shè)置Test02的pivot為“0,0.5”,則代表以屏幕左側(cè)邊緣的正中為基準(zhǔn)點(diǎn)來拉伸UI對(duì)象的寬高:
?
pivot 和 anchor是兩個(gè)不同的屬性,這里并沒有用到anchor來影響UI對(duì)象的寬高顯示
2.設(shè)置了UI對(duì)象的寬高后,由于SetSizeWithCurrentAnchors還需要考慮該UI對(duì)象的anchor,在設(shè)置size后,UGUI會(huì)自動(dòng)根據(jù)UI對(duì)象的size和anchor來設(shè)置其rectTransform相應(yīng)的數(shù)值
3.UGUI中pivot 和 anchor是完全不同的兩個(gè)屬性,兩者的作用也不相同,由上述測試知曉
4.sizeDelta實(shí)際代表的意義:
當(dāng)四個(gè)錨點(diǎn)分散開時(shí):
sizeDelta.x = rect.x - anchorRectangle.x;
sizeDelta.y = rect.y - anchorRectangle.y;
所以當(dāng)sizeDelta.x <?0 時(shí)代表rect的寬度小于原有的矩形寬度,而在UGUI的RectTransform視圖中,卻是站在該UI對(duì)象的角度,超出anchor矩形的使用負(fù)數(shù),在anchor以內(nèi)的則用正數(shù)表示。
如此就會(huì)出現(xiàn)當(dāng)sizeDelta.x < 0,而RectTransform中數(shù)值為正數(shù)的情況:
? ?
PS: "Left","Right"的數(shù)值不一定是對(duì)半分,這里只是因?yàn)樵O(shè)置的tipsBg為上下左右對(duì)稱的設(shè)計(jì)才如此;但sizeDelta.x代表的一定是UI實(shí)際寬度與anchor矩形寬度的總差值
5.RectTransform.rect.width 和 rect.size.x是等效的,都是獲取rect的寬度,但RectTransform.rect.x是獲取rect的X坐標(biāo),這個(gè)不能和rect.size.x弄混
2.如何獲取UI對(duì)象四角的坐標(biāo)值:
在獲取UI對(duì)象四角的坐標(biāo)值時(shí)有兩種方式:一種是Unity自帶的方法rectTransform.GetWorldCorners,另一種則需要根據(jù)該UI對(duì)象的pivot和rect.size來分別計(jì)算——這種比較麻煩,因此不同的pivot計(jì)算方式不同
//方式一:
Vector3[] worldCornersPos = new Vector3[4];
tipsImageRect.GetWorldCorners(worldCornersPos);
foreach(var temp in worldCornersPos)
{
Debug.Log("<color=blue> " + temp + " </color>");
}
//方式二:根據(jù)不同的pivot用不同的方式計(jì)算四角的坐標(biāo)值
//情況一:當(dāng)pivot為“0, 0.5”時(shí)
GameObject test03 = GameObject.Find("Test03");
RectTransform test03Rect = test03.GetComponent<RectTransform>();
test03Rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 200);
test03Rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 300);
Vector3[] test03WorldCornersPos = new Vector3[4];
test03Rect.GetWorldCorners(test03WorldCornersPos);
foreach (var temp2 in test03WorldCornersPos)
{
Debug.Log("<color=yellow> " + temp2 + " " + test03.transform.position + " </color>");
}
//這里為了方便比較兩種方式的差異,所以先使用方式一輸出結(jié)果
//從結(jié)果可以看出,如果使用方式二主動(dòng)計(jì)算,需要根據(jù)pivot的設(shè)置變換不同的計(jì)算過程,這樣其實(shí)沒有必要。所以這里推薦使用Unity自帶的方法來獲取corner數(shù)值
以上測試中“Test03”的pivot為“0,0.5”,運(yùn)行結(jié)果如下:
??
?
?總結(jié):
1.從以上數(shù)值的輸出來看,推薦使用UGUI自帶的"GetWorldCorners"來獲取UI對(duì)象四角的坐標(biāo)值。并且從數(shù)值的輸出順序也可以看出,以屏幕空間左下角為起點(diǎn),順時(shí)針方向輸出四角的值
?2.從以上輸出結(jié)果可以看出,在獲取UI對(duì)象坐標(biāo)時(shí)得到的是以pivot為中心點(diǎn)顯示的坐標(biāo)(0, 249, 0),而并不是UI對(duì)象自身四角交叉線的重合點(diǎn)坐標(biāo),由此可見pivot的重要性,在設(shè)置UI對(duì)象坐標(biāo)和寬高時(shí)都會(huì)用到
原文鏈接:https://blog.csdn.net/m0_47975736/article/details/122089583
相關(guān)推薦
- 2021-10-12 shell實(shí)現(xiàn)Fisher–Yates?shuffle洗牌算法介紹_linux shell
- 2022-05-10 詳解CLR的內(nèi)存分配和回收機(jī)制_C#教程
- 2022-06-14 C#獲取指定目錄下指定文件的方法_C#教程
- 2023-07-02 一文詳解Python中l(wèi)ogging模塊的用法_python
- 2022-04-01 Python 中 __name__ == '__main__' 的作用
- 2023-02-04 Go語言中websocket的使用demo分享_Golang
- 2022-04-25 ASP.NET?Core?MVC中使用Tag?Helper組件_實(shí)用技巧
- 2023-11-20 用python對(duì)數(shù)據(jù)進(jìn)行擬合求函數(shù)表達(dá)式的方法
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支