天天看點

Spring - JDK的動态代理

JDK的動态代理

  • 運作過程:

    JVM -> 動态代理類 -> 代理對象

  • Proxy.newProxyInstance方法參數詳解
Spring - JDK的動态代理
  • 三個參數:
  1. loader: 用哪個類加載器去加載代理對象
  2. interfaces: 動态代理類需要實作的接口
  3. h: 動态代理方法在執行時,會調用h裡面的invoke方法去執行
1. ClassLoader loader
	(1)類加載器的作用:
    	1. 通過類加載器把對應類的位元組碼檔案加載JVM
    	2. 通過類加載器建立類的Class對象, 進而建立這個類的對象
    	
   	(2)類加載器的運作過程:
   		.java -> .class(位元組碼檔案) -> (通過類加載器)加載到JVM -> (通過類加載器建立).class對象 -> new 類的對象	
   
   	(3)如何獲得類加載器
   		JVM會為每一個類的.class檔案自動配置設定與之對應的類加載器
   		
   	(4)備注:
    	Class對象記錄了這個類最完整的資訊
           
2. @NotNull Class<?>[] interfaces

	通過 原始類對象.getClass().getInterfaces() 獲得接口
           
3. @NotNull InvocationHandler h
	
	簡介: InvocationHandler接口是proxy代理執行個體的調用處理程式實作的一個接口,每一個proxy代理執行個體都有一個關聯的調用處理程式;在代理執行個體調用方法時,方法調用被編碼分派到調用處理程式的invoke方法。
	
	當我們通過動态代理對象調用一個方法時候,這個方法的調用就會被轉發到實InvocationHandler接口類的invoke方法來調用
	
	/**
	* Object: 傳回原始方法的傳回值
    * proxy: 代理對象
    * method: 我們所要調用某個對象真實的方法的Method對象, 即核心功能
    * args: 原始方法的參數
    */
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
           
  • 代碼示範

    TextJDKProxy.java

package com.wyt.jdk;

import com.hello.wyt.User;
import com.hello.wyt.UserService;
import com.hello.wyt.UserServiceImpl;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class TextJDKProxy {
    public static void main(String[] args) {
        //1.建立原始對象
        UserService userService = new UserServiceImpl();

        InvocationHandler handler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("---proxy log before---");
                //原始方法運作
                Object ret = method.invoke(userService, args);

                System.out.println("---proxy log after---\n");

                return ret;
            }
        };

        //獲得代理對象
        UserService userServiceProxy = (UserService) Proxy.newProxyInstance(TextJDKProxy.class.getClassLoader(), userService.getClass().getInterfaces(), handler);

        userServiceProxy.login("wyt", "123456");
        userServiceProxy.register(new User());
    }
}
           

UserService.java(接口)

package com.wyt.proxy;

public interface UserService{
    public void register(User user);

    public boolean login(String name, String password);
}

           

UserServiceImpl.java

package com.wyt.proxy;

public class UserServiceImpl implements UserService{
    @Override
    public void register(User user) {
        System.out.println("UserServiceImpl.register 業務運算 + DAO");
    }

    @Override
    public boolean login(String name, String password) {
        System.out.println("UserServiceImpl.login");
        return true;
    }
}

           

User.class

package com.wyt.proxy;

import java.io.Serializable;

public class User implements Serializable {
    private String name;
    private String password;

    public User() {

    }

    public User(String name, String password) {
        this.name = name;
        this.password = password;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}