动态代理的实现有两种方式:1. jdk动态代理;2. cglib动态代理
jdk动态代理
使用反射包中的类和接口实现动态代理的功能,反射包java.lang.reflect,里面有三个类:InvocationHandler,Method,Proxy
InvocationHandler接口:invoke(),表示代理类中要执行的功能代码。代理类的功能要写在invoke()方法中。
/**
* param proxy 动态代理创建出的对象
* param method 目标方法
* param args 目标参数
*/
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
Proxy核心的对象。用来创建动态代理的对象。之前创建的对象都是new类的构造方法(),动态代理中使用Proxy类中的方法来代替new。
Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
动态代理的两个示例
- 动态生成实现了
UserMapper接口的类
public interface UserMapper {
/**
* 通过用户ID查询用户名
*/
String getUsernameByUserId(Long id);
/**
* 通过用户名查询用户数量
*/
Long countByUsername(String username);
}
实现InvocationHandler并且创建出代理类:
/**
* @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("通过用户名查询用户数量,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"));
}
}
- 使用动态代理对
UserServiceImpl类进行增强:
public interface UserService {
String findUsernameByUserId(Long userId);
}
public class UserServiceImpl implements UserService {
@Override
public String findUsernameByUserId(Long userId) {
System.out.println("从数据库中查询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("开启数据库连接。。。。");
Object result = method.invoke(target, args);
System.out.println("关闭数据库连接。。。。");
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));
}
}