java反射与代理

来源:互联网 发布:2017年网络热点话题 编辑:程序博客网 时间:2024/06/05 02:51

反射,主要jdk包:java.lang.reflect

定义类 -> 创建对象 -> 通过对象操作方法、赋值或获取属性等;
定义类 -> 获取类的属性(Field)或方法对象(Method) -> 创建对象 -> 类的属性(Field)或方法对象(Method)在该对象上的调用;

类加载器加载类 <-> 类获取类加载器
ClassLoader.loadClass() <-> Class.getClassLoader();

类定义对象 <-> 对象获取类
Object obj <-> obj.getClass();

代码示例:

HelloReflect接口

public interface HelloReflect {    void sayHello();}

HelloReflect接口实现类

public class HelloReflectImpl implements HelloReflect {    private int id;    @Override    public void sayHello() {        System.out.println("hello, reflect!");    }}

HelloReflect接口代理类

import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class HelloReflectProxy {    private HelloReflect helloReflect;    public HelloReflectProxy(HelloReflect helloReflect) {        this.helloReflect = helloReflect;    }    public HelloReflect getProxy() {        HelloReflect proxy = (HelloReflect) Proxy.newProxyInstance(                helloReflect.getClass().getClassLoader(), helloReflect.getClass().getInterfaces(), new InvocationHandler() {                    @Override                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {                        System.out.println("proxy stdout begin...");                        Object object = method.invoke(helloReflect, args);                        System.out.println("proxy stdout end...");                        return object;                    }                });        return proxy;    }}

反射与jdk动态代理测试类

import java.lang.reflect.Field;import java.lang.reflect.Method;public class TestHelloReflect {    public static void main(String[] args) throws Exception {        HelloReflect helloReflect = new HelloReflectImpl();        //field、method        Field field = HelloReflectImpl.class.getDeclaredField("id");        Method method = HelloReflectImpl.class.getDeclaredMethod("sayHello");        field.setAccessible(true);        field.set(helloReflect, 1);        System.out.println(field.get(helloReflect));        method.invoke(helloReflect);        //proxy、invocationHandler        HelloReflectProxy helloReflectProxy = new HelloReflectProxy(helloReflect);        helloReflect = helloReflectProxy.getProxy();        helloReflect.sayHello();    }}

jdk动态代理:

利用的是被代理类的接口生成的代理类,代理类里会有一个被代理类对象,在调用代理类的方法时,实际上是通过代理类里InvocationHandler对象的invoke方法通过反射来调用被代理类的方法,在invoke这个方法里可以对method做不同判断和处理,实现不同的切面功能等,代理类与被代理类之间是实现的相同接口,所以只能代理接口方法,代理类对象里包含一个被代理类的对象,代理类与被代理类之间是”兄弟”关系

另一种动态代理:cglib,Code Generation Library

需要引入第三方jar包:cglib或cglib-nodep,cglib包需要引入asm包,部分老版本cglib包没有包含asm包、需要单独引入,cglib-nodep包没有asm包、不需要asm包

<dependencies>    <dependency>        <groupId>cglib</groupId>        <artifactId>cglib</artifactId>        <version>3.2.5</version>    </dependency></dependencies>

代码示例:

HelloCglib类,不需实现接口

public class HelloCglib {    public final void testFinal() {        System.out.println("TestFinal, Cglib!");    }    public void sayHello() {        System.out.println("Hello, Cglib!");    }    public void sayHehe() {        System.out.println("Hehe, Cglib!");    }}

HelloCglib代理对象方法回调过滤器

import net.sf.cglib.proxy.CallbackFilter;import java.lang.reflect.Method;public class HelloCglibCallbackFilter implements CallbackFilter {    @Override    public int accept(Method method) {        if("sayHello".equals(method.getName()) || "testFinal".equals(method.getName())) {            return 1;        }        if("sayHehe".equals(method.getName())) {            return 2;        }        return 0;    }}

HelloCglib代理对象sayHello方法拦截器

import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;public class HelloCglibSayHelloInterceptor implements MethodInterceptor {    @Override    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {        System.out.println("cglib say hello interceptor stdout begin...");        Object object = methodProxy.invokeSuper(o, objects);        System.out.println("cglib say hello interceptor stdout end...");        return object;    }}

HelloCglib代理对象sayHehe方法拦截器

import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;public class HelloCglibSayHeheInterceptor implements MethodInterceptor {    @Override    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {        System.out.println("cglib say hehe interceptor stdout begin...");        Object object = methodProxy.invokeSuper(o, objects);        System.out.println("cglib say hehe interceptor stdout end...");        return object;    }}

HelloCglib代理对象测试类

import net.sf.cglib.proxy.Callback;import net.sf.cglib.proxy.CallbackFilter;import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.NoOp;public class TestHelloCglib {    public static void main(String[] args) {        Enhancer enhancer = new Enhancer();        enhancer.setSuperclass(HelloCglib.class);        CallbackFilter callbackFilter = new HelloCglibCallbackFilter();        Callback defaultCallBack = NoOp.INSTANCE;        Callback helloCglibSayHelloInterceptor = new HelloCglibSayHelloInterceptor();        Callback helloCglibSayHeheInterceptor = new HelloCglibSayHeheInterceptor();        Callback[] callbacks = new Callback[]{defaultCallBack, helloCglibSayHelloInterceptor, helloCglibSayHeheInterceptor};        enhancer.setCallbackFilter(callbackFilter);        enhancer.setCallbacks(callbacks);        HelloCglib helloCglib = (HelloCglib) enhancer.create();        helloCglib.testFinal();        helloCglib.sayHello();        helloCglib.sayHehe();    }}

cglib动态代理

需引入第三方包,被代理对象无需实现接口,代理对象是被代理对象的子类,两者属于”父子”关系,代理类无法代理被代理类的final方法,无法Override所以还是调用的父类被代理对象的final方法

cglib代理逻辑:代理类调用方法 -> CallbackFilter方法回调过滤器 -> Callback方法拦截(前置处理 -> methodProxy.invokeSuper(o, objects) -> 后置处理),如果只有单个Callback方法拦截器,且拦截所有方法,则无需设置CallbackFilter

Enhancer类的一些创建方法:
Enhancer.create();//该方法需单独设置superclass等信息
Enhancer.create(Class superclass, Callback callback);
Enhancer.create(Class superclass, Class[] interfaces, Callback callback);
Enhancer.create(Class superclass, Class[] interfaces, CallbackFilter filter, Callback[] callbacks);

另外,cglib包里也实现了类似于jdk里的基于接口的动态代理,使用方法和jdk里的动态代理类似,只不过引入的包需换成net.sf.cglib.proxy包

import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class TestHelloReflect2 {    public static void main(String[] args) {        final HelloReflect helloReflect = new HelloReflectImpl();        HelloReflect helloReflectProxy = (HelloReflect) Proxy.newProxyInstance(                helloReflect.getClass().getClassLoader(), helloReflect.getClass().getInterfaces(), new InvocationHandler() {            @Override            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {                System.out.println("cglib proxy stdout begin...");                Object object = method.invoke(helloReflect, args);                System.out.println("cglib proxy stdout end...");                return object;            }        });        helloReflectProxy.sayHello();    }}
原创粉丝点击