java代理机制

      关于java代理主要涉及到静态代理、动态代理,其中动态代理又有JDK动态代理及CGLIB代理。

代理实现

静态代理

      代理类StaticProxy与被代理类TestImpl实现相同的接口,在StaticProxy内部委托工作给TestImpl实例:

public interface TestInterface {

	void test();
	
}

public class TestImpl implements TestInterface {

	public void test() {
		System.out.println("TestImpl.test()");
	}
	
}

public class StaticProxy implements TestInterface {

	TestInterface target;
	
	public StaticProxy(Object target) {
		this.target =(TestInterface)target;
	}
	
	public void test() {
		System.out.println("StaticProxy test()");
		target.test();
	}
	
}

JDK动态代理

      利用java.lang.reflect.Proxy动态生成代理类,其extends Proxy且implements被代理接口TestInterface,其会将方法调用委派给InvocationHandler实例,这样就可以在invoke中的方法调用前后做文章:

public class JDKDynamicProxy implements InvocationHandler {

	Object target;

	public JDKDynamicProxy(Object target) {
		this.target = target;
	}

	public Object getProxy() {
		return Proxy.newProxyInstance(target.getClass().getClassLoader(),
				target.getClass().getInterfaces(), this);
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		// TODO Auto-generated method stub
		System.out.println("JDKDynamicProxy: do something before method invoke");
		Object result = method.invoke(target, args);
		System.out.println("JDKDynamicProxy: do something after method invoke");
		return result;
	}

}

CGLIB动态代理

      利用Enhancer设置被代理类为超类,设置MethodInterceptor实例做回调,动态生成代理类Class,同样可以在intercept上做文章:

public class CglibProxy implements MethodInterceptor {

	Object target;

	public CglibProxy(Object target) {
		this.target = target;
	}
	
	public Object getProxy() {
		Enhancer enhancer = new Enhancer(); 
		enhancer.setSuperclass(target.getClass());
		enhancer.setCallback(this);
		return enhancer.create();
	} 
	
	@Override
	public Object intercept(Object arg0, Method arg1, Object[] arg2,
			MethodProxy arg3) throws Throwable {
		// TODO Auto-generated method stub
		System.out.println("CglibProxy: do something before method invoke");
		Object result = arg3.invoke(target, arg2);
		System.out.println("CglibProxy: do something after method invoke");
		return result;
	}

}

JDK动态代理实现机制

      在JDKDynamicProxy的getProxy()中,利用Proxy.newProxyInstance来生成代理类实例:

