Java动态代理
Java动态代理
案例
模拟企业业务功能开发,并完成每个功能的性能统计
需求:
- 模拟某企业用户管理业务,需包含用户登录,用户删除,用户查询功能,并要统计每个功能的耗时。
分析:
- 定义一个UserService表示用户业务接口,规定必须完成用户登录,用户删除,用户查询功能。
- 定义一个实现类UserServiceImpl实现UserService,并完成相关功能,且统计每个功能的耗时。
- 定义测试类,创建实验类对象,调用方法。
UserService:
package CC.Proxy;
/**
* 模拟用户业务功能
*/
public interface UserService {
String login(String loginName,String passWord);
void selectUsers();
boolean deleteUsers();
}
UserviceImpl:
package CC.Proxy;
public class UserServiceImpl implements UserService{
@Override
public String login(String loginName, String passWord) {
long startTimer = System.currentTimeMillis();
try {
Thread.sleep(1000);
if("admin".equals(loginName) && "1234".equals(passWord)){
return "success";
}
return "登录名和密码可能有毛病";
} catch (Exception e){
e.printStackTrace();
return "error";
} finally {
long endTimer = System.currentTimeMillis();
System.out.println("login方法耗时: " + (endTimer-startTimer)/1000.0 + "s");
}
}
@Override
public void selectUsers() {
long startTimer = System.currentTimeMillis();
System.out.println("查询了100个用户数据!");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
long endTimer = System.currentTimeMillis();
System.out.println("selectUsers方法耗时: " + (endTimer-startTimer)/1000.0 + "s");
}
@Override
public boolean deleteUsers() {
long startTimer = System.currentTimeMillis();
try {
System.out.println("删除了100个用户数据!");
Thread.sleep(500);
return true;
} catch (InterruptedException e) {
e.printStackTrace();
return false;
}finally {
long endTimer = System.currentTimeMillis();
System.out.println("deleteUsers方法耗时: " + (endTimer-startTimer)/1000.0 + "s");
}
}
}
Test:
package CC.Proxy;
public class Test {
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
System.out.println(userService.login("admin","1234"));
userService.selectUsers();
System.out.println(userService.deleteUsers());
}
}
/**
login方法耗时: 1.011s
success
查询了100个用户数据!
selectUsers方法耗时: 2.007s
删除了100个用户数据!
deleteUsers方法耗时: 0.514s
true
*/
本案例存在哪些问题?
业务对象的每个方法 都要进行性能统计,存在大量重复的代码。
使用动态代理解决问题
动态代理
- 代理就是被代理者没有能力或者不愿意去完成某件事情,需要找个人代替自己去完成这件事,动态代理就是用来对业务功能(方法)进行代理的 。
关键步骤
-
必须有接口,实现类要实现接口(代理通常是基于接口实现的)
-
创建一个实现类的对象,该对象为业务对象,紧接着为业务对象做一个代理对象。
把这里创立的对象传入代理中,返回一个代理对象回来
ProxyUtil代码:
package CC.Proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
* 参数一: 类加载器,负责加载代理
* 参数二: 获取被代理对象实现的全部接口。代理要为全部接口的全部方法进行的代理
* 参数三: 代理的核心处理逻辑
*/
public class ProxyUtil {
/**
* 生成业务对象的代理对象
* @param obj
* @return
*/
public static UserService getProxy(UserService obj) {
//返回了一个代理对象
return (UserService) Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//参数一: 代理对象本身
//参数二: 正在被代理的方法
//参数三: 被代理方法,应该传入的参数
long startTimer = System.currentTimeMillis();
//马上触发方法的真正执行。(触发真正的业务功能)
Object result = method.invoke(obj,args);
long endTimer = System.currentTimeMillis();
System.out.println(method.getName() + "方法耗时: " + (endTimer-startTimer)/1000.0 + "s");
//把业务功能方法执行的结果返回给调用者
return result;
}
});
}
}
最后,在正常逻辑业务中,即可不再重复写性能统计的代码
package CC.Proxy;
public class UserServiceImpl implements UserService{
@Override
public String login(String loginName, String passWord) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if("admin".equals(loginName) && "1234".equals(passWord)){
return "success";
}
return "登录名和密码可能有毛病";
}
@Override
public void selectUsers() {
System.out.println("查询了100个用户数据!");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public boolean deleteUsers() {
try {
System.out.println("删除了100个用户数据!");
Thread.sleep(500);
return true;
} catch (InterruptedException e) {
e.printStackTrace();
return false;
}
}
@Override
public void updateUsers() {
try {
System.out.println("修改了100个用户!");
Thread.sleep(2500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
想要增添其他方法的时候,只需写正常的业务逻辑代码,无需再写性能统计的代码。达到动态代理的效果