程序为什么需要代理?代理长什么样?
例子
梳理
-
代理对象(接口):要包含被代理的对象的方法 ---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{
@Override
public 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);
}
@Override
public void deleteUser() throws Exception {
System.out.println("删除了10个用户");
Thread.sleep(1000);
}
@Override
public 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() {
@Override
public 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 [张三, 李四]