1. 程式人生 > >類載入器(Mapper動態代理)和反射

類載入器(Mapper動態代理)和反射

類的載入:

        當程式要使用某個類時,如果該類還未被載入到記憶體中,則系統會通過載入,連線,初始化三步來實現對這個類進行初始化。
    一:載入 
            就是指將class檔案讀入記憶體,併為之建立一個Class物件。

            任何類被使用時系統都會建立一個Class物件。

            類載入器
                負責將.class檔案載入到內在中,併為之生成對應的Class物件。
               ( 雖然我們不需要關心類載入機制,但是瞭解這個機制我們就能更好的理解程式的執行。)

            類載入器的組成
                Bootstrap ClassLoader 根類載入器
                Extension ClassLoader 擴充套件類載入器

                Sysetm ClassLoader 系統類載入器

         類載入器的作用:

                   Bootstrap ClassLoader 根類載入器也被稱為引導類載入器,負責Java核心類的載入,比如System,String等。        在 JDK中JRE的lib目錄下rt.jar檔案中。

                    Extension ClassLoader 擴充套件類載入器,負責JRE的擴充套件目錄中jar包的載入。在JDK中JRE的lib目錄下ext目錄

                    Sysetm ClassLoader 系統類載入器,負責在JVM啟動時載入來自java命令的class檔案,以及classpath環境變數所指定的jar包和類路徑
    二:連線

            驗證 是否有正確的內部結構,並和其他類協調一致
            準備 負責為類的靜態成員分配記憶體,並設定預設初始化值
            解析 將類的二進位制資料中的符號引用替換為直接引用

    三:初始化

            建立類的例項:建立物件
            訪問類的靜態變數,或者為靜態變數賦值
            呼叫類的靜態方法
            使用反射方式來強制建立某個類或介面對應的java.lang.Class物件
            初始化某個類的子類

            直接使用java.exe命令來執行某個主類

反射:

          JAVA反射機制是在執行狀態中,對於任意一個類(Object),都能夠知道這個類的所有屬性和方法;對於任意一個物件,都能夠呼叫它的任意一個方法和屬性;這種動態獲取的資訊以及動態呼叫物件的方法的功能稱為java語言的反射機制。

要想解剖一個類,必須先要獲取到該類的位元組碼檔案物件。而解剖使用的就是Class類中的方法.所以先要獲取到每一個位元組碼檔案對應的Class型別的物件.

:反射就是通過獲取class位元組碼檔案物件/Class的類物件,獲取該位元組碼檔案物件中的成員變數,構造方法,和成員方法)

    一:通過反射獲取構造方法並使用

        獲取構造方法
getConstructors
getDeclaredConstructors
        建立物件
newInstance()

con.newInstance(“zhangsan", 20);

    二:通過反射獲取成員變數並使用

        獲取所有成員
getFields,getDeclaredFields
        獲取單個成員
getField,getDeclaredField
        修改成員的值

set(Object obj,Object value)   將指定物件變數上此 Field 物件表示的欄位設定為指定的新值。

        獲取所有方法
getMethods
getDeclaredMethods
        獲取單個方法
getMethod
getDeclaredMethod
        暴力訪問

method.setAccessible(true);

     Field: 簡稱成員變數Field 提供有關類或介面的單個欄位的資訊,以及對它的動態訪問許可權。反射的欄位可能是一個類(靜態)欄位或例項欄位。)
         Constructor:簡稱構造方法:提供關於類的單個構造方法的資訊以及對它的訪問許可權。
        Method:簡稱成員方法:類或介面上單獨某個方法(以及如何訪問該方法)的資訊

    三:反射應用舉例

        通過配置檔案執行類中的方法,加入給ArrayList<Integer>的一個物件,我想在這個集合中新增一個字串資料,如何實現呢?

        寫一個方法,  public void setProperty(Object obj, String propertyName, Object value){},此方法可將obj物件中名為propertyName的屬性的值設定為value。

 
 問題:
如何獲取class位元組碼檔案物件/Class的類物件

 答:

