我们以几个问题,来开始我们今天的学习,如果下面几个问题,你都能说出个一二,那么恭喜你,你已经掌握了这方面的知识。
1,什么是代理模式?
2,Java中,静态代理与动态代理的区别?
3,Spring使用的是JDK的动态代理,还是CGLIB的动态代理?
4,JDK的动态代理的实现原理?
5,JDK的动态代理与CGLIB的动态代理的实现上,有何不同?
6,你知道的,还有其他动态代理技术吗?请简述实现原理。

OK,言归正传。

Java的代理模式分为:静态代理和动态代理。首先我们需要搞清楚,什么是代理模式?注意,我们这里说的是JDK的代理模式。代理模式中,代
理类和委托类具有相同的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间
通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,
来提供特定的服务。
    说白了,JDK的代理模式,提供了另一种生成对象的方式。从程序结构上来说,JDK的代理模式,把代理类作为对象,代理代理类完成基本的功能,
并且增加了其他行为,我们可以在代理类执行之前(后),插入一段代码,完成其他的附加功能。我们可以把这种模式,看做是对生成对象的一种控制,
或者说是一种管理。Spring管理bean使用的就是动态代理。
    代理模式是23种设计模式之一,我们来回顾一下23种设计模式:
Factory(工厂模式)  
Builder(建造模式)  
Factory Method(工厂方法模式)  
Prototype(原始模型模式)  
Singleton(单例模式)  
Facade(门面模式)  
Adapter(适配器模式)  
Bridge(桥梁模式)  
Composite(合成模式)  
Decorator(装饰模式)  
Flyweight(享元模式)  
Proxy(代理模式)  
Command(命令模式)  
Interpreter(解释器模式)  
Visitor(访问者模式)  
Iterator(迭代子模式)  
Mediator(调停者模式)  
Memento(备忘录模式)  
Observer(观察者模式)  
State(状态模式)  
Strategy(策略模式)  
Template Method(模板方法模式)  
Chain Of Responsibleity(责任链模式)

按照代理的创建时期,代理类可以分为:静态代理和动态代理。静态代理指的是,由程序员创建或特定工具自动生成源代码,再对其进行编译。
在程序运行前,代理类的.class文件就已经存在了。动态代理指的是,在程序运行时,运用反射机制动态生成源代码,再对其进行编译。
    只看概念,比较抽象,我们下面来看一下代码示例。我们先来看一下静态代理的组成要素:
* 一个接口
* 一个接口实现类

* 一个代理类,也实现了接口,是增强版的实现类

/**
* @description 代理模式 之 静态代理 -- StaticProxyInterface接口
* @description 一个接口
*/
public interface StaticProxyInterface {
public void queryInfo();
}

  

/**
* @description 代理模式 之 静态代理 -- StaticProxyImpl实现类
* @description StaticProxyImpl,在代理模式中,叫做委托类,包含业务逻辑
* @description 一个接口实现类
*/
public class StaticProxyImpl implements StaticProxyInterface{
public void queryInfo() {
System.out.println("代理模式 之 静态代理 -- StaticProxyImpl实现类 查看信息...");
}
}

  

/**
* @description 代理模式 之 静态代理 -- StaticProxy代理类
* @description StaticProxy,在代理模式中,叫做代理类,增强StaticProxyImpl实现类
* @description 一个代理类,也实现了接口,是增强版的实现类
*/
public class StaticProxy implements StaticProxyInterface{ private StaticProxyImpl staticProxyImpl;
public StaticProxy(StaticProxyImpl staticProxyImpl){
this.staticProxyImpl = staticProxyImpl;
}
public void queryInfo() {
// 事务处理之前,可以执行一段代码
System.out.println("事务处理之前...");
// 调用委托类的方法
staticProxyImpl.queryInfo();
// 事务处理之后,可以执行一段代码
System.out.println("事务处理之后...");
}
}

  

