本文最后更新于 2024-02-12T10:11:04+08:00
Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的法的功能称为java语言的反射机制。
反射机制:具有操作字节码文件的能力
- java.lang.Class :保留一个类的全部信息
- java.util.reflect.Constructor:保存了一个类当中的构造方法的所有信息
- java.util.reflect.Method:保存了一个类当中的方法的所有信息
- java.util.reflect.Field:保存了一个类当中的成员属性的所有信息
动态代理
动态代理简单来说就是在程序执行过程中,创建代理对象,通过代理对象执行方法,给目标类的方法增加额外的功能,也叫做功能增强。
JDK动态代理的实现步骤
- 首先我们需要有一个目标类,在目标类的基础上通过动态代理实现功能增强
- 创建InvocationHandler接口的实现类,在这个类中实现invoke方法,在invoke方法中实现给目标类的方法增强功能
- 通过JDK中的Proxy创建代理,通过代理调用目标类中的方法,实现功能增强
JDK动态代理的代码实现
- 创建一个接口
1 2 3 4
| public interface SomeService { void doSome(); void doOther(); }
|
- 目标类实现这个接口:
1 2 3 4 5 6 7 8 9 10 11 12
| public class SomeServiceImpl implements SomeService {
@Override public void doSome() { System.out.println("执行doSome"); }
@Override public void doOther() { System.out.println("执行doOther"); } }
|
- 创建一个工具类,里面是增强的功能:
1 2 3 4 5 6 7 8 9 10 11
| public class ServiceTools {
public static void doLog(){ System.out.println("方法的执行时间:" + new Date()); }
public static void doTrans(){ System.out.println("方法执行完毕,提交事务"); }
}
|
- 创建InvocationHandler接口的实现类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| public class MyInvocationHandler implements InvocationHandler { private Object target;
public MyInvocationHandler(Object target) { this.target = target; }
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("执行MyInvocationHandler中的invoke方法");
System.out.println(method.getName());
Object res = null;
ServiceTools.doLog();
res = method.invoke(target, args);
ServiceTools.doTrans();
return res; } }
|
- 通过Proxy创建代理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public static void main(String[] args) { SomeService target = new SomeServiceImpl();
InvocationHandler handler = new MyInvocationHandler(target);
SomeService proxy = (SomeService) Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), handler );
proxy.doSome(); }
|
通用类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| public class JdkProxy implements InvocationHandler {
private Object target;
public JdkProxy(Object target) { this.target = target; }
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { long starTime = System.nanoTime(); Object result = method.invoke(this.target, args); long endTime = System.nanoTime(); System.out.println(this.target.getClass() + ".m1()方法耗时(纳秒):" + (endTime - starTime)); return result; }
public static <T> T createProxy(Object target, Class<T> targetInterface) { if (!targetInterface.isInterface()) { throw new IllegalStateException("targetInterface必须是接口类型!"); } else if (!targetInterface.isAssignableFrom(target.getClass())) { throw new IllegalStateException("target必须是targetInterface接口的实现类!"); } return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new JdkProxy(target)); }
public static <T> T createProxy(Object target) { return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new JdkProxy(target)); } }
使用: IService proxy = JdkProxy.createProxy(new SomeServiceImpl(), SomeService.class);
IService proxy1 = JdkProxy.createProxy(new SomeServiceImpl());
|
总结一下动态代理实现过程:
- 通过getProxyClass0()生成代理类。
- 通过Proxy.newProxyInstance()生成代理类的实例对象,创建对象时传入InvocationHandler类型的实例。
- 调用新实例的方法,即此例中的m1(),m2(),即原InvocationHandler类中的invoke()方法。
动态代理的作用:
- 在目标类源代码不改变的情况下,增加目标类的功能
- 当涉及到多个方法都需要增加某些同样的功能时,使用动态代理可以减少代码的重复
- 可以使目标类专注于业务逻辑代码
- 实现解耦合,让业务功能和日志、事务和非事务功能分离
为什么jdk动态代理必须实现接口:
1 2 3 4 5 6 7 8 9
| String path = "logs/$Proxy0.class"; byte[] classFile = ProxyGenerator.generateProxyClass("$Proxy0", IServiceImpl.class.getInterfaces());
FileOutputStream out = new FileOutputStream(path); out.write(classFile); out.flush(); out.close();
|
cglib
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| public static void main(String[] args) {
Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(Service1.class);
enhancer.setCallback(new MethodInterceptor() { @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("调用方法:" + method); Object result = methodProxy.invokeSuper(o, objects); return result; } }); Service1 proxy = (Service1) enhancer.create(); proxy.m1(); proxy.m2();
Service1 proxy1 = CglibProxy.createProxy(new Service1()); proxy1.m2(); proxy1.m1(); }
|
通用方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| public class CglibProxy implements MethodInterceptor {
private Object target;
public CglibProxy(Object target) { this.target = target; }
@Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { long starTime = System.nanoTime(); Object result = method.invoke(target, objects); long endTime = System.nanoTime(); System.out.println(method + ",耗时(纳秒):" + (endTime - starTime)); return result; }
public static <T> T createProxy(T target) { CglibProxy cglibProxy = new CglibProxy(target); Enhancer enhancer = new Enhancer(); enhancer.setCallback(cglibProxy); enhancer.setSuperclass(target.getClass()); return (T) enhancer.create(); } }
|
Service1
1 2 3 4 5 6 7 8 9 10 11
| public class Service1 {
public void m1() { System.out.println("m1"); }
public void m2() { System.out.println("m2"); } }
|