1.動態代理的作用
動態代理最主要的用途就是在各種框架中,很方便的在運行期間生成代理類,通過代理類就可以完成AOP、過濾器、攔截器等操作
(注:代理就是被代理者沒有能力或者不愿意去完成某件事情,需要找個人代替自己去完成這件事,動態代理就是用來對業務功能(方法)進行代理的。比如UserService類有1000個業務方法,每個業務方法都都需要記錄執行時間,那么不可能寫1000次相同代碼吧,因此可以讓代理對象幫忙完成時間記錄)
首先使用動態代理必須基于接口,動態代理的靜態創建方法:
public static Object newProxyInstance(ClassLoader loader,/*對象.getClass().getClassLoader() ,目標對象通過getClass方法獲取類的所有信息后,調用getClassLoader()方法來獲取類加載器
獲取類加載器后,可以通過這個類型的加載器,在程序運行時,將生成的代理類加載到JVM即Java虛擬機中,以便運行時需要*/Class<?>[] interfaces,/*對象.getClass().getInterfaces()
獲取被代理類的所有接口信息,以便于生成的代理類可以具有代理類接口中的所有方法*/InvocationHandler handle /*用于集中處理在動態代理類對象上的方法調用,通常在該方法中實現對委托類方法的處理以及訪問*/ )
java.lang.reflect.InvocationHandler
是代理對象的實際處理代理邏輯的接口,具體代理邏輯在其 invoke 方法中實現
public Object invoke(Object proxy, Method method, Object[] args)
**解釋說明:
- 返回值:方法被代理后執行的結果
- 參數列表說明:Object proxy : 就是代理對象(通常不使用)Method method : 代理對象調用的方法Object[] args : 被代理方法中的參數 (因為參數個數不定,所以用一個對象數組來表示)如果方法不使用參數,則為 null//所有代理對象調用的方法,執行是都會經過invoke
//因此如果要對某個方法進行代理增強,就可以在這個invoke方法中進行定義
例子:
/*其中Star是代理類接口,具有Song和Dance方法;*/
public class ProxyUtil {public static Star createProxy(BigStar bigStar){Star starProxy = (Star) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(),new Class[]{Star.class}, new InvocationHandler() {@Override // 回調方法public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 代理對象要做的事情,會在這里寫代碼if(method.getName().equals("sing")){System.out.println("準備話筒,收錢20萬");}else if(method.getName().equals("dance")){System.out.println("準備場地,收錢1000萬");}return method.invoke(bigStar, args);}});return starProxy;}
}
2.線程池的幾種狀態
- RUNNING : 表示正常運行,既可以接受新任務,也會正常處理阻塞隊列的任務
- SHUTDOWN : 當線程池調用shutdown()方法時,進入該狀態,表示線程池處于關閉狀態,不會接受新任務但是會處理隊列中的任務
- STOP : 調用線程池的shutdownnow()方法時,進入該狀態,表示線程池處于停止狀態,既不接受新任務也不處理隊列任務,正常運行的線程也會被中斷
- TIDYING : 線程池沒有線程運行時,狀態自動變為TIDYING,并且調用terminated(),該方法是空方法,留給程序與擴展
- TERMINATED : terminated()方法執行完成后,線程池就變成該狀態
3.反射技術的作用,需要什么
- 反射需要Class對象
- 作用
- 不使用new關鍵字去創建對象
- 不使用“對象名.方法”的形式就可以調用方法
- 不使用“對象名.屬性”的形式就可以給屬性賦值取值
- 可以對私有成員變量進行操作
4.獲取Class對象的方法
- 類型名.Class
- 對象名.getcClass
- Class.forName(String className) //className是全路徑類名 = 包名+類型名
5.反射創建對象的方法
-
根據Class對象創建
Class stuClass = Class.forName("com.cls.demo2.Student");Student stu = (Student) stuClass.newInstance();stu.study();
-
獲取構造器進行創建
//獲取Class對象(Student.class) Class stuClass = Student.class;//public Student(String name, int age, String gender) //獲取帶有參數的構造器對象 //參數:是用來設置構造方法中參數的類型是什么 Constructor con = stuClass.getConstructor(String.class, int.class, String.class);//實例化有參構造方法 //參數:要傳遞給Student(String name, int age, String gender)的數據 Student stu = (Student) con.newInstance("熊大", 22, "男");//調用對象中的方法 stu.study();
6.獲取成員方法 方法調用
-
獲取成員方法
每一個成員方法都是一個Method類的對象,我們可以通過Method對象來調用成員方法
Class類中的Method相關方法:
Method[] getMethods(); //獲得當前類和其父類中的所有public成員方法對象,返回數組Method[] getDeclaredMethods(); //獲得當前類中的所有成員方法對象,返回數組 //只獲得本類的,包括public、protected、默認、private的Method getMethod(String name,Class...args); //根據方法名和參數類型獲得對應的成員方法對象,只能獲得public的 //參數說明: name : 類中方法的名字 args : 方法中參數類型的Class 例:int.class Method getDeclaredMethod(String name,Class...args); //根據方法名和參數類型獲得對應的成員方法對象,包括public、protected、(默認)、private的
Method常用方法:
//使用方法對象,調用對象中的方法執行(入棧執行) Object invoke(Object obj, Object... args) // 設置"暴力訪問" ——是否取消權限檢查,true取消權限檢查,false表示不取消 void setAccessible(true)
例子:
@Testpublic void testMethod2() throws ClassNotFoundException {//獲取Class對象Class stuClass = Class.forName("com.itheima.method.demo1.Student");//使用Class對象,獲取Method對象Method[] methods = stuClass.getDeclaredMethods();//獲取本類中所有方法(包含私有)for (Method m : methods){System.out.println(m);}}
-
方法調用
反射調用對象的私有方法需要去除JVM權限檢查
7.注解
-
自定義注解
public @interface 注解名{//內容熟悉:數據類型 屬性名();數據類型 屬性名() dalfult 默認值; }
-
元注解
定義在自定義注解上,@Target指定自定義注解修飾什么地方,@Retention指定自定義注解生命周期(有效范圍)
例子
@Target({ElementType.METHOD,ElementType.TYPE}) //修飾類/接口 以及 方法 public @inference stu{String name(); }
-
注解解析
使用反射技術完成注解數據的解析
步驟:
- 利用反射獲取相關對象:類,構造器,方法,屬性
- 利用方法getAnnotation,獲取自定義注解的對象
- 通過注解的對象分別獲取注解屬性值