开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 3 天,点击查看活动详情
一、代理的介绍
简单来说,动态代理就是在程序运行期,创建目标对象的代理对象,对目标对象中的方法进行功能性增强的一种技术。可以看到,概念种出现了这么几种角色:①.真实角色,②.代理角色,③.方法,④.客户(访问角色)。那么访问角色本可以直接访问真实角色的某个方法,为什么在开发的过程种需要一个代理角色呢?也就说动态代理解决了什么问题。在这里我们明确一个核心概念:动态代理能够让真实对象专注于自己的核心功能,让代理对象拦截客户对真实对象的访问,另外可以在不修改方法源码的情况下,增强被代理对象的方法的功能。
举个例子,小明(真实角色)的主要业务是唱歌,在还没火的时候自己跑东跑西去街头、酒吧等地方唱歌,在这期间需要自己负责找合适的场地,以及和酒吧老板谈工资等业务,突然有一天他火了,很多人要请他唱歌,所有的事亲历亲为他根本忙不过来,这个时候经纪人(代理角色)出现了,客户们要请小明唱歌,不能直接找到小明了,而是需要和经纪人谈,经纪人在商业等方面的理解比小明强(对代理对象的方法增强)。这样小明就可以专注于自己的唱歌业务了,经纪人的存在就是拦截了客户对小明(真实对象)的访问。
二、代理的创建,使用演示
定义明星类
public class BigStar {
String name;
public BigStar(String name) {
this.name = name;
}
public String sing(String name) {
System.out.println(this.name + "正在唱" + this.name);
return "thanks,thanks";
}
public void dance() {
System.out.println(this.name + "跳舞");
}
}
创建明星接口
public interface Star {
String sing(String name);
void dance();
}
创建代理工具类
public class ProxyUtil {
public static Star createProxy(BigStar bigStar) {
/**
* newProxyInstance (ClassLoader loader,
* Class<?>[] interfaces,
* InvocationHandler h)
* 参数1 : 用于指定一个类加载器
* 参数2 : 指定生成代理长什么样子,也就是有哪些方法
* 参数3 : 用来指定生成的代理做什么事情
*/
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 (method.getName().equals("sing")) {
System.out.println("准备话筒");
} else if (method.getName().equals("dance")) {
System.out.println("搭建舞台");
}
return method.invoke(bigStar, args);
}
}
);
return starProxy;
}
}
测试
public class Test {
public static void main(String[] args) {
BigStar s = new BigStar("杨超越");
// 创建代理对象
Star proxy = ProxyUtil.createProxy(s);
// 执行代理方法
String result = proxy.sing("匆匆那年");
System.out.println(result);
}
}

三、动态代理的实际应用
增强接口性能。减少重复工作
public interface UserService {
void login(String loginName, String passWord) throws Exception;
void deleteUsers() throws Exception;
String[] selectUsers() throws Exception;
}
接口优化前
public class UserServiceImpl implements UserService{
@Override
public void login(String loginName, String passWord) throws Exception {
long startTime = System.currentTimeMillis();
if ("admin".equals(loginName) && "123456".equals(passWord)) {
System.out.println("登陆成功");
} else {
System.out.println("登陆失败");
}
Thread.sleep(1000);
long endTime = System.currentTimeMillis();
System.out.println("login方法执行耗时:" + (endTime - startTime) / 1000.0 + "s");
}
@Override
public void deleteUsers() throws Exception {
long startTime = System.currentTimeMillis();
System.out.println("删除成功");
Thread.sleep(1000);
long endTime = System.currentTimeMillis();
System.out.println("deleteUser方法执行耗时:" + (endTime - startTime) / 1000.0 + "s");
}
@Override
public String[] selectUsers() throws Exception {
long startTime = System.currentTimeMillis();
System.out.println("查询出三个用户");
String[] names = {"odin", "jack", "mouse"};
Thread.sleep(1000);
long endTime = System.currentTimeMillis();
System.out.println("selectUser方法执行耗时:" + (endTime - startTime) / 1000.0 + "s");
return names;
}
}
接口实现优化后
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("删除成功");
Thread.sleep(1000);
}
@Override
public String[] selectUsers() throws Exception {
System.out.println("查询出三个用户");
String[] names = {"odin", "jack", "mouse"};
Thread.sleep(1000);
return names;
}
}
使用代理增强功能,类似AOP
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 (method.getName().equals("login") || method.getName().equals("deleteUsers") || method.getName().equals("selectUsers")) {
long startTime = System.currentTimeMillis();
Object res = method.invoke(userService, args);
long endTime = System.currentTimeMillis();
System.out.println(method.getName() + "方法执行耗时 : " + (endTime - startTime) / 1000.0 + "s");
return res;
} else {
Object res = method.invoke(userService, args);
return res;
}
}
});
return userServiceProxy;
}
}
测试类
public class Test {
public static void main(String[] args) throws Exception {
UserService userService = ProxyUtil.createProxy(new UserServiceImpl());
userService.login("admin", "123456");
System.out.println("=========================================");
userService.deleteUsers();
System.out.println("=========================================");
String[] names = userService.selectUsers();
System.out.println("查询到用户名:" + Arrays.toString(names));
System.out.println("=========================================");
}
}
