程序为什么需要代理?代理长什么样?
例子
梳理
-
代理对象(接口):要包含被代理的对象的方法 ---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 [张三, 李四]