一、java动态代理原理基础
代理原理基础:
实际是一种设计模式即代理模式,是面向对象的分析设计编程思想。
代理模式概念:
给某一个对象提供一个代理,并由代理对象来控制对真是对象的访问,代理模式是一种结构型设计模式
代理模式角色:
Subject(抽象主题角色):定义代理类和真是主题的公共对外方法,也就是代理类代理真实主题的方法
RealSubject(真实主题角色):真正实现业务逻辑的类
Proxy(代理主题角色):用来代理和封装真实主题
代理模式类型:
分为静态代理和动态代理
静态代理即:在程序运行前已经存在代理类的字节码文件,代理类和真实主题角色在运行前已确定
动态代理即:在程序运行期间由JVM根据反射等机制动态的生成,所以在运行前并不存在代理类的字节码文件
二、java动态代理实现
动态代理主要实现的:一种JDK动态代理,一种是CGLIB字节码机制
1.JDK动态代理实现方式
JDK动态代理实现原理就是java提供了一个Proxy类和一个InvocationHandler接口,通过这个类和这个接口使用反射机制实现生成JDK动态代理类和动态代理对象。
JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理
示例:
/**
*定义一个接口
*/
public interface UserService {
void save();
}
/**
* @Date: 2020/11/21 09:03
* @Description: 创建需要被代理的实现类:
*/
public class UserServiceImpl implements UserService {
@Override
public void save() {
System.out.println("----已经保存数据!----");
}
}
/**
* @Date: 2020/11/21 09:03
* @Description: 创建动态代理对象:
*/
public class LogHandler implements InvocationHandler {
//被代理的目标对象
private Object target;
public LogHandler(Object target) {
this.target = target;
if (target == null){
throw new NullPointerException("target must be non-null");
}
}
/**
* 执行目标对象的方法
*
* @param proxy 代理对象
* @param method 代理方法
* @param args 方法参数
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] objects) throws Throwable{
before();
Object invoke = method.invoke(target, objects);
after();
return invoke;
}
// 调用invoke方法之前执行
private void before() {
System.out.println(String.format("log start time [%s] ", LocalDateTime.now()));
}
// 调用invoke方法之后执行
private void after() {
System.out.println(String.format("log end time [%s] ", LocalDateTime.now()));
}
}
/**
* @Date: 2020/11/21 09:23
* @Description: 测试类
*/
public class DynamicProxyTest {
public static void main(String... args){
UserService userService = new UserServiceImpl();
ClassLoader classLoader = userService.getClass().getClassLoader();
InvocationHandler invocationHandler = new LogHandler(userService);
Class<?>[] interfaces = userService.getClass().getInterfaces();
UserService proxy = (UserService) Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
proxy.save();
}
}
这里只介绍java动态代理,也没有介绍源码原因如下:
1.平时用jdk比较多
2.也是介绍一种思想,学习别人编程思维。
3.还是要自己去实践与学习,自己要去查阅源码,再结合自己得想法去创新