反射与动态代理
13 Jul 2018 | Java |反射可以在程序运行期间调用对象信息(public protected default private 的字段、方法、接口类、父类等等)。
为什么会使用反射?比如我现在需要调用别人写的的一个类,但是,此时,别人的代码还没有完成,我是无法直接使用的(比如类里面的某个方法不存在,我直接调用了,编辑器就会报错,即无法通过编译),这个时候我可以通过反射的机制来使用类的所有信息。
动态代理是为某一个对象提供一个代理对象以控制对真正对象的访问。
动态代理的实现方式可以用JDK本身提供的(就是基于反射机制实现的);也可以使用CGLIB动态代理(基于ASM机制实现)。
JDK代理:
- 由JDK本身提供,更加可靠
- 代码实现简单
- 可以平滑升级(不要停止服务,可以直接重启而不影响业务,用户也感觉不到)
CGLIB代理:
- 可以处理没有实现接口的类(JDK代理处理的类需要实现接口)
- 高性能
基于反射的动态代理
```java public class MyDynamicProxy { public static void main (String[] args) { HelloImpl hello = new HelloImpl(); MyInvocationHandler handler = new MyInvocationHandler(hello); // 构造代码实例 /** *为什么我们这里可以将其转化为Hello类型的对象?原因就是在newProxyInstance这个方法的第二个参数上, 我们给这个代理对象提供了一组什么接口,那么我这个代理对象就会实现了这组接口,这个时候我们当然可以将这个 代理对象强制类型转化为这组接口中的任意一个,因为这里的接口是Hello类型,所以就可以将其转化为Hello类型了。 */ Hello proxyHello = (Hello) Proxy.newProxyInstance(HelloImpl.class.getClassLoader(), HelloImpl.class.getInterfaces(), handler); // 调用代理方法 proxyHello.sayHello();//代理对象调用方法时,会先被InvocationHandler的invoke()拦截 } } interface Hello { void sayHello(); } class HelloImpl implements Hello { @Override public void sayHello() { System.out.println(“Hello World”);//真正的方法 } } 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(“Invoking sayHello”); Object result = method.invoke(target, args);//真正的方法被调用 return result; } }
##### 基于CGLIB的动态代理
```java
public class MyDynamicProxy_CGLIB {
public static void main (String[] args) {
MyCglibProxy cglibProxy = new MyCglibProxy();
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(HelloImpl.class);
enhancer.setCallback(cglibProxy);//MethodInterceptor是Callback的子接口
HelloImpl proxyHello = (HelloImpl)enhancer.create();
// 调用代理方法
proxyHello.sayHello();
}
}
class HelloImpl {
public void sayHello() {
System.out.println("Hello World");//真正的方法
}
}
public class MyCglibProxy implements MethodInterceptor{
@Override
public Object intercept(Object o, Method method, Object[] arg2, MethodProxy methodProxy) throws Throwable {
// TODO Auto-generated method stub
System.out.println("调用方法之 前 干点其他事儿......");
Object o1 = methodProxy.invokeSuper(o, arg2);
System.out.println("调用方法之 后 干点其他事儿......");
return o1;
}
}