動態(tài)代理的實現(xiàn)有兩種方式:1. jdk動態(tài)代理;2. cglib動態(tài)代理
jdk動態(tài)代理
使用反射包中的類和接口實現(xiàn)動態(tài)代理的功能,反射包java.lang.reflect,里面有三個類:InvocationHandler,Method,Proxy
InvocationHandler接口:invoke(),表示代理類中要執(zhí)行的功能代碼。代理類的功能要寫在invoke()方法中。
/**
* param proxy 動態(tài)代理創(chuàng)建出的對象
* param method 目標(biāo)方法
* param args 目標(biāo)參數(shù)
*/
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
Proxy核心的對象。用來創(chuàng)建動態(tài)代理的對象。之前創(chuàng)建的對象都是new類的構(gòu)造方法(),動態(tài)代理中使用Proxy類中的方法來代替new。
Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
動態(tài)代理的兩個示例
- 動態(tài)生成實現(xiàn)了
UserMapper接口的類
public interface UserMapper {
/**
* 通過用戶ID查詢用戶名
*/
String getUsernameByUserId(Long id);
/**
* 通過用戶名查詢用戶數(shù)量
*/
Long countByUsername(String username);
}
實現(xiàn)InvocationHandler并且創(chuàng)建出代理類:
/**
* @author YanYu
*/
public class MapperHandler implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ("getUsernameByUserId".equals(method.getName())) {
System.out.println("通過用戶ID查詢用戶名");
return "admin " + "id:" + args[0];
} else if ("countByUsername".equals(method.getName())) {
System.out.println("通過用戶名查詢用戶數(shù)量,username: " + args[0]);
return 1L;
}
throw new RuntimeException("method not found");
}
public static void main(String[] args) {
UserMapper userMapper = (UserMapper) Proxy.newProxyInstance(
MapperHandler.class.getClassLoader(),
new Class[]{ UserMapper.class },
new MapperHandler()
);
System.out.println(userMapper.getUsernameByUserId(5L));
System.out.println(userMapper.countByUsername("admin"));
}
}
- 使用動態(tài)代理對
UserServiceImpl類進(jìn)行增強(qiáng):
public interface UserService {
String findUsernameByUserId(Long userId);
}
public class UserServiceImpl implements UserService {
@Override
public String findUsernameByUserId(Long userId) {
System.out.println("從數(shù)據(jù)庫中查詢userId: " + userId + " 的用戶");
return "admin";
}
}
public class ServiceHandler implements InvocationHandler {
private Object target;
public ServiceHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("開啟數(shù)據(jù)庫連接。。。。");
Object result = method.invoke(target, args);
System.out.println("關(guān)閉數(shù)據(jù)庫連接。。。。");
return result;
}
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
UserService userServiceProxy = (UserService) Proxy.newProxyInstance(
userService.getClass().getClassLoader(),
UserServiceImpl.class.getInterfaces(),
new ServiceHandler(userService)
);
System.out.println(userServiceProxy.findUsernameByUserId(5L));
}
}