/**
* @description 代理模式 之 静态代理
* @description 测试类StaticProxyTest
* @description 什么是静态代理:静态代理指的是,由程序员创建或特定工具自动生成源代码,再对其进行编译。
* 在程序运行前,代理类的.class文件就已经存在了。
* @description 静态代理组成要素:
* 1,一个接口
* 2,一个接口实现类
* 3,一个代理类,也实现接口,是增强版的接口实现类
*/
public class StaticProxyTest {
public static void main(String[] args){
StaticProxyImpl staticProxyImpl = new StaticProxyImpl();
StaticProxy staticProxy = new StaticProxy(staticProxyImpl);
staticProxy.queryInfo();
}
/*
* 静态代理的一个缺点就是:我们需要为每一个接口生成一个代理类,也就是一个接口必然要对应一个代理类。这样
* 必然会生成很多的代理类,并且这些代理类的代码有很多重复的部分。解决这一问题,最好的办法就是通过一个代理类
* 完成全部的代理功能,此时就要使用动态代理。
*/
}

  动态代理又可以分为2种:JDK的动态代理和CGLIB的动态代理,JDK的动态代理依赖具体的接口,需要绑定接口,如果一个类没有实现接口,
则不能使用JDK的动态代理。CGLIB的动态代理不依赖具体的接口,功能更加强大。下面我们分别进行说明,JDK的动态代理的关键是
InvocationHandler接口,先来看JDK的动态代理:

/**
* @description 代理模式 之 JDK的动态代理 -- DynamicProxyInterface接口
* @description 一个接口
*/
public interface DynamicProxyInterface {
public void queryInfo();
}

  

/**
* @description 代理模式 之 JDK的动态代理 -- DynamicProxyImpl实现类
* @description DynamicProxyImpl,在代理模式中,叫做委托类,包含业务逻辑
* @description 一个接口实现类
*/
public class DynamicProxyImpl implements DynamicProxyInterface { public void queryInfo() {
// TODO Auto-generated method stub
System.out.println("代理模式 之 JDK的动态代理 -- DynamicProxyImpl实现类 查看信息...");
}
}

  

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @description 代理模式 之 JDK的动态代理 -- DynamicProxy代理类
* @description DynamicProxy,在代理模式中,叫做代理类,增强DynamicProxyImpl实现类
* @description 一个代理类,实现了InvocationHandler接口
* @description JDK的动态代理 与 静态代理的区别就在这个代理类,静态代理类直接实现接口,而JDK的动态代理类不
* 直接实现具体的接口,而是实现了JDK提供的InvocationHandler接口。
*/
public class DynamicProxy implements InvocationHandler {
// 目标实现类,也就是某个接口的实现类,这里的target_interface_implements,可以看做是一种抽象
private Object target_interface_implements;
// 带参数构造方法,把目标实现类的对象作为参数传递进去,这里不是覆盖具体某个实现类的构造方法,而是抽象出来一个方法
public Object dynamicBindImplToProxyClass(Object target_interface_implements){
this.target_interface_implements = target_interface_implements;
// 取得代理对象
return Proxy.newProxyInstance(target_interface_implements.getClass().getClassLoader(),
target_interface_implements.getClass().getInterfaces(), this);
// JDK的动态代理依赖具体的接口,需要绑定接口,如果一个类没有实现接口,则不能使用JDK的动态代理
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub
Object result = null;
// 事务处理之前,可以执行一段代码
System.out.println("事务处理之前...");
// 执行方法
result = method.invoke(target_interface_implements, args);
// 事务处理之后,可以执行一段代码
System.out.println("事务处理之后...");
return result;
}
}

  

package com.ebank.action;
/**
* @description 代理模式 之 JDK的动态代理
* @description 测试类DynamicProxyTest
* @description 动态代理指的是,在程序运行时,运用反射机制动态生成源代码,再对其进行编译。
* @description JDK的动态代理组成要素:
* 1,一个接口
* 2,一个接口实现类
* 3,一个代理类,实现了InvocationHandler接口
*/
public class DynamicProxyTest {
public static void main(String[] args){
DynamicProxy dynamicProxy = new DynamicProxy();
DynamicProxyInterface dynamicProxyForImpl = (DynamicProxyInterface) dynamicProxy.dynamicBindImplToProxyClass(new DynamicProxyImpl());
dynamicProxyForImpl.queryInfo();
}
/*
* JDK的动态代理依靠具体的接口,如果有些类并没有实现,则不能使用JDK的动态代理,这时候就需要
* 使用CGLIB的动态代理
* // JDK的动态代理的关键是InvocationHandler接口
*/
}

  