public static Object newProxyInstance(ClassLoader loader,
									  Class[] interfaces,
									  InvocationHandler h)
	throws IllegalArgumentException
{
	if (h == null) {
		throw new NullPointerException();
	}

	// 获取代理类Class
	Class cl = getProxyClass(loader, interfaces);

	// 利用Constructor反射构造代理类实例
	try {
		Constructor cons = cl.getConstructor(constructorParams);
		return 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 Class getProxyClass(ClassLoader loader,
									 Class... interfaces)
	throws IllegalArgumentException
{
	if (interfaces.length > 65535) {
		throw new IllegalArgumentException("interface limit exceeded");
	}

	Class proxyClass = null;

	/* collect interface names to use as key for proxy class cache */
	String[] interfaceNames = new String[interfaces.length];

	// for detecting duplicates
	Set> interfaceSet = new HashSet<>();

	// 确保interfaces中的接口由loader加载
	for (int i = 0; i < interfaces.length; i++) {
		/*
		 * Verify that the class loader resolves the name of this
		 * interface to the same Class object.
		 */
		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");
		}

		/*
		 * Verify that the Class object actually represents an
		 * interface.
		 */
		if (!interfaceClass.isInterface()) {
			throw new IllegalArgumentException(
				interfaceClass.getName() + " is not an interface");
		}

		/*
		 * Verify that this interface is not a duplicate.
		 */
		if (interfaceSet.contains(interfaceClass)) {
			throw new IllegalArgumentException(
				"repeated interface: " + interfaceClass.getName());
		}
		interfaceSet.add(interfaceClass);

		interfaceNames[i] = interfaceName;
	}

	/*
	 * Using string representations of the proxy interfaces as
	 * keys in the proxy class cache (instead of their Class
	 * objects) is sufficient because we require the proxy
	 * interfaces to be resolvable by name through the supplied
	 * class loader, and it has the advantage that using a string
	 * representation of a class makes for an implicit weak
	 * reference to the class.
	 */
	List key = Arrays.asList(interfaceNames);

	// 在loader关联的代理类缓存中查看,如果有代理类则直接返回;否则动态生成代理类
	Map, Object> cache;
	synchronized (loaderToCache) {
		cache = loaderToCache.get(loader);
		if (cache == null) {
			cache = new HashMap<>();
			loaderToCache.put(loader, cache);
		}
		/*
		 * This mapping will remain valid for the duration of this
		 * method, without further synchronization, because the mapping
		 * will only be removed if the class loader becomes unreachable.
		 */
	}

	/*
	 * Look up the list of interfaces in the proxy class cache using
	 * the key.  This lookup will result in one of three possible
	 * kinds of values:
	 *     null, if there is currently no proxy class for the list of
	 *         interfaces in the class loader,
	 *     the pendingGenerationMarker object, if a proxy class for the
	 *         list of interfaces is currently being generated,
	 *     or a weak reference to a Class object, if a proxy class for
	 *         the list of interfaces has already been generated.
	 */
	synchronized (cache) {
		/*
		 * Note that we need not worry about reaping the cache for
		 * entries with cleared weak references because if a proxy class
		 * has been garbage collected, its class loader will have been
		 * garbage collected as well, so the entire cache will be reaped
		 * from the loaderToCache map.
		 */
		do {
			Object value = cache.get(key);
			if (value instanceof Reference) {
				proxyClass = (Class) ((Reference) value).get();
			}
			if (proxyClass != null) {
				// proxy class already generated: return it
				return proxyClass;
			} else if (value == pendingGenerationMarker) {
				// proxy class being generated: wait for it
				try {
					cache.wait();
				} catch (InterruptedException e) {
					/*
					 * The class generation that we are waiting for should
					 * take a small, bounded time, so we can safely ignore
					 * thread interrupts here.
					 */
				}
				continue;
			} else {
				/*
				 * No proxy class for this list of interfaces has been
				 * generated or is being generated, so we will go and
				 * generate it now.  Mark it as pending generation.
				 */
				cache.put(key, pendingGenerationMarker);
				break;
			}
		} while (true);
	}

	// 动态生成代理类
	try {
		String proxyPkg = null;     // package to define proxy class in

		// 确定代理类所在的package,即为interfaces中非public的接口,因为代理类要implements它
		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) {     // if no non-public proxy interfaces,
			proxyPkg = "";          // use the unnamed package
		}

		{
			// 代理类名称:包名+“$Proxy”+序号
			long num;
			synchronized (nextUniqueNumberLock) {
				num = nextUniqueNumber++;
			}
			String proxyName = proxyPkg + proxyClassNamePrefix + num;
			/*
			 * Verify that the class loader hasn't already
			 * defined a class with the chosen name.
			 */

			// 生成代理类字节码
			byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
				proxyName, interfaces);
			try {
				proxyClass = defineClass0(loader, proxyName,
					proxyClassFile, 0, proxyClassFile.length);
			} catch (ClassFormatError e) {
				/*
				 * A ClassFormatError here means that (barring bugs in the
				 * proxy class generation code) there was some other
				 * invalid aspect of the arguments supplied to the proxy
				 * class creation (such as virtual machine limitations
				 * exceeded).
				 */
				throw new IllegalArgumentException(e.toString());
			}
		}
		// add to set of all generated proxy classes, for isProxyClass
		proxyClasses.put(proxyClass, null);

	} finally {
		/*
		 * We must clean up the "pending generation" state of the proxy
		 * class cache entry somehow.  If a proxy class was successfully
		 * generated, store it in the cache (with a weak reference);
		 * otherwise, remove the reserved entry.  In all cases, notify
		 * all waiters on reserved entries in this cache.
		 */
		synchronized (cache) {
			if (proxyClass != null) {
				cache.put(key, new WeakReference>(proxyClass));
			} else {
				cache.remove(key);
			}
			cache.notifyAll();
		}
	}
	return proxyClass;
}

在该示例中,TestImpl的代理类大致如下:

public class $Proxy1 extends Proxy implements TestInterface {
	// m0、m1、m2分别为hashCode、equals、toString方法对应的Method实例
	java.land.reflect.Method m0;
	java.land.reflect.Method m1;
	java.land.reflect.Method m2;
	// m3为test方法对应的Method实例
	java.land.reflect.Method m3;

	public $Proxy1(InvocationHandler h) {
		super(h);
	}
	
	public int hashCode(){
		...
	}
	
	public boolean equals(Object obj) {
		...
    }
	
	public String toString() {
		...
	}
	
	public void test() {
		...
		h.invoke(this, m3, args);
		...
	}
}

总结

      使用代理一般是为了能在方法调用的前后进行拦截,做一些有用的工作。

      静态代理:

优点:实现代理类简单;

缺点:需要为每一个被代理类配一个代理类,另外,如果被代理类的接口有变动,代理类需要重新修改编译。

      JDK动态代理:

优点:只需要被代理类实例,多个被代理类情况下实现一个动态代理类即可,不受接口变动影响;无需额外的jar包;

缺点:不能代理类。

      Cglib动态代理:

优点:只需要被代理类实例,多个被代理类情况下实现一个动态代理类即可,不受接口变动影响;

缺点:不能代理接口;需要额外的cglib.jar、asm.jar。

你可能感兴趣的:(java常用)