手机
当前位置:查字典教程网 >编程开发 >Java >深入解析java中的静态代理与动态代理
深入解析java中的静态代理与动态代理
摘要:java编码中经常用到代理,代理分为静态代理和动态代理。其中动态代理可以实现spring中的aop。一、静态代理:程序运行之前,程序员就要编...

java编码中经常用到代理,代理分为静态代理和动态代理。其中动态代理可以实现spring中的aop。

一、静态代理:程序运行之前,程序员就要编写proxy,然后进行编译,即在程序运行之前,代理类的字节码文件就已经生成了

被代理类的公共父类

复制代码 代码如下:

package staticproxy;

public abstract class BaseClass {

public abstract void add();

}

被代理类

复制代码 代码如下:

package staticproxy;

public class A extends BaseClass {

public void add() {

System.out.println("A add !");

}

}

代理类

复制代码 代码如下:

package staticproxy;

public class Proxy {

BaseClass baseClass;

public void add() {

baseClass.add();

}

public void setBaseClass(BaseClass baseClass) {

this.baseClass = baseClass;

}

public static void main(String[] args) {

BaseClass baseClass = new A();

Proxy proxy = new Proxy();

proxy.setBaseClass(baseClass);

proxy.add();

}

}

二、动态代理:实际的代码在编译期间并没有生成,而是在运行期间运用反射机制动态的生成

被代理类接口

复制代码 代码如下:

package jdkproxy;

public interface Service {

public void add();

public void update();

}

被代理类A

复制代码 代码如下:

package jdkproxy;

public class AService implements Service {

public void add() {

System.out.println("AService add>>>>>>>>>>>>>>>>>>");

}

public void update() {

System.out.println("AService update>>>>>>>>>>>>>>>");

}

}

被代理类B

复制代码 代码如下:

package jdkproxy;

public class BService implements Service {

public void add() {

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

}

public void update() {

System.out.println("BService update---------------");

}

}

代理类

复制代码 代码如下:

package jdkproxy;

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;

public class MyInvocationHandler implements InvocationHandler {

private Object target;

MyInvocationHandler() {

super();

}

MyInvocationHandler(Object target) {

super();

this.target = target;

}

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

throws Throwable {

// 程序执行前加入逻辑

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

// 程序执行

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

//程序执行后加入逻辑

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

return result;

}

public Object getTarget() {

return target;

}

public void setTarget(Object target) {

this.target = target;

}

}

测试类

复制代码 代码如下:

package jdkproxy;

import java.lang.reflect.Proxy;

public class Test {

public static void main(String[] args) {

Service aService = new AService();

MyInvocationHandler handler = new MyInvocationHandler(aService);

// Proxy为InvocationHandler实现类动态创建一个符合某一接口的代理实例

Service aServiceProxy = (Service) Proxy.newProxyInstance(aService

.getClass().getClassLoader(), aService.getClass()

.getInterfaces(), handler);

//由动态生成的代理对象来aServiceProxy 代理执行程序,其中aServiceProxy 符合Service接口

aServiceProxy.add();

System.out.println();

aServiceProxy.update();

// 以下是对B的代理

// Service bService = new BService();

// MyInvocationHandler handler = new MyInvocationHandler(bService);

// Service bServiceProxy = (Service) Proxy.newProxyInstance(bService

// .getClass().getClassLoader(), bService.getClass()

// .getInterfaces(), handler);

// bServiceProxy.add();

// System.out.println();

// bServiceProxy.update();

}

}

输出结果:

before-----------------------------

AService add>>>>>>>>>>>>>>>>>>

after------------------------------

before-----------------------------

AService update>>>>>>>>>>>>>>>

after------------------------------

其中上述标红的语句是产生代理类的关键代码,可以产生一个符合Service接口的代理对象,newProxyInstance这个方法会做这样一件事情,他将把你要代理的全部接口,用一个由代码动态生成的类来实现,该类中所有的接口中的方法都重写为调用InvocationHandler.invoke()方法。

下面详细介绍是如何实现代理对象的生成的

Proxy的newProxyInstance方法,其中,为了看起来方便,已经将该方法中的异常处理语句删减

下下面public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h) throws

复制代码 代码如下:

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h) throws IllegalArgumentException

{

if (h == null) {

throw new NullPointerException();

}

//生成指定的代理类

Class cl = getProxyClass(loader, interfaces);

Constructor cons = cl.getConstructor(constructorParams);

// 生成代理类的实例,并把MyInvocationHandler的实例传给它的构造方法,代理类对象实际执行都会调用MyInvocationHandler的invoke方法,所以代理类对象中维持一个MyInvocationHandler引用

return (Object) cons.newInstance(new Object[] { h });

} 其中getProxyClass方法返回代理类的实例

Proxy的getProxyClass方法

复制代码 代码如下:

public static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces) throws IllegalArgumentException

{

//前面省略很多缓存、异常处理、判断逻辑代码,为了使程序更加突出

byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces);

proxyClass = defineClass0(loader, proxyName,proxyClassFile, 0, proxyClassFile.length);

proxyClasses.put(proxyClass, null);

return proxyClass;

}

下面看ProxyGenerator的generateProxyClass方法,该方法最终产生代理类的字节码文件:

复制代码 代码如下:

public static byte[] generateProxyClass(final String name, Class[] interfaces)

{

ProxyGenerator gen = new ProxyGenerator(name, interfaces);

// 这里动态生成代理类的字节码

final byte[] classFile = gen.generateClassFile();

// 如果saveGeneratedFiles的值为true,则会把所生成的代理类的字节码保存到硬盘上

if (saveGeneratedFiles) {

java.security.AccessController.doPrivileged(

new java.security.PrivilegedAction<Void>() {

public Void run() {

try {

FileOutputStream file =

new FileOutputStream(dotToSlash(name) + ".class");

file.write(classFile);

file.close();

return null;

} catch (IOException e) {

throw new InternalError(

"I/O exception saving generated file: " + e);

}

}

});

}

// 返回代理类的字节码

return classFile;

}

那么最终生成的代理类到底是什么样子呢,如下(省略了一下equals,hashcode,toString等方法,只展示构造函数和add方法):

复制代码 代码如下:

public final class $Proxy11 extends Proxy implements Service

{ // 构造方法,参数就是刚才传过来的MyInvocationHandler类的实例

public $Proxy11(InvocationHandler invocationhandler)

{

super(invocationhandler);

}

/**

* 继承的add方法,重写,调用MyInvocationHandler中的invoke方法

*/

public final void add()

{

try

{

// 实际上就是调用MyInvocationHandler中的invoke方法

super.h.invoke(this, m3, null);

return;

}

catch(Error _ex) { }

catch(Throwable throwable)

{

throw new UndeclaredThrowableException(throwable);

}

}

}

【深入解析java中的静态代理与动态代理】相关文章:

浅谈java中的访问修饰符

java动态代理(jdk与cglib)详细解析

代理角色java设计模式之静态代理详细介绍

java中的正则操作方法总结

深入解析java虚拟机

java 静态代理 动态代理深入学习

深入java内存查看与分析详解

深入理解Java编程中异常处理的优劣

深入Java线程中断的本质与编程原则的概述

浅析java程序中hibernate的应用总结

精品推荐
分类导航