一、程序为什么需要代理?代理长什么样?
1.1、对象如果嫌身上干的事太多的话,可以通过代理来转移部分职责。
1.2、对象有什么方法想被代理,代理就一定要有对应的方法
1.3、中介如何知道要派有唱歌、跳舞方法的代理呢?-->接口
1.4、示例

二、如何为 Java 对象创建一个代理对象?
java.lang.reflect.Proxy 类:提供了为对象产生代理对象的方法:

1.4示例的代码
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 代理工具类:中介公司,专门负责创建代理对象并返回给别人使用
*/
public class ProxyUtil {
// 创建一个明星对象的代理对象返回。
public static StarService createProxy(Star s){
/**
* 参数一:用于执行用哪个类加载器去加载生成的代理类。
* 参数二:用于指定代理类需要实现的接口: 明星类实现了哪些接口,代理类就实现哪些接口
* 参数三:用于指定代理类需要如何去代理(代理要做的事情)。
*/
StarService proxy = (StarService) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(),
s.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 用来声明代理对象要干的事情。
// 参数一: proxy接收到代理对象本身(暂时用处不大)
// 参数二: method代表正在被代理的方法
// 参数三: args代表正在被代理的方法的参数
String methodName = method.getName();
if("sing".equals(methodName)){
System.out.println("准备话筒,收钱20万!");
}else if("dance".equals(methodName)){
System.out.println("准备场地,收钱100万!");
}
// 真正干活(把真正的明星对象叫过来正式干活)
// 找真正的明星对象来执行被代理的行为:method方法
Object result = method.invoke(s, args);
return result;
}
});
return proxy;
}
}
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Star implements StarService{
private String name;
@Override
public void sing(String name) {
System.out.println(this.name + "表演唱歌:" + name);
}
@Override
public String dance() {
System.out.println(this.name + "表演跳舞:魅力四射!" );
return "谢谢!谢谢!";
}
}
// 明星行为接口
public interface StarService {
void sing(String name);
String dance();
}
public class Test {
public static void main(String[] args) {
// 目标:创建代理对象。
// 1、准备一个明星对象:设计明星类。
Star star = new Star("章若楠");
// 2、为章若楠创建一个专属与她的代理对象。
StarService proxy = ProxyUtil.createProxy(star);
proxy.sing("《红昭愿》");
System.out.println(proxy.dance());
}
}
三、解决实际问题、掌握使用代理的好处
场景
某系统有一个用户管理类,包含用户登录,删除用户,查询用户等功能,系统要求统计每个功能的执行耗时情况,以便后期观察程序性能。
代码
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyUtil {
public static <T> T createProxy(T obj) {
T proxy = (T) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(),
obj.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
long start = System.currentTimeMillis(); // 记录开始时间 1970年1月1日0时0分0秒 走到此刻的总毫秒值
// 真正调用业务对象被代理的方法
Object result = method.invoke(obj, args);
long end = System.currentTimeMillis();
System.out.println(method.getName() + "方法耗时:"+(end-start)/1000.0+"秒");
return result;
}
});
return proxy;
}
}
/**
* 用户业务接口
*/
public interface UserService {
// 登录功能
void login(String loginName,String passWord) throws Exception;
// 删除用户
void deleteUsers() throws Exception;
// 查询用户,返回数组的形式。
String[] selectUsers() throws Exception;
String[] selectUsers2() throws Exception;
}
/**
* 用户业务实现类(面向接口编程)
*/
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 deleteUsers() throws Exception{
System.out.println("成功删除了1万个用户~");
Thread.sleep(1500);
}
@Override
public String[] selectUsers() throws Exception{
System.out.println("查询出了3个用户");
String[] names = {"张全蛋", "李二狗", "牛爱花"};
Thread.sleep(500);
return names;
}
@Override
public String[] selectUsers2() throws Exception {
System.out.println("查询出了3000个用户");
String[] names = {"张全蛋2", "李二狗2", "牛爱花2"};
Thread.sleep(2500);
return names;
}
}
import java.util.Arrays;
/**
* 目标:使用动态代理解决实际问题,并掌握使用代理的好处。
*/
public class Test {
public static void main(String[] args) throws Exception{
// 1、创建用户业务对象。
UserService userService = ProxyUtil.createProxy(new UserServiceImpl());
// 2、调用用户业务的功能。
userService.login("admin", "123456");
userService.deleteUsers();
String[] names = userService.selectUsers();
System.out.println("查询到的用户是:" + Arrays.toString(names));
String[] names2 = userService.selectUsers2();
System.out.println("查询到的用户是:" + Arrays.toString(names2));
}
}
注意:此案例的代理思想,其实也是AOP(切面思想)。即在不修改业务逻辑代码的情况下,通过代理实现横切关注点(如日志、性能统计等)的模块化。
四、体会Spring思想

470

被折叠的 条评论
为什么被折叠?



