反射
- 理解:
- 反射是在字节码交由JVM解释时,可以动态的获取类的结构信息,进而实现动态访问。
- 这种访问是对类、字段、方法信息的获取与使用,并不能进行更改,非要更改只能通过是ASM等字节码操作库去,动态创建修改类。当然如果想通过类加载器动态加载类依然是反射实现。
- 反射的具体实现是由java.lang.reflect内提供的运行时检查和操作类属性和方法的API。
- 值得一提的是反射时,会进行安全检查(有权限修饰符的检查,也有安全管理器对反射行为的检查)和类型检查,这种行为所带来的额外开销,会影响性能。
动态代理
-
JDK动态代理:
- 动态代理是基于反射实现,用于动态创建代理对象,并拦截和处理方法调用。用两种实现方式:基于接口实现的动态代理(JDK动态代理)、基于类实现的动态代理(CGLIB)。
-
JDK动态代理:
- 只能为实现了接口的类生成代理对象。
- 通过
Proxy类和InvocationHandler接口来实现。
import java.lang.reflect.Proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; interface MyInterface { void doSomething(); } class MyInterfaceImpl implements MyInterface { public void doSomething() { System.out.println("Doing something..."); } } class MyInvocationHandler implements InvocationHandler { private final Object target; public MyInvocationHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Before method call"); Object result = method.invoke(target, args); System.out.println("After method call"); return result; } } public class Main { public static void main(String[] args) { MyInterface target = new MyInterfaceImpl(); MyInterface proxyInstance = (MyInterface) Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), new MyInvocationHandler(target) ); proxyInstance.doSomething(); } } -
CGLIB动态代理:
- 可以代理没有实现接口的类,通过字节码生成技术创建代理类。
- 主要使用
Enhancer类来创建代理对象,并设置回调方法。
import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; class MyClass { public void doSomething() { System.out.println("Doing something..."); } } class MyMethodInterceptor implements MethodInterceptor { @Override public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("Before method call"); Object result = proxy.invokeSuper(obj, args); System.out.println("After method call"); return result; } } public class Main { public static void main(String[] args) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(MyClass.class); enhancer.setCallback(new MyMethodInterceptor()); MyClass proxy = (MyClass) enhancer.create(); proxy.doSomething(); } }
应用场景
-
反射应用场景:
- 序列化与反序列化:通过反射获取对象字段信息进行序列化和反序列化。
- Spring框架:Spring利用反射机制实现控制反转(IoC)和依赖注入(DI)。
- 动态加载类:根据需要动态加载和操作类。
-
动态代理应用场景:
- AOP(面向切面编程):动态代理用于在运行时织入横切关注点(如日志记录、事务管理等)。
- 装饰器模式:在运行时为对象提供额外的功能而无需修改原有类。