三種方式來獲取這個class位元組碼檔案物件:

 1)Object中的getClass() 

                            示例:獲取class位元組碼檔案物件

Person p1 = new Person() ;//建立Person物件
Class c1 = p1.getClass() ;  //獲取class位元組碼檔案物件 

 2)任何資料型別的靜態屬性class

示例://資料型別的靜態屬性class
Class c2 = Person.class ;
System.out.println(c3==c2);//列印true

 3)Class類中的方法:
 forName(String className)
 forName("類路徑")

         在開發中使用第三種方式,forName方法中的引數是一個String型別,以後可以用字串型別資料作為配置檔案!

                            示例://public static Class<?> forName(String className)
                          //java.lang.ClassNotFoundException: Person
                                        //Class c4 = Class.forName("Person") ;
//org.westos_01.Person 
//引數:類路徑:包名.類名
Class c4 = Class.forName("org.westos_01.Person") ;
System.out.println(c4==c2);

package org.weosts_04;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

/**
 *通過獲取成員方法並使用 
 *
 */
public class MethodReflectDemo {

	public static void main(String[] args)throws Exception {
		
		//通過反射獲取Pereson位元組碼檔案物件(包名.類名)
		Class c = Class.forName("org.westos_01.Person") ;
		
		//獲取當前位元組碼檔案物件中的所有的公共的成員方法(包括父類中的)
		//public Method[] getMethods()  例句:Method[] methods = c.getMethods() ;

		//public Method[] getDeclaredMethods():所有的成員方法
		例句/*Method[] methods = c.getDeclaredMethods() ;
		      for(Method method:methods) {//增強for迴圈,遍歷methods
                      System.out.println(method);}*/
		
		/***
		 * 之前呼叫Person類中的show()
		 * Person p = new Person() ;
		 * p.show() ;
		 */
		
		//獲取Constructor物件
		Constructor con = c.getConstructor() ;
		Object obj = con.newInstance() ;
		
		//獲取單個的成員方法,Method  
		//呼叫public void show(){}
		//public Method getMethod(String name, Class<?>... parameterTypes)
		//引數1: 表示方法名
		//引數2:表示當前方法的引數資料型別的靜態class屬性
		Method m1 = c.getMethod("show") ;
//		obj.m1() ;
		
		//public Object invoke(Object obj, Object... args)
		//引數1:指定的哪個物件上呼叫底層invoke(),
		//引數2:表示的呼叫那個方法所傳遞的實際引數
		m1.invoke(obj) ; //在obj物件上呼叫m1物件所表示的成員方法
		System.out.println("--------------------");
		/**
		 * public void method(String s) {
				System.out.println("method"+s);
			}
		 */
		
		Method m2 = c.getMethod("method",String.class) ;
		
		//呼叫底層方法
		m2.invoke(obj, "hello") ;
		
		System.out.println("-----------------------");
		/**
		 * public String getString(String s,int i) {
					return s+i ;
				}
		 */
		
		Method m3 = c.getMethod("getString",String.class,int.class) ;
		//呼叫Method類中的invoke()方法,呼叫底層哪個位元組碼檔案物件的對應的成員方法
		Object objgetString = m3.invoke(obj, "javaweb",100) ;
		System.out.println(objgetString);
		
		System.out.println("---------------------------");
		
		/**
		 * //私有的
			private void function() {
				System.out.println("function Preson");
				}		
		 */
		
		//public Method getDeclaredMethod(String name , Class<?>... parameterTypes)
		Method m4= c.getDeclaredMethod("function") ;
		
		//取消Java語言訪問檢查
		m4.setAccessible(true);
		//呼叫obj 物件中的底層的function()方法
		m4.invoke(obj) ;	
	}
}
成員方法
package org.westos_01;

public class Person {
	
	private String name ;
	int age ;
	public String address ;
	
	//公共的無參
	public Person() {
	}
	
	//私有的帶一個引數的構造方法
	private Person(String name) {
		this.name = name ;
	}
	