接下来我们来分析一下JDK的动态代理的实现原理,JDK实现的动态代理,我们可以狭义的理解为,通过实现InvocationHandler接口,而实现的
动态代理。JDK的动态代理的实现需要依赖接口。拿上面的JDK的动态代理的示例代码来说,DynamicProxyImpl这个类,必须要实现某个接口,才
能借助InvocationHandler来实现动态代理,因为Proxy.newProxyInstance()这个方法中,需要传入代理类的接口作为参数。在示例中,我们的
DynamicProxyImpl类实现了DynamicProxyInterface接口。我们实现首先来看InvocationHandler接口的源代码:

package java.lang.reflect;
public interface InvocationHandler {
/**
* Processes a method invocation on a proxy instance and returns the result. This method will be invoked on an invocation
* handler when a method is invoked on a proxy instance that it is associated with.
* Processes : 处理,加工,审核
* @param proxy--the proxy instance that the method was invoked on
*
* @param method--the Method instance corresponding to the interface method invoked on the proxy instance. The declaring
* class of the Method object will be the interface that the method was declared in, which may be a
* superinterface of the proxy interface that the proxy class inherits the method through.
*
* @param args--an array of objects containing the values of the arguments passed in the method invocation on the proxy
* instance, or null if interface method takes no arguments.Arguments of primitive types are wrapped in instances of the
* appropriate primitive wrapper class, such as Integer or Boolean.
* primitive : 简单的,这里个人理解为基本的,primitive type 意为基本数据类型
* @return the value to return from the method invocation on the proxy instance. If the declared return type of the interface
* method is a primitive type, then the value returned by this method must be an instance of the corresponding primitive
* wrapper class; otherwise, it must be a type assignable to the declared return type. If the value returned by this method is
* null and the interface method's return type is primitive, then a NullPointerException will be
* thrown by the method invocation on the proxy instance. If the value returned by this method is otherwise not compatible with
* the interface method's declared return type as described above, a ClassCastException will be thrown by the method
* invocation on the proxy instance.
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}

  然后,我们来看CGLIB的动态代理,CGLIB的动态代理的关键是MethodInterceptor接口,这个接口位于:net.sf.cglib.proxy.MethodInterceptor

/**
* @description 代理模式 之 CGLIB的动态代理 -- CglibDynamicProxyImpl类
* @description CglibDynamicProxyImpl,在代理模式中,叫做委托类,包含业务逻辑
* @description 一个没有实现接口的类
*/
public class CglibDynamicProxyImpl {
public void queryInfo() {
// TODO Auto-generated method stub
System.out.println("代理模式 之 CGLIB的动态代理 -- CglibDynamicProxyImpl类 查看信息...");
}
}

  

import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/**
* @description 代理模式 之 CGLIB的动态代理 -- CglibDynamicProxy代理类
* @description CglibDynamicProxy,在代理模式中,叫做代理类,增强DynamicProxyImpl实现类
* @description 一个代理类,实现了MethodInterceptor接口
* @description CGLIB的动态代理 与 静态代理的区别就在这个代理类,静态代理类直接实现接口,而CGLIB的动态代理类不
* 直接实现具体的接口,而是实现了MethodInterceptor接口。
*/
public class CglibDynamicProxy implements MethodInterceptor {
// 目标实现类,也就是某个接口的实现类,这里的target_interface_implements,可以看做是一种抽象
private Object target_class;
// 创建代理对象
public Object getInstance(Object target_class){
this.target_class = target_class;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target_class.getClass());
// 回调方法
enhancer.setCallback(this);
// 创建代理对象
return enhancer.create();
}
// 回调方法
public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy proxy) throws Throwable {
// 事务处理之前,可以执行一段代码
System.out.println("事务处理之前...");
// 执行方法
proxy.invokeSuper(arg0, arg2);
// 事务处理之后,可以执行一段代码
System.out.println("事务处理之后...");
return null;
}
}

  

