概述
上篇文章《Java反射——Class和ClassLoader 》,我们简单介绍了反射的基本概念及相关类。这里介绍下,反射的一个主要应用——动态代理。
动态代理
动态代理的实现,两种方式:JDK动态代理和CGLIB动态代理。
步骤都基本相同,获得代理类,执行调用方法进行方法增强。
代理模式类图如下:
此处Proxy代理了具体的对象(RealSubject),如果我们想让这种代理关系更普适,就引出了动态代理,即Proxy可以代理很多的对象,具体代理哪个对象在运行时才能确定。
Java中实现了这种方式,即JDK动态代理。
JDK
只能代理接口。
Proxy:通用的生成代理对象类,创建参数为InvocationHandler。
public class JDKProxy implements InvocationHandler{
//需要代理的目标对象
private Object target;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("动态代理开始");
Object invoke = method.invoke(target, args);
System.out.println("动态代理结束");
return invoke;
}
/**
* 获取代理对象
* @param targetObject 目标对象
* @return
*/
private Object getJDKProxy(Object targetObject){
this.target=targetObject;
//JDK动态代理,只能针对实现了接口的类进行代理。
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),targetObject.getClass().getInterfaces(),this);
}
public static void main(String[] args) {
JDKProxy jdkProxy=new JDKProxy();
//获取代理对象
AgencyService agencyService=(AgencyService)jdkProxy.getJDKProxy(new AgencyServiceImpl());
//执行代理对象的方法
agencyService.queryAgency(new AgencyInfo());
}
}
CGLIB
可以代理类。
import com.family.model.AgencyInfo;
import com.family.service.AgencyService;
import com.family.service.impl.AgencyServiceImpl;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* @author
* @description
* @date Created in 下午6:42 2019/7/25
*/
public class CGLIBProxy implements MethodInterceptor {
private Object target;
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("CGLIB动态代理,开始");
Object invoke=method.invoke(target,objects);
System.out.println("CGLIB动态代理,结束");
return invoke;
}
/**
* 定义获取代理对象的方法
* @param targetObject
* @return
*/
public Object getCglibProxy(Object targetObject){
this.target=targetObject;
//设置父类
Enhancer enhancer=new Enhancer();
enhancer.setSuperclass(targetObject.getClass());
//设置回调
enhancer.setCallback(this);
//创建并返回代理对象
Object result=enhancer.create();
return result;
}
public static void main(String[] args) {
CGLIBProxy cglibProxy=new CGLIBProxy();
//获取代理对象
AgencyService agencyService=(AgencyService)cglibProxy.getCglibProxy(new AgencyServiceImpl());
agencyService.queryAgency(new AgencyInfo());
}
}
API
1.Proxy
提供了创建动态代理类和示例的静态方法,也是所有动态代理类的超类。
针对接口创建代理类
动态代理类:(动态代理)类在被创建时,实现了一系列在运行时指定的接口。
代理接口:被代理类实现的接口。
代理实例:代理类的一个实例。
//根据传入的类加载器、代理的接口、invocationHandler返回动态代理类实例。
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
Objects.requireNonNull(h);
//克隆代理接口
final Class<?>[] intfs = interfaces.clone();
//校验代理类的访问权限
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
//获得代理类
Class<?> cl = getProxyClass0(loader, intfs);
/*
* 调用指定invocation handler的构造器
*/
try {
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
//获取代理类的构造方法
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
//调用构造方法,创建实例
return cons.newInstance(new Object[]{h});
} catch (IllegalAccessException|InstantiationException e) {
throw new InternalError(e.toString(), e);
} catch (InvocationTargetException e) {
Throwable t = e.getCause();
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else {
throw new InternalError(t.toString(), t);
}
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString(), e);
}
}
2.InvocationHandler
作用:完成方法的拦截与代理。
当调用代理实例的方法时,下面的invoke()会被执行。
invoke()的参数说明:
proxy:代理实例
method:对应的接口方法
args:(在代理实例的方法调用中)传递的参数值的对象数组
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
3.MethodInterceptor
通用的回调,做拦截。
public interface MethodInterceptor
extends Callback
{
public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args,
MethodProxy proxy) throws Throwable;
}
4.Enhancer
生成代理子类。动态生成的子类,会重写超类的非final方法,并且会有回调的钩子来实现用户自定义的拦截。
public class Enhancer extends AbstractClassGenerator
{
//设置超类(生成类需要继承的类)
public void setSuperclass(Class superclass) {
if (superclass != null && superclass.isInterface()) {
setInterfaces(new Class[]{ superclass });
} else if (superclass != null && superclass.equals(Object.class)) {
// affects choice of ClassLoader
this.superclass = null;
} else {
this.superclass = superclass;
}
}
//设置回调
public void setCallback(final Callback callback) {
setCallbacks(new Callback[]{ callback });
}
public void setCallbacks(Callback[] callbacks) {
if (callbacks != null && callbacks.length == 0) {
throw new IllegalArgumentException("Array cannot be empty");
}
this.callbacks = callbacks;
}
//获取/生成一个类
public Object create() {
classOnly = false;
argumentTypes = null;
return createHelper();
}
private Object createHelper() {
preValidate();
Object key = KEY_FACTORY.newInstance((superclass != null) ? superclass.getName() : null,
ReflectUtils.getNames(interfaces),
filter == ALL_ZERO ? null : new WeakCacheKey<CallbackFilter>(filter),
callbackTypes,
useFactory,
interceptDuringConstruction,
serialVersionUID);
this.currentKey = key;
Object result = super.create(key);
return result;
}
}
super.create(key)即AbstractClassGenerator中的create()
protected Object create(Object key) {
try {
ClassLoader loader = getClassLoader();
Map<ClassLoader, ClassLoaderData> cache = CACHE;
ClassLoaderData data = cache.get(loader);
if (data == null) {
synchronized (AbstractClassGenerator.class) {
cache = CACHE;
data = cache.get(loader);
if (data == null) {
Map<ClassLoader, ClassLoaderData> newCache = new WeakHashMap<ClassLoader, ClassLoaderData>(cache);
data = new ClassLoaderData(loader);
newCache.put(loader, data);
CACHE = newCache;
}
}
}
this.key = key;
Object obj = data.get(this, getUseCache());
if (obj instanceof Class) {
return firstInstance((Class) obj);
}
return nextInstance(obj);
} catch (RuntimeException e) {
throw e;
} catch (Error e) {
throw e;
} catch (Exception e) {
throw new CodeGenerationException(e);
}
}
小结
动态代理,可以动态的对指定方法进行增强。动态代理的两种实现方式:JDK动态代理和CGLIB动态代理。
JDK动态代理只可以为接口去完成操作,采用的是反射机制,无需引入其他jar包。
CGLIB对指定的目标生成一个子类,并覆盖其中方法实现增强,采用的是继承。