Java代理模式

java

静态代理

代理类自己编写,在编译器已经确认了代理类。

实现步骤

1.定义接口及其实现类

public interface SayHelloService {

void say();

}

public class SayHelloServiceImpl implements SayHelloService {

@Override

public void say() {

System.out.println("Hello Bitch");

}

}


2.定义类代理对象

public class SayHelloServiceProxy implements SayHelloService {

private SayHelloService target;

public SayHelloServiceProxy(SayHelloService service) {

this.target = service;

}

@Override

public void say() {

System.out.println("记录日志。。。。。。");

target.say();

System.out.println("清理数据。。。。。。");

}

public static void main(String[] args) {

SayHelloServiceProxy proxy = new SayHelloServiceProxy(new SayHelloServiceImpl());

proxy.say();

}

}

代理类实现了目标对象的接口,对原有得接口做了扩展,其中所有的对象都是在编译期都确定好了。

缺点

需要代理对象实现目标对象的接口,假如目标对象方法很多或者需要代理多个对象,复杂度就会很高。

而动态代理不需要在编译期确定代理类,可以在运行时期动态生成,反射是动态代理的一种实现方式。

java中的动态代理

主要由以下两种方式实现:

JDK动态代理

JDK动态代理需要目标对象实现一个或多个接口,否则只能使用CGLIB实现动态代理。

实现步骤

1.定义目标类和公共接口

public interface UserService {

void add();

}

public class UserServiceImpl implements UserService {

@Override

public void add() {

// TOD Auto-generated method stub

System.out.println("-------add--------");

}

}


2.定义调用处理器类,可以再运行时生成代理类,并带上一些增强的功能

java.lang.reflect.Proxy : 这是生成代理类的主类,通过 Proxy 类生成的代理类都继承了 Proxy 类,即 DynamicProxyClas extends Proxy。

java.lang.reflect.InvocationHandler:调用处理类

public class MyInvocationHandler implements InvocationHandler {

private Object target;

public MyInvocationHandler(Object target) {

super();

this.target = target;

}

@Override

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

System.out.println("------begin " + method.getName() + "------");

Object result = method.invoke(target, args);

System.out.println("------end " + method.getName() + "-------");

return result;

}

public Object getProxy() {

return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), target.getClass().getInterfaces(), this);

}

public static void main(String[] args) {

UserService service = new UserServiceImpl();

MyInvocationHandler handler = new MyInvocationHandler(service);

UserService proxy = (UserService) handler.getProxy();

proxy.add();

}

}

原理解析

上面关键点在于Proxy.newProxyInstance() 方法创建了一个代理对象,查看他的源码,封装了创建代理类及对象的方法,如下:

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);

}

/*

* Look up or generate the designated proxy class.

*/

Class<?> cl = getProxyClass0(loader, intfs);

/*

* Invoke its constructor with the designated 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);

}

}

其中的getProxyClass0(loader, intfs)实际生成了代理类,这个代理类是动态代理的关键,因为是在运行时动态生成的,我们可以通过下面的方法将生成的文件显示出来,探探究竟

public static void main(String[] args) throws IOException {

byte[] testProxies = ProxyGenerator.generateProxyClass("Proxy0", UserServiceImpl.class.getInterfaces());

String path = "E:/userProxies.class";

FileOutputStream fileOutputStream = new FileOutputStream(path);

fileOutputStream.write(testProxies);

fileOutputStream.flush();

fileOutputStream.close();

}

反编译生成的文件如下

public final class Proxy0 extends Proxy implements UserService {

private static Method m1;

private static Method m2;

private static Method m3;

private static Method m0;

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});

} catch (RuntimeException | Error var3) {

throw var3;

} catch (Throwable var4) {

throw new UndeclaredThrowableException(var4);

}

}

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 add() throws {

try {

super.h.invoke(this, m3, (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);

} 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"));

m2 = Class.forName("java.lang.Object").getMethod("toString");

m3 = Class.forName("org.example.proxy.inter.UserService").getMethod("add");

m0 = Class.forName("java.lang.Object").getMethod("hashCode");

} catch (NoSuchMethodException var2) {

throw new NoSuchMethodError(var2.getMessage());

} catch (ClassNotFoundException var3) {

throw new NoClassDefFoundError(var3.getMessage());

}

}

}

分析:jdk动态生成了一个代理类,继承于Proxy,当我们调用add()方法时,将此方法当做参数传了进去,super.h.invoke(this, m3, (Object[])null)。 最终调用了InvocationHandler的invoke方法。

InvocationHandler的invoke:

public Object invoke(Object obj, Object... args)

throws IllegalAccessException, IllegalArgumentException,

InvocationTargetException

{

if (!override) {

if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {

Class<?> caller = Reflection.getCallerClass();

checkAccess(caller, clazz, obj, modifiers);

}

}

MethodAccessor ma = methodAccessor; // read volatile

if (ma == null) {

ma = acquireMethodAccessor();

}

return ma.invoke(obj, args);

}


通过反射,得到被代理对象的方法实现。

一整套下来,达到了代理的功能。

Cglib动态代理

Cglib 是一个强大的高性能的代码生成包,它可以在运行期扩展 Java 类与实现 Java接口。

public class CglibProxy implements MethodInterceptor {

private Enhancer enhancer = new Enhancer();

public Object getProxy(Class clazz) {

//设置需要创建子类的类

enhancer.setSuperclass(clazz);

enhancer.setCallback(this);

//通过字节码技术动态创建子类实例

return enhancer.create();

}

//实现 MethodInterceptor接口方法

@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;

}

public static void main(String[] args) {

CglibProxy proxy = new CglibProxy();

//通过生成子类的方式创建代理类

UserServiceImpl proxyImp = (UserServiceImpl) proxy.getProxy(UserServiceImpl.class);

proxyImp.add();

}

}

二者区别

使用动态代理的对象必须实现一个或多个接口

使用 cglib 代理的对象则无需实现接口,达到代理类无侵入。

SpringAOP

主要由JDK动态代理和CGLIB动态代理实现

JDK 动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口。JDK 动态代理的核心是 InvocationHandler 接口和 Proxy 类。如果目标类没有实现接口,那么 Spring AOP 会选择使用 CGLIB 来动态代理目标类。

CGLIB(Code Genration Libray),是一个代码生成的类库,可以在运行时动态的生成某个类的子类,CGLIB 是通过继承的方式做的动态代理,因此如果某个类被标记为 final,那么它是无法使用 CGLIB 做动态代理的。

以上是 Java代理模式 的全部内容, 来源链接: utcz.com/z/391702.html

回到顶部