/**
* @description 代理模式 之 CGLIB的动态代理
* @description 测试类CglibDynamicProxyTest
* @description 动态代理指的是,在程序运行时,运用反射机制动态生成源代码,再对其进行编译。
* @description CGLIB的动态代理组成要素:
* 1,一个类
* 2,一个代理类,实现了MethodInterceptor接口
*/
public class CglibDynamicProxyTest { public static void main(String[] args){
CglibDynamicProxy cglibDynamicProxy = new CglibDynamicProxy();
CglibDynamicProxyImpl cglibDynamicProxyImpl = (CglibDynamicProxyImpl) cglibDynamicProxy.getInstance(new CglibDynamicProxyImpl());
cglibDynamicProxyImpl.queryInfo();
}
// CGLIB的动态代理的关键是MethodInterceptor接口
}

   CGLIB实现的动态代理,要求委托类不能被final关键字修饰,因为在运行期间,通过Java的反射机制,会生成委托类的子类。我们都知道,一个
类,一旦被final关键字修饰,那么这个类就不能被继承。假如我们使用final关键字修饰了委托类,编译期间不会报错,但是程序运行时,会报错:
不能继承final类,如下:

  1. Exception in thread "main" java.lang.IllegalArgumentException: Cannot subclass final class class com.yangcq.CglibDynamicProxyImpl
  2. at net.sf.cglib.proxy.Enhancer.generateClass(Enhancer.java:446)
  3. at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
  4. at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216)
  5. at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)
  6. at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:285)
  7. at com.ebank.action.CglibDynamicProxy.getInstance(CglibDynamicProxy.java:24)
  8. at com.ebank.action.CglibDynamicProxyTest.main(CglibDynamicProxyTest.java:14)

CGLIB的动态代理的实现原理是什么样的呢?CGLIB为我们提供了MethodInterceptor接口,我们不需要依赖某个接口,也就是说,即使代理类没有
实现任何接口,也是可以借助CGLIB来实现动态代理的。CGLIB是借助Java反射机制,在运行期间为代理类生成一个子类,通过子类,来完成父类的动
态代理。下面我们来看一下MethodInterceptor的源代码:

package net.sf.cglib.proxy;
import java.lang.reflect.Method;
public abstract interface MethodInterceptor extends Callback{
public abstract Object intercept(Object paramObject, Method paramMethod, Object[] paramArrayOfObject,
MethodProxy paramMethodProxy) throws Throwable;
}

  实现动态代理,我们需要关注一个关键的类:public class Proxy implements java.io.Serializable
Proxy的源代码:

