一、什么是代理模式
代理模式指一个对象A通过持有另一个对象B,可以具有对象B同样的行为。简单点说,就是多一个代理对象,替原对象处理一些操作。在一些情况下,一个对象不能或者不想直接访问另一个对象,那么就会通过一个中介对象帮忙访问处理。这个中介对象就是代理对象,这种模式即为代理模式。通过代理模式,我们可以更好的保护原本业务,不被外界代码所侵入,形成防御式编程。
代理模式一般分为三种角色:
• 抽象(Subject)主题角色:通过接口或者抽象类声明真实主题和代理对象实现的业务方法。也是通过接口或者抽象类,声明真实主题和代理的共同接口方法。
• 真实(Real Subject)主题角色:实现了抽象主题中的具体业务方法,是最终要引用的对象。
• 代理(Proxy)主题角色:提供了与真实主题相同的接口,包含了真实主题的引用,它可以访问、控制或者增强真实主题的功能。
代理模式的优点:
• 降低代码的耦合度,拓展性好;
• 保护目标对象;
• 增强目标对象。
代理模式的缺点:
• 类的数量增加;
• 增加了代理对象,处理变慢;
• 系统复杂度增加。
使用代理模式的主要两个目的:保护目标对象,增强目标对象。
java实现代理有两种方式,静态代理和动态代理。java动态代理的实现方式一般为:JDK动态代理和CGLib动态代理,javasist动态代理。
二、静态代理和动态代理
1、静态代理
静态代理就是在代码运行前代理类已经存在,一旦创建了,在程序运行期间不允许被修改或者很难被修改。这种代理类是在编译前就创建好了,由我们手动创建,不是编译器自动生成,编译前,接口,代理类,目标对象就确定下来了。一般静态代理中,代理类和目标类都会实现同一个接口或者继承同一父类。
Subject类,定义了超市的行为,送货到家
package com.chenys.proxyTest;
/**
* @author chenys
* 抽象主题角色 - 超市的行为
* Subject
*/
public interface SuperMarketAction {
/**
* 送货操作
*/
void deliverGoods();
}
RealSubject类,定义Proxy所代表的真实实体。即超市
package com.chenys.proxyTest;
/**
* @author chenys
* Real Subject - 超市
*/
public class SuperMarket implements SuperMarketAction{
/**
* 送货
*/
@Override
public void deliverGoods() {
System.out.println("SuperMarket.deliverGoods()");
}
}
Proxy代理类,通过保存引用访问实体
package com.chenys.proxyTest;
/**
* @author chenys
* Proxy代理类 - 物流公司
*/
public class ExpressCompanyProxy implements SuperMarketAction{
private SuperMarket superMarket;
public ExpressCompanyProxy(SuperMarket superMarket) {
this.superMarket = superMarket;
}
/**
* 代理类执行操作 - 寄快递,相当于超市将物品发给物流公司,由物流公司进行分发到各个人手中。
*/
@Override
public void deliverGoods() {
System.out.println("代理类调用委托类方法之前");
superMarket.deliverGoods();
System.out.println("代理类调用委托类方法之后");
}
}
未使用代理类测试
package com.chenys.proxyTest;
/**
* 测试类
*/
public class StaticProxyMain {
public static void main(String[] args) {
SuperMarket superMarket = new SuperMarket();
superMarket.deliverGoods();
}
}
测试结果
SuperMarket.deliverGoods()
使用代理类测试
package com.chenys.proxyTest;
/**
* 测试类
*/
public class StaticProxyMain {
public static void main(String[] args) {
SuperMarket superMarket = new SuperMarket();
ExpressCompanyProxy proxy = new ExpressCompanyProxy(superMarket);
proxy.deliverGoods();
}
}
测试结果
代理类调用委托类方法之前
SuperMarket.deliverGoods()
代理类调用委托类方法之后
2、动态代理
动态代理,在程序运行时,根据指示动态的生成代理类。JAVA的动态代理常用的有JDK动态代理和CGLib动态代理。
2-1、JDK动态代理
JDK动态代理,主要使用java.lang.reflect包下面的Proxy类和InvocationHandler接口。
Subject类,定义了超市的行为,送货到家
package com.chenys.proxyTest;
/**
* @author chenys
* 抽象主题角色 - 超市的行为
* Subject
*/
public interface SuperMarketAction {
/**
* 送货操作
*/
void deliverGoods();
}
RealSubject类,定义Proxy所代表的真实实体。即超市
package com.chenys.proxyTest;
/**
* @author chenys
* Real Subject - 超市
*/
public class SuperMarket implements SuperMarketAction{
/**
* 送货
*/
@Override
public void deliverGoods() {
System.out.println("SuperMarket.deliverGoods()");
}
}
Proxy代理类,动态生成
package com.chenys.jdkproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 动态代理 - 实现InvocationHandler接口
* Each proxy instance has an associated invocation handler.
* * When a method is invoked on a proxy instance, the method
* * invocation is encoded and dispatched to the {@code invoke}
* * method of its invocation handler.
* 每个动态代理示例都有这样一个关联接口,当动态代理示例对象执行方法时,会调用InvocationHandler的invoke方法进行增强调用
*/
public class SuperMarketInvocationHandler implements InvocationHandler {
/**
* 被代理对象
*/
private SuperMarketAction superMarket;
/**
* 构造函数
* @param superMarket
*/
public SuperMarketInvocationHandler(SuperMarketAction superMarket) {
this.superMarket = superMarket;
}
/**
* 代理对象增强方式
* @param proxy
* @param method
* @param args
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理类调用委托类方法之前");
Object result = method.invoke(superMarket, args);
System.out.println("代理类调用委托类方法之后");
return result;
}
/**
* 创建代理对象
* @return
*/
public Object createProxy() {
return Proxy.newProxyInstance(superMarket.getClass().getClassLoader(),superMarket.getClass().getInterfaces(),this);
}
}
执行方法
package com.chenys.jdkproxy;
import java.lang.reflect.Proxy;
/**
* main方法
*/
public class JdkProxy {
public static void main(String[] args) {
// 方式一
proxy1();
System.out.println("-------------------------");
// 方式二
proxy2();
}
public static void proxy1() {
// 创建要被代理的类
SuperMarketAction superMarketAction = new SuperMarket();
// 创建要被代理类的处理方式
SuperMarketInvocationHandler invocationHandler = new SuperMarketInvocationHandler(superMarketAction);
// 创建代理对象
SuperMarketAction proxy = (SuperMarketAction) Proxy.newProxyInstance(superMarketAction.getClass().getClassLoader(), superMarketAction.getClass().getInterfaces(), invocationHandler);
// 通过代理对象进行调用
proxy.deliverGoods();
}
public static void proxy2() {
SuperMarketAction superMarketAction = new SuperMarket();
SuperMarketInvocationHandler invocationHandler = new SuperMarketInvocationHandler(superMarketAction);
SuperMarketAction proxy = (SuperMarketAction) invocationHandler.createProxy();
proxy.deliverGoods();
}
}
执行结果,方式一和方式二结果一样的,都能正确创建出代理对象,并进行调用
代理类调用委托类方法之前
SuperMarket.deliverGoods()
代理类调用委托类方法之后
-------------------------
代理类调用委托类方法之前
SuperMarket.deliverGoods()
代理类调用委托类方法之后
我们来看看java.lang.reflect.InvocationHandler接口的invoke方法
/**
* proxy: 方法被调用的代理对象实例
* method: 被调用的方法对象
* args: 被调用的方法参数
**/
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
再来看看java.lang.reflect.Proxy的newProxyInstance方法
/**
* loader :被代理对象的类加载器
* interfaces :被代理对象的接口列表
* h :代理类调用方法时处理方式
**/
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
我们来看看上面例子生成的代理类,再上述main方法中,新增一行代码,可以生成com/sun/proxy文件夹,里面会有$Proxy0.class,这个就是jdk动态生成的代理类了
public static void main(String[] args) {
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
// 方式一
proxy1();
System.out.println("-------------------------");
// 方式二
proxy2();
}
$Proxy0.class的内容如下:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.sun.proxy;
import com.chenys.jdkproxy.SuperMarketAction;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class $Proxy0 extends Proxy implements SuperMarketAction {
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m0;
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
/**
* 调用h.invoke方法,增强equals()方法
**/
public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
/**
* 调用h.invoke方法,增强deliverGoods()方法
**/
public final void deliverGoods() throws {
try {
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
/**
* 调用h.invoke方法,增强toString()方法
**/
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
/**
* 调用h.invoke方法,增强hashCode()方法
**/
public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
/**
* 通过反射,获取代理类的接口方法
*
**/
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m3 = Class.forName("com.chenys.jdkproxy.SuperMarketAction").getMethod("deliverGoods");
m2 = Class.forName("java.lang.Object").getMethod("toString");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
2-2、CGLib动态代理
Subject类,定义了超市的行为,送货到家
package com.chenys.proxyTest;
/**
* @author chenys
* 抽象主题角色 - 超市的行为
* Subject
*/
public interface SuperMarketAction {
/**
* 送货操作
*/
void deliverGoods();
}
RealSubject类,定义Proxy所代表的真实实体。即超市
package com.chenys.proxyTest;
/**
* @author chenys
* Real Subject - 超市
*/
public class SuperMarket implements SuperMarketAction{
/**
* 送货
*/
@Override
public void deliverGoods() {
System.out.println("SuperMarket.deliverGoods()");
}
}
Proxy代理类,动态生成
package com.chenys.cglibproxy;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* 代理类处理方法
*/
public class MethodHandler implements MethodInterceptor {
public MethodHandler() {
}
/**
* @param obj 被代理的对象(需要增强的对象)
* @param method 被拦截的方法(需要增强的方法)
* @param args 方法入参
* @param methodProxy 用于调用原始方法
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("代理类调用委托类方法之前");
Object result = methodProxy.invokeSuper(obj, args);
System.out.println("代理类调用委托类方法之后");
return result;
}
}
调用
package com.chenys.cglibproxy;
import org.springframework.cglib.proxy.Enhancer;
/**
* cglib调用
*/
public class CGLibProxy {
public static void main(String[] args) {
// 声明cglib代理增强器对象
Enhancer enhancer = new Enhancer();
// 设置被代理的超类
enhancer.setSuperclass(SuperMarket.class);
// 设置代理方法的增强方法拦截器
enhancer.setCallback(new MethodHandler());
// 创建代理对象
SuperMarket superMarket = (SuperMarket) enhancer.create();
// 调用方法
superMarket.deliverGoods();
}
}
运行结果:
代理类调用委托类方法之前
SuperMarket.deliverGoods()
代理类调用委托类方法之后
通过cgliib生成的动态代理如下:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.chenys.cglibproxy;
import java.lang.reflect.Method;
import org.springframework.cglib.core.ReflectUtils;
import org.springframework.cglib.core.Signature;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.Factory;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
public class SuperMarket$$EnhancerByCGLIB$$cef7fc40 extends SuperMarket implements Factory {
private boolean CGLIB$BOUND;
public static Object CGLIB$FACTORY_DATA;
private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
private static final Callback[] CGLIB$STATIC_CALLBACKS;
private MethodInterceptor CGLIB$CALLBACK_0;
private static Object CGLIB$CALLBACK_FILTER;
private static final Method CGLIB$deliverGoods$0$Method;
private static final MethodProxy CGLIB$deliverGoods$0$Proxy;
private static final Object[] CGLIB$emptyArgs;
private static final Method CGLIB$equals$1$Method;
private static final MethodProxy CGLIB$equals$1$Proxy;
private static final Method CGLIB$toString$2$Method;
private static final MethodProxy CGLIB$toString$2$Proxy;
private static final Method CGLIB$hashCode$3$Method;
private static final MethodProxy CGLIB$hashCode$3$Proxy;
private static final Method CGLIB$clone$4$Method;
private static final MethodProxy CGLIB$clone$4$Proxy;
public SuperMarket$$EnhancerByCGLIB$$cef7fc40() {
CGLIB$BIND_CALLBACKS(this);
}
static {
CGLIB$STATICHOOK1();
}
public final boolean equals(Object var1) {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
Object var2 = var10000.intercept(this, CGLIB$equals$1$Method, new Object[]{var1}, CGLIB$equals$1$Proxy);
return var2 == null ? false : (Boolean)var2;
} else {
return super.equals(var1);
}
}
public final String toString() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
return var10000 != null ? (String)var10000.intercept(this, CGLIB$toString$2$Method, CGLIB$emptyArgs, CGLIB$toString$2$Proxy) : super.toString();
}
public final int hashCode() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
Object var1 = var10000.intercept(this, CGLIB$hashCode$3$Method, CGLIB$emptyArgs, CGLIB$hashCode$3$Proxy);
return var1 == null ? 0 : ((Number)var1).intValue();
} else {
return super.hashCode();
}
}
protected final Object clone() throws CloneNotSupportedException {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
return var10000 != null ? var10000.intercept(this, CGLIB$clone$4$Method, CGLIB$emptyArgs, CGLIB$clone$4$Proxy) : super.clone();
}
public Object newInstance(Callback var1) {
CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});
SuperMarket$$EnhancerByCGLIB$$cef7fc40 var10000 = new SuperMarket$$EnhancerByCGLIB$$cef7fc40();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}
public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
CGLIB$SET_THREAD_CALLBACKS(var3);
SuperMarket$$EnhancerByCGLIB$$cef7fc40 var10000 = new SuperMarket$$EnhancerByCGLIB$$cef7fc40;
switch(var1.length) {
case 0:
var10000.<init>();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
default:
throw new IllegalArgumentException("Constructor not found");
}
}
public Object newInstance(Callback[] var1) {
CGLIB$SET_THREAD_CALLBACKS(var1);
SuperMarket$$EnhancerByCGLIB$$cef7fc40 var10000 = new SuperMarket$$EnhancerByCGLIB$$cef7fc40();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}
public Callback getCallback(int var1) {
CGLIB$BIND_CALLBACKS(this);
MethodInterceptor var10000;
switch(var1) {
case 0:
var10000 = this.CGLIB$CALLBACK_0;
break;
default:
var10000 = null;
}
return var10000;
}
public Callback[] getCallbacks() {
CGLIB$BIND_CALLBACKS(this);
return new Callback[]{this.CGLIB$CALLBACK_0};
}
public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] var0) {
CGLIB$STATIC_CALLBACKS = var0;
}
public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) {
CGLIB$THREAD_CALLBACKS.set(var0);
}
public void setCallback(int var1, Callback var2) {
switch(var1) {
case 0:
this.CGLIB$CALLBACK_0 = (MethodInterceptor)var2;
default:
}
}
public final void deliverGoods() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
var10000.intercept(this, CGLIB$deliverGoods$0$Method, CGLIB$emptyArgs, CGLIB$deliverGoods$0$Proxy);
} else {
super.deliverGoods();
}
}
public void setCallbacks(Callback[] var1) {
this.CGLIB$CALLBACK_0 = (MethodInterceptor)var1[0];
}
public static MethodProxy CGLIB$findMethodProxy(Signature var0) {
String var10000 = var0.toString();
switch(var10000.hashCode()) {
case -2002897756:
if (var10000.equals("deliverGoods()V")) {
return CGLIB$deliverGoods$0$Proxy;
}
break;
case -508378822:
if (var10000.equals("clone()Ljava/lang/Object;")) {
return CGLIB$clone$4$Proxy;
}
break;
case 1826985398:
if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
return CGLIB$equals$1$Proxy;
}
break;
case 1913648695:
if (var10000.equals("toString()Ljava/lang/String;")) {
return CGLIB$toString$2$Proxy;
}
break;
case 1984935277:
if (var10000.equals("hashCode()I")) {
return CGLIB$hashCode$3$Proxy;
}
}
return null;
}
final void CGLIB$deliverGoods$0() {
super.deliverGoods();
}
private static final void CGLIB$BIND_CALLBACKS(Object var0) {
SuperMarket$$EnhancerByCGLIB$$cef7fc40 var1 = (SuperMarket$$EnhancerByCGLIB$$cef7fc40)var0;
if (!var1.CGLIB$BOUND) {
var1.CGLIB$BOUND = true;
Object var10000 = CGLIB$THREAD_CALLBACKS.get();
if (var10000 == null) {
var10000 = CGLIB$STATIC_CALLBACKS;
if (var10000 == null) {
return;
}
}
var1.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])var10000)[0];
}
}
static void CGLIB$STATICHOOK1() {
CGLIB$THREAD_CALLBACKS = new ThreadLocal();
CGLIB$emptyArgs = new Object[0];
Class var0 = Class.forName("com.chenys.cglibproxy.SuperMarket$$EnhancerByCGLIB$$cef7fc40");
Class var1;
Method[] var10000 = ReflectUtils.findMethods(new String[]{"equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"}, (var1 = Class.forName("java.lang.Object")).getDeclaredMethods());
CGLIB$equals$1$Method = var10000[0];
CGLIB$equals$1$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$1");
CGLIB$toString$2$Method = var10000[1];
CGLIB$toString$2$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$2");
CGLIB$hashCode$3$Method = var10000[2];
CGLIB$hashCode$3$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$3");
CGLIB$clone$4$Method = var10000[3];
CGLIB$clone$4$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$4");
CGLIB$deliverGoods$0$Method = ReflectUtils.findMethods(new String[]{"deliverGoods", "()V"}, (var1 = Class.forName("com.chenys.cglibproxy.SuperMarket")).getDeclaredMethods())[0];
CGLIB$deliverGoods$0$Proxy = MethodProxy.create(var1, var0, "()V", "deliverGoods", "CGLIB$deliverGoods$0");
}
final Object CGLIB$clone$4() throws CloneNotSupportedException {
return super.clone();
}
final int CGLIB$hashCode$3() {
return super.hashCode();
}
final boolean CGLIB$equals$1(Object var1) {
return super.equals(var1);
}
final String CGLIB$toString$2() {
return super.toString();
}
}
也就是生成子类,然后通过子类继承原有类进行增强调用。
2-3、JDK动态代理和CGLib动态代理的不同
JDK动态代理只能对实现了接口的类生成代理,而不能针对类无接口的类,动态的生成代理对象,该代理对象继承Proxty,实现被代理对象的接口。
CGLib是针对类实现代理,对被代理类继承生成一个子类,覆盖其中的方法,使用ASM在内存中动态的生成被代理类的子类,即使代理类没有实现任何接口也可以实现动态代理功能。
三、反射
JDK动态代理生成的代理类里,就使用到了反射。反射就是把Java类映射成一个个的Java对象,在运行状态中,对于任意一个类,就能知道这个类的所有属性和方法;对于任意一个对象,都能调用它的任意一个方法和属性。这种动态获取信息及动态调用对象方法的功能叫Java的反射机制。
Java中主要由以下的类来实现Java反射机制(这些类都位于java.lang.reflect包中):
• Class类:代表一个类。 Field类:代表类的成员变量(成员变量也称为类的属性)。
• Method类:代表类的方法。
• Constructor类:代表类的构造方法。
• Array类:提供了动态创建数组,以及访问数组的元素的静态方法。
举个例子
package com.chenys.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class JavaReflect {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class cls = Class.forName(SuperMarket.class.getName());
// 获取定义的所有字段。getFields()为获取定义的public字段
Field[] declaredFields = cls.getDeclaredFields();
StringBuffer fieldBuffer = new StringBuffer();
for (Field field : declaredFields) {
fieldBuffer.append(field.getName()).append(", ");
}
System.out.println("SuperMarket的字段为:" + fieldBuffer.toString());
// 获取所有的method
Method[] declaredMethods = cls.getDeclaredMethods();
StringBuffer methodBuffer = new StringBuffer();
for (Method method : declaredMethods) {
methodBuffer.append(method.getName()).append(", ");
}
System.out.println("SuperMarket的方法为:" + methodBuffer.toString());
// 无参构造函数
Constructor constructor = cls.getConstructor();
SuperMarket superMarket = (SuperMarket) constructor.newInstance();
superMarket.setName("张三的超市");
System.out.println(superMarket.getName());
superMarket.deliverGoods();
System.out.println("-------------");
// 有参构造函数
Constructor constructor1 = cls.getConstructor(java.lang.Long.class,java.lang.String.class,java.lang.String.class);
SuperMarket superMarket1 = (SuperMarket) constructor1.newInstance(10L, "李四的超市","广东省");
System.out.println(superMarket1.getName());
superMarket1.deliverGoods();
System.out.println("------------");
//通过反射调用方法
//获得和属性对应的getXXX()方法
Method setNameMethod = cls.getMethod("setName",java.lang.String.class);
// 非共有方法,需要设置可访问权限
// setNameMethod.setAccessible(true);
setNameMethod.invoke(superMarket,"王五的超市");
Method getNameMethod = cls.getMethod("getName");
String name = (String) getNameMethod.invoke(superMarket,null);
System.out.println(name);
Method deliverGoodsMethod = cls.getMethod("deliverGoods",null);
deliverGoodsMethod.invoke(superMarket);
}
}
运行结果如下:
SuperMarket的字段为:id, name, location,
SuperMarket的方法为:getName, getLocation, getId, setName, setId, setLocation, deliverGoods,
张三的超市
SuperMarket.deliverGoods()
-------------
李四的超市
SuperMarket.deliverGoods()
------------
王五的超市
SuperMarket.deliverGoods()
四、使用
1、springMVC中,也是使用了代理方式,通过DispatcherServlet.class的doDispatch方法可知,在做完一系列工作后,包括Multipart检查,mappedHandler查找对应适配器,以及各种Resolver解析器后,就会进行调用invoke,去调用我们声明的@RequestMapping的方法。
protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
this.checkRequest(request);
ModelAndView mav;
if (this.synchronizeOnSession) {
HttpSession session = request.getSession(false);
if (session != null) {
Object mutex = WebUtils.getSessionMutex(session);
synchronized(mutex) {
mav = this.invokeHandlerMethod(request, response, handlerMethod);
}
} else {
mav = this.invokeHandlerMethod(request, response, handlerMethod);
}
} else {
mav = this.invokeHandlerMethod(request, response, handlerMethod);
}
if (!response.containsHeader("Cache-Control")) {
if (this.getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
this.applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
} else {
this.prepareResponse(response);
}
}
return mav;
}
2、mybatis mapper也是使用了动态代理,mapper中只声明了接口,没有实现类,调用 JDBC 等操作都是在 Mybatis InvocationHandler 实现的。
3、aop
4、日志
5、rpc