	//沒有許可權修飾符的帶兩個引數的構造方法
	Person(String name,int age){
		this.name = name ;
		this.age =age ;
	}
	
	//公共的帶三個引數的構造方法
	public Person(String name,int age,String address) {
		this.name = name ;
		this.age =age ;
		this.address = address;
	}
	
	//成員方法
	//無參的,沒有返回值
	public void show() {
		System.out.println("show Person");
	}
	
	//有參的,沒有返回值的
	public void method(String s) {
		System.out.println("method"+s);
	}
	
	//有參的,並且有返回值的
	public String getString(String s,int i) {
		return s+i ;
	}
	
	//私有的
	private void function() {
		System.out.println("function Preson");
	}

	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + ", address=" + address + "]";	}}		

動態代理:


    動態代理(hibernate,MyBatis都會存在代理)
    代理:本來應該自己做的事情,卻請了別人來做,被請的人就是代理物件。
    舉例:春季回家買票讓人代買
    動態代理:在程式執行過程中產生的這個物件

    而程式執行過程中產生物件其實就是我們剛才反射講解的內容,所以,動態代理其實就是通過反射來生成一個代理

    在Java中java.lang.reflect包下提供了一個Proxy類和一個InvocationHandler介面,通過使用這個類和介面就可以生成動態代理物件。JDK提供的代理只能針對介面做代理。我們有更強大的代理cglib
    Proxy類中的方法建立動態代理類物件
    public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
    最終會呼叫InvocationHandler的方法
    InvocationHandler
    Object invoke(Object proxy,Method method,Object[] args)

相關推薦

載入(Mapper動態代理)反射

類的載入:        當程式要使用某個類時,如果該類還未被載入到記憶體中,則系統會通過載入,連線,初始化三步來實現對這個類進行初始化。    一:載入             就是指將class檔案讀入記憶體,併為之建立一個Class物件。            任何類被

載入|註解|動態代理

一、類載入器 1.什麼是類載入器,作用是什麼? 類載入器就載入位元組碼檔案(.class)   2.類載入器的種類   類載入器有三種,不同類載入器載入不同的 1)BootStrap:引導類載入器:載入都是最基礎的檔案 2)ExtClassLoader:擴充套件類載入器:載入都是基

【Mybatis】mapper動態代理對映檔案配置標籤

提要:主要演示了mybatis中,在類中的其他自定義類,在sql語句中如何取值。sql語句中,範圍sql與集合的對應   一、目錄結構 二、相關實體類 QueryVo package com.test.domain; import java.io.Seria

【Mybatis】mapper動態代理sqlMapconfig.xml配置標籤

1.mapper動態代理 使用mapper對映來,聯絡sql語句和程式碼函式。 步驟一:在上一篇基礎的上,新增一個介面,要求與UserMapper的xml配置檔案同名,加入在xml中的所有sql的id相同的方法,即方法名相同,入參和返回值都相同 步驟二:修改usermapper的名稱

java中的動態代理反射

java的動態代理是用反射實現的。 什麼是反射? java的反射機制,是說在執行時刻,對於任何一個類,都能夠知道它的所有屬性和方法;對任意一個物件,都能夠呼叫它的任意方法和屬性;這種動態獲取資訊以及動態呼叫方法的功能稱為java的反射機制。 java通過j