package java.lang.reflect;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import sun.misc.ProxyGenerator;
public class Proxy implements java.io.Serializable { private static final long serialVersionUID = -2222568056686623797L;
private final static String proxyClassNamePrefix = "$Proxy";
private final static Class[] constructorParams = { InvocationHandler.class };
private static Map loaderToCache = new WeakHashMap();
private static Object pendingGenerationMarker = new Object();
private static long nextUniqueNumber = 0;
private static Object nextUniqueNumberLock = new Object();
private static Map proxyClasses = Collections.synchronizedMap(new WeakHashMap());
protected InvocationHandler h;
// 私有构造函数,不允许程序员通过构造函数来实例化Proxy,生成Proxy的实例,需要调用newProxyInstance方法
private Proxy() {
}
// 受保护的构造函数,这个函数也不允许程序员直接调用
protected Proxy(InvocationHandler h) {
this.h = h;
} public static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces) throws IllegalArgumentException{
// 这行代码,可以说明,在Class类文件的数据结构中,接口interfaces占用2个字节,最大值65535
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
}
Class proxyClass = null;
String[] interfaceNames = new String[interfaces.length];
// Set是无序,不可重复的集合
Set interfaceSet = new HashSet();
for (int i = 0; i < interfaces.length; i++) {
String interfaceName = interfaces[i].getName();
Class interfaceClass = null;
try {
// 通过接口名称和类加载器,获得接口实现类
interfaceClass = Class.forName(interfaceName, false, loader);
}
catch (ClassNotFoundException e) {
}
if (interfaceClass != interfaces[i]) {
throw new IllegalArgumentException(interfaces[i] + " is not visible from class loader");
}
if (!interfaceClass.isInterface()) {
throw new IllegalArgumentException(interfaceClass.getName() + " is not an interface");
}
if (interfaceSet.contains(interfaceClass)) {
throw new IllegalArgumentException("repeated interface: " + interfaceClass.getName());
}
interfaceSet.add(interfaceClass);
interfaceNames[i] = interfaceName;
}
Object key = Arrays.asList(interfaceNames);
Map cache;
synchronized (loaderToCache) {
cache = (Map) loaderToCache.get(loader);
if (cache == null) {
cache = new HashMap();
loaderToCache.put(loader, cache);
}
}
synchronized (cache) {
do {
Object value = cache.get(key);
if (value instanceof Reference) {
proxyClass = (Class) ((Reference) value).get();
}
if (proxyClass != null) {
return proxyClass;
}
else if (value == pendingGenerationMarker) {
try {
cache.wait();
}
catch (InterruptedException e) {
}
continue;
}
else {
cache.put(key, pendingGenerationMarker);
break;
}
} while (true);
}
try {
String proxyPkg = null;
for (int i = 0; i < interfaces.length; i++) {
int flags = interfaces[i].getModifiers();
if (!Modifier.isPublic(flags)) {
String name = interfaces[i].getName();
int n = name.lastIndexOf('.');
String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
if (proxyPkg == null) {
proxyPkg = pkg;
}
else if (!pkg.equals(proxyPkg)) {
throw new IllegalArgumentException("non-public interfaces from different packages");
}
}
}
if (proxyPkg == null) {
proxyPkg = "";
}
{
long num;
synchronized (nextUniqueNumberLock) {
num = nextUniqueNumber++;
}
String proxyName = proxyPkg + proxyClassNamePrefix + num;
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces);
try {
proxyClass = defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
}
catch (ClassFormatError e) {
throw new IllegalArgumentException(e.toString());
}
}
proxyClasses.put(proxyClass, null);
}
finally {
synchronized (cache) {
if (proxyClass != null) {
cache.put(key, new WeakReference(proxyClass));
}
else {
cache.remove(key);
}
cache.notifyAll();
}
}
return proxyClass;
} public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
throws IllegalArgumentException{
if (h == null) {
throw new NullPointerException();
}
// 获得代理类,需要传递2个参数,类加载器和接口
Class cl = getProxyClass(loader, interfaces);
try {
// 获得代理类的构造函数
Constructor cons = cl.getConstructor(constructorParams);
// 通过构造函数,生成实例对象
return (Object) cons.newInstance(new Object[] { h });
}
catch (NoSuchMethodException e) {
throw new InternalError(e.toString());
}
catch (IllegalAccessException e) {
throw new InternalError(e.toString());
}
catch (InstantiationException e) {
throw new InternalError(e.toString());
}
catch (InvocationTargetException e) {
throw new InternalError(e.toString());
}
} public static boolean isProxyClass(Class<?> cl) {
if (cl == null) {
throw new NullPointerException();
}
return proxyClasses.containsKey(cl);
} public static InvocationHandler getInvocationHandler(Object proxy) throws IllegalArgumentException{
if (!isProxyClass(proxy.getClass())) {
throw new IllegalArgumentException("not a proxy instance");
}
Proxy p = (Proxy) proxy;
return p.h;
}
private static native Class defineClass0(ClassLoader loader, String name, byte[] b, int off, int len);
}

  

  1. package java.lang.reflect;
  2. import java.lang.ref.Reference;
  3. import java.lang.ref.WeakReference;
  4. import java.util.Arrays;
  5. import java.util.Collections;
  6. import java.util.HashMap;
  7. import java.util.HashSet;
  8. import java.util.Map;
  9. import java.util.Set;
  10. import java.util.WeakHashMap;
  11. import sun.misc.ProxyGenerator;
  12. public class Proxy implements java.io.Serializable {
  13. private static final long serialVersionUID = -2222568056686623797L;
  14. private final static String proxyClassNamePrefix = "$Proxy";
  15. private final static Class[] constructorParams = { InvocationHandler.class };
  16. private static Map loaderToCache = new WeakHashMap();
  17. private static Object pendingGenerationMarker = new Object();
  18. private static long nextUniqueNumber = 0;
  19. private static Object nextUniqueNumberLock = new Object();
  20. private static Map proxyClasses = Collections.synchronizedMap(new WeakHashMap());
  21. protected InvocationHandler h;
  22. // 私有构造函数,不允许程序员通过构造函数来实例化Proxy,生成Proxy的实例,需要调用newProxyInstance方法
  23. private Proxy() {
  24. }
  25. // 受保护的构造函数,这个函数也不允许程序员直接调用
  26. protected Proxy(InvocationHandler h) {
  27. this.h = h;
  28. }
  29. public static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces) throws IllegalArgumentException{
  30. // 这行代码,可以说明,在Class类文件的数据结构中,接口interfaces占用2个字节,最大值65535
  31. if (interfaces.length > 65535) {
  32. throw new IllegalArgumentException("interface limit exceeded");
  33. }
  34. Class proxyClass = null;
  35. String[] interfaceNames = new String[interfaces.length];
  36. // Set是无序,不可重复的集合
  37. Set interfaceSet = new HashSet();
  38. for (int i = 0; i < interfaces.length; i++) {
  39. String interfaceName = interfaces[i].getName();
  40. Class interfaceClass = null;
  41. try {
  42. // 通过接口名称和类加载器,获得接口实现类
  43. interfaceClass = Class.forName(interfaceName, false, loader);
  44. }
  45. catch (ClassNotFoundException e) {
  46. }
  47. if (interfaceClass != interfaces[i]) {
  48. throw new IllegalArgumentException(interfaces[i] + " is not visible from class loader");
  49. }
  50. if (!interfaceClass.isInterface()) {
  51. throw new IllegalArgumentException(interfaceClass.getName() + " is not an interface");
  52. }
  53. if (interfaceSet.contains(interfaceClass)) {
  54. throw new IllegalArgumentException("repeated interface: " + interfaceClass.getName());
  55. }
  56. interfaceSet.add(interfaceClass);
  57. interfaceNames[i] = interfaceName;
  58. }
  59. Object key = Arrays.asList(interfaceNames);
  60. Map cache;
  61. synchronized (loaderToCache) {
  62. cache = (Map) loaderToCache.get(loader);
  63. if (cache == null) {
  64. cache = new HashMap();
  65. loaderToCache.put(loader, cache);
  66. }
  67. }
  68. synchronized (cache) {
  69. do {
  70. Object value = cache.get(key);
  71. if (value instanceof Reference) {
  72. proxyClass = (Class) ((Reference) value).get();
  73. }
  74. if (proxyClass != null) {
  75. return proxyClass;
  76. }
  77. else if (value == pendingGenerationMarker) {
  78. try {
  79. cache.wait();
  80. }
  81. catch (InterruptedException e) {
  82. }
  83. continue;
  84. }
  85. else {
  86. cache.put(key, pendingGenerationMarker);
  87. break;
  88. }
  89. } while (true);
  90. }
  91. try {
  92. String proxyPkg = null;
  93. for (int i = 0; i < interfaces.length; i++) {
  94. int flags = interfaces[i].getModifiers();
  95. if (!Modifier.isPublic(flags)) {
  96. String name = interfaces[i].getName();
  97. int n = name.lastIndexOf('.');
  98. String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
  99. if (proxyPkg == null) {
  100. proxyPkg = pkg;
  101. }
  102. else if (!pkg.equals(proxyPkg)) {
  103. throw new IllegalArgumentException("non-public interfaces from different packages");
  104. }
  105. }
  106. }
  107. if (proxyPkg == null) {
  108. proxyPkg = "";
  109. }
  110. {
  111. long num;
  112. synchronized (nextUniqueNumberLock) {
  113. num = nextUniqueNumber++;
  114. }
  115. String proxyName = proxyPkg + proxyClassNamePrefix + num;
  116. byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces);
  117. try {
  118. proxyClass = defineClass0(loader, proxyName,
  119. proxyClassFile, 0, proxyClassFile.length);
  120. }
  121. catch (ClassFormatError e) {
  122. throw new IllegalArgumentException(e.toString());
  123. }
  124. }
  125. proxyClasses.put(proxyClass, null);
  126. }
  127. finally {
  128. synchronized (cache) {
  129. if (proxyClass != null) {
  130. cache.put(key, new WeakReference(proxyClass));
  131. }
  132. else {
  133. cache.remove(key);
  134. }
  135. cache.notifyAll();
  136. }
  137. }
  138. return proxyClass;
  139. }
  140. public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
  141. throws IllegalArgumentException{
  142. if (h == null) {
  143. throw new NullPointerException();
  144. }
  145. // 获得代理类,需要传递2个参数,类加载器和接口
  146. Class cl = getProxyClass(loader, interfaces);
  147. try {
  148. // 获得代理类的构造函数
  149. Constructor cons = cl.getConstructor(constructorParams);
  150. // 通过构造函数,生成实例对象
  151. return (Object) cons.newInstance(new Object[] { h });
  152. }
  153. catch (NoSuchMethodException e) {
  154. throw new InternalError(e.toString());
  155. }
  156. catch (IllegalAccessException e) {
  157. throw new InternalError(e.toString());
  158. }
  159. catch (InstantiationException e) {
  160. throw new InternalError(e.toString());
  161. }
  162. catch (InvocationTargetException e) {
  163. throw new InternalError(e.toString());
  164. }
  165. }
  166. public static boolean isProxyClass(Class<?> cl) {
  167. if (cl == null) {
  168. throw new NullPointerException();
  169. }
  170. return proxyClasses.containsKey(cl);
  171. }
  172. public static InvocationHandler getInvocationHandler(Object proxy) throws IllegalArgumentException{
  173. if (!isProxyClass(proxy.getClass())) {
  174. throw new IllegalArgumentException("not a proxy instance");
  175. }
  176. Proxy p = (Proxy) proxy;
  177. return p.h;
  178. }
  179. private static native Class defineClass0(ClassLoader loader, String name, byte[] b, int off, int len);
  180. }

