程序為什么需要代理?代理長什么樣?
例子
梳理
-
代理對象(接口):要包含被代理的對象的方法 ---Star
-
被代理對象:要實現代理對象(接口) ---SuperStar
-
代理工具類:創建一個代理,返回值用代理對象,參數傳被代理的對象,用Proxy代理類new一個實例,并重寫invoke方法 --- 就是代理對象要做的事情
實體類,被代理的對象
(要實現代理)
package com.dev.springBootDemo.proxy;/*** @author zhumq* @date 2024/7/2 20:51*/
public class SuperStar implements Star{private String name;public SuperStar(String name) {this.name = name;}public String sing(String singName) {System.out.println(this.name + "正在唱:" + singName);return "唱完了!謝謝大家!";}public void dance() {System.out.println(this.name + "正在跳舞中~~~" );}}
代理對象(接口)
要包含被代理的對象的方法
package com.dev.springBootDemo.proxy;/*** @author zhumq* @date 2024/7/2 20:56*/
public interface Star {void dance();String sing(String singName);
}
代理工具類 :
創建一個代理,返回值用代理對象,參數傳被代理的對象,用Proxy代理類new一個實例,并重寫invoke方法 --- 就是代理對象要做的事情
package com.dev.springBootDemo.proxy;
?
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
?
/*** @author zhumq* @date 2024/7/2 20:57*/
public class ProxyUtil {public static Star createProxy(SuperStar superStar) {/*** (lassLoader loader , Class<?>[] interfaces, InvocationHandler h )* 參數1:用于指定一個類加載器* 參數2:用于指定一個接口數組,因為一個代理類可以代理多個接口,所以可以指定多個接口* ? ? ? 也就是指定生成的代理長什么樣* 參數3:用于指定一個InvocationHandler對象,當調用代理類的方法時,就會自動調用InvocationHandler中的invoke方法* ? ? ? (指定InvocationHandler中的invoke方法,在調用Star接口中的方法時,就會自動執行)* ? ? ? 也就是生成的代理對象要做什么}*/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 ("sing".equals(method.getName())) {System.out.println("代理要去做:唱歌要先租場地");} else if ("dance".equals(method.getName())) {System.out.println("代理要去做:跳舞要去請老師教");}return method.invoke(superStar, args);}});return starProxy;}
}
?
測試類:
package com.dev.springBootDemo.proxy;
?
/*** @author zhumq* @date 2024/7/2 21:16*/
public class TestProxy {public static void main(String[] args) {SuperStar superStar = new SuperStar("周杰倫");Star proxy = ProxyUtil.createProxy(superStar);System.out.println(proxy.sing("稻香"));proxy.dance();}
}
?
輸出
代理要去做:唱歌要先租場地 周杰倫正在唱:稻香 唱完了!謝謝大家! 代理要去做:跳舞要去請老師教 周杰倫正在跳舞中~~~
解決實際問題
-
UserService
-
UserServiceImpl
-
ProxyUtil
-
TestProxy
UserService
package com.dev.springBootDemo.proxy2;/*** 用戶業務接口* @author zhumq* @date 2024/7/2 21:33*/
public interface UserService {// 登錄功能void login(String loginName, String password) throws Exception;// 刪除用戶功能void deleteUser() throws Exception;// 查詢用戶功能String[] selectUsers() throws Exception;
}
?
UserServiceImpl
package com.dev.springBootDemo.proxy2;
?
/*** 用戶業務實現(面向接口編程鳥綱)* @author zhumq* @date 2024/7/2 21:35*/
public class UserServiceImpl implements UserService{@Overridepublic void login(String loginName, String password) throws Exception {
?if ("admin".equals(loginName) && "123456".equals(password)) {System.out.println("登錄成功");}else {System.out.println("登錄失敗");}Thread.sleep(1000);}
?@Overridepublic void deleteUser() throws Exception {System.out.println("刪除了10個用戶");Thread.sleep(1000);
?}
?@Overridepublic String[] selectUsers() throws Exception {System.out.println("查詢了2個用戶");String[] users = new String[]{"張三", "李四"};Thread.sleep(1000);return users;}
}
?
ProxyUtil
package com.dev.springBootDemo.proxy2;
?
import com.dev.springBootDemo.proxy.Star;
?
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
?
/*** @author zhumq* @date 2024/7/2 21:41*/
public class ProxyUtil {// 為用戶業務對象創建代理public static UserService createProxy(UserService userService) {UserService userServiceProxy = (UserService) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(), new Class[]{UserService.class}, new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if ("login".equals(method.getName()) || "deleteUser".equals(method.getName())|| "selectUsers".equals(method.getName())) {
?long startTime = System.currentTimeMillis();
?Object s = method.invoke(userService, args);
?long endTime = System.currentTimeMillis();
?System.out.println(method.getName() + "方法耗時:" + (endTime - startTime) / 1000 + "s");
?return s;} else {return method.invoke(userService, args);}}});return userServiceProxy;}
}
?
TestProxy
package com.dev.springBootDemo.proxy2;
?
import java.util.Arrays;
?
/*** @author zhumq* @date 2024/7/2 21:49*/
public class TestProxy {public static void main(String[] args) throws Exception {UserService userService = ProxyUtil.createProxy(new UserServiceImpl());
?System.out.println("----------------用戶登錄-------------------");userService.login("admin", "123456");System.out.println("----------------用戶刪除-------------------");userService.deleteUser();System.out.println("----------------用戶查詢-------------------");String[] users = userService.selectUsers();System.out.println(Arrays.toString(users));}
}
輸出:
----------------用戶登錄------------------- 登錄成功 login方法耗時:1s ----------------用戶刪除------------------- 刪除了10個用戶 deleteUser方法耗時:1s ----------------用戶查詢------------------- 查詢了2個用戶 selectUsers方法耗時:1s [張三, 李四]