Java高階特性(動態代理反射

目錄第4天 java高階特性增強今天內容安排:1、掌握多執行緒2、掌握併發包下的佇列3、瞭解JMS4、掌握JVM技術5、掌握反射和動態代理Øjava多執行緒增強通俗來講:應用程式就是一個程序。不管是我們開發的應用程式,還是我們執行的其他的應用程式,都需要先把程式安裝在本地的硬

載入的作用範圍雙親委派模型

JVM定義把類載入階段中的通過類的全名稱,取得此類的“二進位制位元組流”這種操作的實現的程式碼模組叫做類載入器 public ClassLoader getClassLoader();取得當前類載入器 類載入器分為四種,按照從頂層到底層的順序為:Bootstrap:啟動類

利用ClassLoader載入獲取專案資源用class獲取專案資源

首先看想專案中的目錄 在專案中有兩個a.html  一個在專案中 另一個在專案的報下  在Demo2.java這個檔案中建立程式碼來實現用兩個方法來訪問專案資源 Java程式碼入下 package cc; import java.io.IOException; impo

JAVA載入、註解動態代理

一.類載入器 1.什麼是類載入器,作用是什麼 類載入器就載入位元組碼檔案(.class) 2.類載入器的種類 類載入器有三種,不同載入器載入不同 BootStrap:引導類載入器:載入都是最基礎的檔案 ExtClassLoader:擴充套

java載入動態代理

import java.lang.reflect.*; import java.util.ArrayList; import java.util.Collection; public class ProxyTest { public static void main(String[] args) throw

JavaEE複習回顧十一: (基礎加強) 載入 && 註解 && 動態代理

參考文章: 1,動態代理——從一竅不通到恍然大悟 2,UML類圖與類的關係詳解   一,類載入器 1.1 什麼是類載入器,作用是什麼? 一個自己編寫的 Java 程式碼原始檔,起執行的過程主要分為三個階段。 第一個階段: SOURCE 級別,即原始碼階段,已

Java -- 載入&反射&代理

類載入&類載入器 類的載入描述: 反射&reflect JAVA反射機制是在執行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個物件,都能夠呼叫它的任意一個方法和屬性;這種動態獲取的資訊以及動態呼叫物件的方法的功能稱為java語言

載入反射反射的應用例項(泛型擦除配置檔案)

類載入器 1.1類的載入 當程式要使用某個類時,如果該類還未被載入到記憶體中,則系統會通過載入,連線,初始化三步來實現對這個類進行初始化。   1.1.1載入 指將class檔案讀入記憶體,併為之建立一個Class物件。 任何類被使用時系統都會建立一個Class物件(位元組碼檔案物件,建

加載+註解+動態代理

tab tin 耦合性 註解開發 cat isa lpad span ppr 一、類加載器 1.什麽是類加載器,作用是什麽? 類加載器就加載字節碼文件(.class) 2.類加載器的種類 類加載器有三種,不同類加載器加載不同的 1)BootStrap:

Java載入( CLassLoader ) 死磕9: 上下文載入原理案例

【正文】Java類載入器(  CLassLoader ) 死磕9:  上下文載入器原理和案例 本小節目錄 9.1. 父載入器不能訪問子載入器的類 9.2. 一個寵物工廠介面 9.3. 一個寵物工廠管理類 9.4 APPClassLoader不能訪問子載入器中的類 9.5. 執行緒上下文

Java載入( CLassLoader ) 死磕8: 使用ASM,載入實現AOP

【正文】Java類載入器(  CLassLoader ) 死磕8:  使用ASM,和類載入器實現AOP 本小節目錄 8.1. ASM位元組碼操作框架簡介 8.2. ASM和訪問者模式 8.3. 用於增強位元組碼的事務類 8.4 通過ASM訪問註解 8.5. 通過ASM注入AOP事務程式

java載入機制自定義載入

類載入順序 上圖所示的是類載入的順序,按照大的順序可以分為載入、連結、初始化 其中連結又可以分成驗證、準備、解析三個步驟 載入 1.將類的class檔案讀入到記憶體中 載入類檔案的方式有: 1. 本機檔案載入 2.jar包載入 3.網路載入 4.原始檔動態編譯載入

反射(Constructor、Field、Method、載入

一:什麼是反射 在認識反射之前,首先回顧下什麼是正向處理。如果我們需要例項化一個物件,首先需要匯入這個類的包,在這個包中找這個類: package CODE.反射; import java.util.Date; public class Fan { public static

Java載入2.反射的使用

反射的使用 1、通過反射機制獲取Java類的構造方法並使用 (1)Person類 package cn.itcast_01; public class Person { private St

基於介面的兩種動態代理的解析及使用

基於介面: package com.itheima.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.P