java之静态代理和动态代理的更多相关文章

  1. java静态代理与动态代理

    原文链接:http://www.orlion.ga/207/ 一.代理模式 代理模式是经常用到的设计模式,代理模式是给指定对象提供代理对象.由代理对象来控制具体对象的引用. 代理模式涉及到的角色: 抽 ...

  2. java的静态代理和动态代理(jdk、cglib)

    一.代理模式 代理的概念来自于设计模式中的代理模式,先了解一下代理模式 1.结构图 2.参与者 Subject:接口,定义代理类和实际类的共用接口 RealSubject:实际类,实现Subject这 ...

  3. 【Java】代处理?代理模式 - 静态代理,动态代理

    >不用代理 有时候,我希望在一些方法前后都打印一些日志,于是有了如下代码. 这是一个处理float类型加法的方法,我想在调用它前打印一下参数,调用后打印下计算结果.(至于为什么不直接用+号运算, ...

  4. Java:静态代理 and 动态代理

    代理模式是常用的设计模式,其特征是代理类与委托类具有相同的接口,在具体实现上,有静态代理和动态代理之分.代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并 ...

  5. Java基础-静态代理与动态代理比较

    JAVA的静态代理与动态代理比较 静态代理类: 由程序员创建或由特定工具自动生成源代码,再对其编译.在程序运行前,代理类的.class文件就已经存在了.动态代理类: 在程序运行时,运用反射机制动态创建 ...

  6. java中静态代理,动态代理知识的补充

    文章转载自:http://blog.csdn.net/jialinqiang/article/details/8950989 一.Java动态代理 相对于静态代理的代理类在编译时生成(.class文件 ...

  7. java静态代理与动态代理简单分析

    原创作品,可以转载,但是请标注出处地址http://www.cnblogs.com/V1haoge/p/5860749.html 1.动态代理(Dynamic Proxy) 代理分为静态代理和动态代理 ...

  8. 黑马程序员:Java基础总结----静态代理模式&动态代理

    黑马程序员:Java基础总结 静态代理模式&动态代理   ASP.Net+Android+IO开发 . .Net培训 .期待与您交流! 静态代理模式 public  class  Ts {   ...

  9. Java静态代理和动态代理

    今天介绍一下代理设计模式,在业务场景中使用代理模式的好处有很多,包括什么权限校验,事务管理等等,具体有什么好处大家自动百度吧,我这里只解释代理模式的设计原理.首先这个设计模式出来的时候先是静态代理模式 ...

  10. java中的静态代理和动态代理,入门整理

    静态代理和动态代理主要解决的问题是:在直接访问对象时带来的问题,其目的就是为其他对象提供一个代理以控制对某个对象的访问.代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后 ...

随机推荐

  1. 天气类App原型制作分享-ColorfulClouds

    ColorfulClouds是一款界面精美的天气预报App,它可以准确预报降雨量.污染程度等.这款App最美的是它的首页天气插画,扁平精美,同时配上了适当的动效,把普通的天气变得漂亮有趣,十分吸引眼球 ...

  2. (转)关于docker的15个小tip

    转自:https://www.cnblogs.com/elnino/p/3899136.html 1. 获取最近运行容器的id 这是我们经常会用到的一个操作,按照官方示例,你可以这样做(环境ubunt ...

  3. POJ 3662 Telephone Lines【Dijkstra最短路+二分求解】

    Telephone Lines Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7214   Accepted: 2638 D ...

  4. 1022: [SHOI2008]小约翰的游戏John【Nim博弈,新生必做的水题】

    1022: [SHOI2008]小约翰的游戏John Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 2709  Solved: 1726[Submit] ...

  5. [bzoj1369] [Baltic2003]Gem

    结论题...一棵树里用到的颜色数不超过logn.. f[i][j]表示以i为根的子树里,i的颜色是j的方案数. g[i][j]表示max{f[i][k]},(k!=j #include<cstd ...

  6. HTML5 Canvas 数据持久化存储之属性列表

    属性列表想必大家都不会陌生,正常用 HTML5 来做的属性列表大概就是用下拉菜单之类的,而且很多情况下,下拉列表还不够好看,怎么办?我试着用 HT for Web 来实现属性栏点击按钮弹出多功能选框, ...

  7. Ajax及异步操作

    之前我们使用的是jQuery的Ajax,这是一种极为便捷的Ajax操作方式,但是我们还需要对Ajax技术进行进一步的了解. <input type="text" id=&qu ...

  8. Flume介绍

    Flume介绍 http://flume.apache.org/FlumeUserGuide.html 一.Flume架构图 含义 Source 规定收集数据的来源 Channel 相当于一个管道,连 ...

  9. NSMutableArray 记住取不到时要进行强转

    NSMutableArray  记住取不到时要进行强转

  10. ASP.NET Core 一步步搭建个人网站(6)_单页模式和优化

    前言 HI,有段时间没有更新了,主要因为第一年前事情比较多,有些事得忙着张罗下:第二呢,对个人网站进行了一次大范围的优化,主要是申请的云服务器资源有限,1m的网络带宽,带上图片展示的话,打开网站的平均 ...