代理模式需要为每个类编写一个代理类,动态代理则会自动生成代理类简化操作。
实现动态代理有两种方式java自带api和cglib。
java自带api
基于接口生成代理类,实现动态代理
/**
* 功能接口
*/
public interface MyDao {
void create();
void query();
void update();
void delete();
}
/**
* 功能类
*/
public class MyDaoImp implements MyDao {
public void create() {
// 第八步:正真的create方法被调用
System.out.println("create something ... ");
}
public void query() {
System.out.println("query something ... ");
}
public void update() {
System.out.println("update something ... ");
}
public void delete() {
System.out.println("delete something ... ");
}
}
/**
* 委托类
*/
public class Agent implements InvocationHandler {
private Object proxied;
private int id;
public Agent(Object proxied, int id) {
this.proxied = proxied;
this.id = id;
}
// 通过代理类我们实现了权限过滤
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 第六步:目标方法调用前做一些业务操作,我们这里做了权限过滤
if (method.getName().equals("query")) {
return method.invoke(proxied, args);
}
if (id != 110) {
System.out.println("id=" + id + "没有" + method.getName() + "权限");
return null; // 空对象
}
// 第七步:利用反射调用了MyDaoImp中的create方法
return method.invoke(proxied, args);
}
}
/**
* 测试类
*/
public class Main {
public static void main(String[] args) {
// 第一步:新建对象,调用函数
Main main = new Main();
main.start();
// main.getClassFile(new Class[]{MyDao.class});
}
private void start() {
int id = 1101;
// 第二步:新建委托类,传入被代理的功能类,以及我们业务需要的id
Agent agent = new Agent(new MyDaoImp(), id);
// 第三步:取得代理对象,传入类加载器、实现的接口数组、代理类,这时会根据传入的参数生成一个代理类$Proxy0
MyDao myDao = (MyDao) Proxy.newProxyInstance(MyDaoImp.class.getClassLoader(), new Class[]{MyDao.class}, agent);
// 第四步:调用create方法,由于我们使用的是接口,所以我们正真拿到的对象并不是MyDaoImp,而是第三步生成的实现了MyDao的$Proxy0类(以create方法为例讲解调用步骤)
myDao.create();
myDao.query();
myDao.delete();
myDao.update();
}
// 该方法可以获取动态生成的代理类
private void getClassFile(Class[] classes) {
byte[] classFile = ProxyGenerator.generateProxyClass("com.sun.proxy.$Proxy0", classes);
FileOutputStream out = null;
try {
out = new FileOutputStream(("D:/$Proxy0.class"));
out.write(classFile);
out.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
/**
* 生成的代理类
* 可用测试类中的getClassFile方法取得class文件
*/
public final class $Proxy0 extends Proxy implements MyDao {
private static Method m1;
private static Method m6;
private static Method m2;
private static Method m4;
private static Method m5;
private static Method m0;
private static Method m3;
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {
try {
return ((Boolean)super.h.invoke(this, m1, new Object[]{var1})).booleanValue();
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final void query() throws {
try {
super.h.invoke(this, m6, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
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);
}
}
public final void delete() throws {
try {
super.h.invoke(this, m4, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void create() throws {
try {
// 第五步:调用Agent中的invoke方法
// super.h 在构造器中传入,即为Agent对象
// m5 在静态块中加载,反射取得MyDao中的create方法
super.h.invoke(this, m5, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final int hashCode() throws {
try {
return ((Integer)super.h.invoke(this, m0, (Object[])null)).intValue();
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void update() throws {
try {
super.h.invoke(this, m3, (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", new Class[]{Class.forName("java.lang.Object")});
m6 = Class.forName("core.proxy.jdk.MyDao").getMethod("query", new Class[0]);
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
m4 = Class.forName("core.proxy.jdk.MyDao").getMethod("delete", new Class[0]);
m5 = Class.forName("core.proxy.jdk.MyDao").getMethod("create", new Class[0]);
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
m3 = Class.forName("core.proxy.jdk.MyDao").getMethod("update", new Class[0]);
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
注:
该动态代理的原理,根据传入的委托类和接口,利用java的字节码技术自动生成一个新的代理类。
由于我们使用的是接口,所用我们真正使用的是生成的代理类。
该动态代理有一个接口
spring默认使用该动态代理技术
cglib
基于继承生成代理类,实现动态代理
/**
* 功能类
*/
public class MyDaoImp {
public void create() {
System.out.println("create something ... ");
}
public void query() {
System.out.println("query something ... ");
}
public void update() {
System.out.println("update something ... ");
}
public void delete() {
System.out.println("delete something ... ");
}
}
/**
* 委托类
*/
public class Agent implements MethodInterceptor {
private int id;
public Agent(int id) {
this.id = id;
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
// 第九步:处理业务员逻辑
if (method.getName().equals("query")) {
return methodProxy.invokeSuper(o, objects);
}
if (id != 110) {
System.out.println("id=" + id + "没有" + method.getName() + "权限");
return NoOp.INSTANCE; // 空对象
}
// 第十步:调用真正的业务类
return methodProxy.invokeSuper(o, objects);
}
}
/**
* 测试类
*/
public class Main {
public static void main(String[] args) {
// 第一步:新建对象,调用函数
Main main = new Main();
main.start();
}
public void start() {
int id = 111;
// 第二步:新建委托类
Agent agent = new Agent(id);
// 第三步:新建代理类处理对象
Enhancer enhancer = new Enhancer();
// 第四步:设置生成代理对象的父类
enhancer.setSuperclass(MyDaoImp.class);
// 第五步:设置委托类
enhancer.setCallback(agent);
// 第六步:取得生成的代理类,返回的类为MyDaoImp的子类
MyDaoImp myDaoImp = (MyDaoImp) enhancer.create();
// 第七步:调用create方法,实际调用了MyDaoImp子类的create方法,(以create方法为例继续接下去的流程)
myDaoImp.create();
myDaoImp.query();
myDaoImp.update();
myDaoImp.delete();
getClassFile(enhancer);
}
// 获取代理对象字节码文件
private void getClassFile(Enhancer enhancer){
FileOutputStream out = null;
try {
byte[] bytes = DefaultGeneratorStrategy.INSTANCE.generate(enhancer);
out = new FileOutputStream(("D:/Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72.class"));
out.write(bytes);
out.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
/**
* 生成的代理类
* 可用测试类中的getClassFile方法取得class文件
*/
public class aa28f65a extends core.proxy.cglib.MyDaoImp implements net.sf.cglib.proxy.Factory {
private boolean CGLIB$BOUND;
public static java.lang.Object CGLIB$FACTORY_DATA;
private static final java.lang.ThreadLocal CGLIB$THREAD_CALLBACKS;
private static final net.sf.cglib.proxy.Callback[] CGLIB$STATIC_CALLBACKS;
private net.sf.cglib.proxy.MethodInterceptor CGLIB$CALLBACK_0;
private static java.lang.Object CGLIB$CALLBACK_FILTER;
private static final java.lang.reflect.Method CGLIB$update$0$Method;
private static final net.sf.cglib.proxy.MethodProxy CGLIB$update$0$Proxy;
private static final java.lang.Object[] CGLIB$emptyArgs;
private static final java.lang.reflect.Method CGLIB$delete$1$Method;
private static final net.sf.cglib.proxy.MethodProxy CGLIB$delete$1$Proxy;
private static final java.lang.reflect.Method CGLIB$create$2$Method;
private static final net.sf.cglib.proxy.MethodProxy CGLIB$create$2$Proxy;
private static final java.lang.reflect.Method CGLIB$query$3$Method;
private static final net.sf.cglib.proxy.MethodProxy CGLIB$query$3$Proxy;
private static final java.lang.reflect.Method CGLIB$equals$4$Method;
private static final net.sf.cglib.proxy.MethodProxy CGLIB$equals$4$Proxy;
private static final java.lang.reflect.Method CGLIB$toString$5$Method;
private static final net.sf.cglib.proxy.MethodProxy CGLIB$toString$5$Proxy;
private static final java.lang.reflect.Method CGLIB$hashCode$6$Method;
private static final net.sf.cglib.proxy.MethodProxy CGLIB$hashCode$6$Proxy;
private static final java.lang.reflect.Method CGLIB$clone$7$Method;
private static final net.sf.cglib.proxy.MethodProxy CGLIB$clone$7$Proxy;
static void CGLIB$STATICHOOK2() { /* compiled code */ }
final void CGLIB$update$0() { /* compiled code */ }
public final void update() { /* compiled code */ }
final void CGLIB$delete$1() { /* compiled code */ }
public final void delete() { /* compiled code */ }
final void CGLIB$create$2() { /* compiled code */ }
// 生成的代理类无法完全反编译
// 第八步:调用Agent的intercept方法
// 预测无法反编译的内容为 intercept(this, CGLIB$create$2$Method, null, CGLIB$create$2$Proxy)
public final void create() { /* compiled code */ }
final void CGLIB$query$3() { /* compiled code */ }
public final void query() { /* compiled code */ }
final boolean CGLIB$equals$4(java.lang.Object o) { /* compiled code */ }
public final boolean equals(java.lang.Object o) { /* compiled code */ }
final java.lang.String CGLIB$toString$5() { /* compiled code */ }
public final java.lang.String toString() { /* compiled code */ }
final int CGLIB$hashCode$6() { /* compiled code */ }
public final int hashCode() { /* compiled code */ }
final java.lang.Object CGLIB$clone$7() throws java.lang.CloneNotSupportedException { /* compiled code */ }
protected final java.lang.Object clone() throws java.lang.CloneNotSupportedException { /* compiled code */ }
public static net.sf.cglib.proxy.MethodProxy CGLIB$findMethodProxy(net.sf.cglib.core.Signature signature) { /* compiled code */ }
public aa28f65a() { /* compiled code */ }
public static void CGLIB$SET_THREAD_CALLBACKS(net.sf.cglib.proxy.Callback[] callbacks) { /* compiled code */ }
public static void CGLIB$SET_STATIC_CALLBACKS(net.sf.cglib.proxy.Callback[] callbacks) { /* compiled code */ }
private static final void CGLIB$BIND_CALLBACKS(java.lang.Object o) { /* compiled code */ }
public java.lang.Object newInstance(net.sf.cglib.proxy.Callback[] callbacks) { /* compiled code */ }
public java.lang.Object newInstance(net.sf.cglib.proxy.Callback callback) { /* compiled code */ }
public java.lang.Object newInstance(java.lang.Class[] classes, java.lang.Object[] objects, net.sf.cglib.proxy.Callback[] callbacks) { /* compiled code */ }
public net.sf.cglib.proxy.Callback getCallback(int i) { /* compiled code */ }
public void setCallback(int i, net.sf.cglib.proxy.Callback callback) { /* compiled code */ }
public net.sf.cglib.proxy.Callback[] getCallbacks() { /* compiled code */ }
public void setCallbacks(net.sf.cglib.proxy.Callback[] callbacks) { /* compiled code */ }
}
注:
该动态代理的原理,根据传入的委托类和业务类,利用java的字节码技术自动生成一个新的代理类。
生成的代理类为被代理的子类。
spring可选择使用该动态代理技术
参考文章
已忘记。。。