反射,主要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();
}
}