动态代理的使用
JDK动态代理只能给实现接口的类生成代理对象,主要用来通过JDK动态代理能够在不修改对象方法的前提下,修改方法内容.
1. 接口 UserService.java
package cn.bing.jdkproxy;
public interface UserService {
public void sayHello();
}
2. 实现类,需要生成代理对象的类 UserServiceImpl.java
package cn.bing.jdkproxy;
public class UserServiceImpl implements UserService {
public UserServiceImpl(){super();}
@Override
public void sayHello() {
System.out.println("hello world!");
}
}
3. 生成代理类,改变对象行为
需求:
在调用sayHello前,输出 --- before ----
调用sayHello后------after ------
核心是调用方法 java.lang.reflect.Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
生成代理对象。
参数说明:
loader 类加载器 ,使用当前类的类加载器就行
interfaces: 需要生成代理对象的类的接口的类对象,可以通过Class.getInterfaces获取
h: InvocationHandler接口的实现类对象,实现这个类,重写invoke方法,增加一些方法,在调用原方法前后
package cn.bing.jdkproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class MyInvocationHandler implements InvocationHandler{
private Object object;
public MyInvocationHandler(){}
public MyInvocationHandler(Object obj){
this.object = obj;
}
/**
* 执行目标对象的方法
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("-------before--------");
Object invoke = method.invoke(this.object, args);
System.out.println("-------after----------");
return invoke;
}
/**
* 生成目标对象的代理对象
* @return
*/
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(), this.object.getClass().getInterfaces(), this);
}
}
4. 执行,生成代理对象
package cn.bing.jdkproxy.junit;
import org.junit.Test;
import cn.bing.jdkproxy.MyInvocationHandler;
import cn.bing.jdkproxy.UserService;
import cn.bing.jdkproxy.UserServiceImpl;
public class ProxyJunit {
@Test
public void test(){
UserService userService = new UserServiceImpl();
MyInvocationHandler handler = new MyInvocationHandler(userService);
UserService proxy = (UserService)handler.getProxy();
proxy.sayHello();
}
}
输出:
-------before--------
hello world!
-------after----------
hello world!
JDK动态代理源码解析
首先看下核心方法:Proxy.newProxyInstance
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
if (h == null) {
throw new NullPointerException();
}
final Class<?>[] intfs = interfaces.clone();
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
//获取生成的代理的Class对象
Class<?> cl = getProxyClass0(loader, intfs);
try {
//利用反射生成构造器
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) {
// create proxy instance with doPrivilege as the proxy class may
// implement non-public interfaces that requires a special permission
return AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
//构造器对象生成代理对象
return newInstance(cons, ih);
}
});
} else {
//构造器对象生成代理对象
return newInstance(cons, ih);
}
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString());
}
}
调用getProxyClass0方法生成代理对象的类对象
private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
private static Class<?> getProxyClass0(ClassLoader loader,
Class<?>... interfaces) {
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
}
//WeakCache的get方法获取
return proxyClassCache.get(loader, interfaces);
}
//WeakCache类的构造方法
public WeakCache(BiFunction<K, P, ?> subKeyFactory,
BiFunction<K, P, V> valueFactory) {
this.subKeyFactory = Objects.requireNonNull(subKeyFactory);
this.valueFactory = Objects.requireNonNull(valueFactory);
}
调用WeakCache的get方法
public V get(K key, P parameter) {
Objects.requireNonNull(parameter);
expungeStaleEntries();
Object cacheKey = CacheKey.valueOf(key, refQueue);
ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
if (valuesMap == null) {
ConcurrentMap<Object, Supplier<V>> oldValuesMap
= map.putIfAbsent(cacheKey,
valuesMap = new ConcurrentHashMap<>());
if (oldValuesMap != null) {
valuesMap = oldValuesMap;
}
}
//创建subkey
Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
//第一次,valuesMap是新创建的,这里获取supplier是空的
Supplier<V> supplier = valuesMap.get(subKey);
Factory factory = null;
//从这里开始看
while (true) {
第三步: 最终调用factory的get方法获取代理对象
if (supplier != null) {
// supplier might be a Factory or a CacheValue<V> instance
V value = supplier.get();
if (value != null) {
return value;
}
}
//第一步:supperlier为空,首先创建factory对象
if (factory == null) {
factory = new Factory(key, parameter, subKey, valuesMap);
}
if (supplier == null) {
supplier = valuesMap.putIfAbsent(subKey, factory);
if (supplier == null) {
// 第二步:这里将supplier赋值为factory
supplier = factory;
}
// else retry with winning supplier
} else {
if (valuesMap.replace(subKey, supplier, factory)) {
// successfully replaced
// cleared CacheEntry / unsuccessful Factory
// with our Factory
supplier = factory;
} else {
// retry with current supplier
supplier = valuesMap.get(subKey);
}
}
}
}
调用Factory对象的get方法
@Override
public synchronized V get() { // serialize access
// re-check
Supplier<V> supplier = valuesMap.get(subKey);
//检查supplier的值是否和当前的值一致,可能因为多线程环境下,发生改变
//再次检查
if (supplier != this) {
return null;
}
V value = null;
try {
//这是核心方法,获取代理对象
value = Objects.requireNonNull(valueFactory.apply(key, parameter));
} finally {
if (value == null) { // remove us on failure
valuesMap.remove(subKey, this);
}
}
// the only path to reach here is with non-null value
assert value != null;
// wrap value with CacheValue (WeakReference)
CacheValue<V> cacheValue = new CacheValue<>(value);
// try replacing us with CacheValue (this should always succeed)
if (valuesMap.replace(subKey, this, cacheValue)) {
// put also in reverseMap
reverseMap.put(cacheValue, Boolean.TRUE);
} else {
throw new AssertionError("Should not reach here");
}
// successfully replaced us with new CacheValue -> return the value
// wrapped by it
return value;
}
}
最终是调用ProxyClassFactory的apply方法获取代理对象:
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
for (Class<?> intf : interfaces) {
//创建Class对象放到一个interfaceSet 里面
...........
}
//代理类的全类型名
String proxyPkg = null;
/*
* 如果接口不是public接口,定义的代理类将存放在同一个包里面
*/
for (Class<?> intf : interfaces) {
int flags = intf.getModifiers();
if (!Modifier.isPublic(flags)) {
String name = intf.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) {
// 如果是公共的接口,代理类的包名称为 com.sun.proxy package
proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
}
/*
* 生成代理类的名称
*/
long num = nextUniqueNumber.getAndIncrement();
String proxyName = proxyPkg + proxyClassNamePrefix + num;
/*
* 生成代理类的二进制数组
*/
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces);
try {//根据代理类的字节码,生成代理类对象
return defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
} catch (ClassFormatError e) {
throw new IllegalArgumentException(e.toString());
}
}
}
进去ProxyGenerator.generateProxyClass方法看下,生成二进制数组的过程
public static byte[] generateProxyClass(String paramString, Class[] paramArrayOfClass)
{
ProxyGenerator localProxyGenerator = new ProxyGenerator(paramString, paramArrayOfClass);
//生成文件的二进制码
final byte[] arrayOfByte = localProxyGenerator.generateClassFile();
//如果是true,将文件写到硬盘上
if (saveGeneratedFiles) {
AccessController.doPrivileged(new PrivilegedAction()
{
public Void run() {
try {
FileOutputStream localFileOutputStream = new FileOutputStream(ProxyGenerator.dotToSlash(this.val$name) + ".class");
localFileOutputStream.write(arrayOfByte);
localFileOutputStream.close();
return null;
} catch (IOException localIOException) {
throw new InternalError("I/O exception saving generated file: " + localIOException);
}
}
});
}
return arrayOfByte;
}
最后,测试下,将代理文件写到本地磁盘
@Test
public void writeToHard(){
byte[] bt = ProxyGenerator.generateProxyClass("$Proxy1", UserServiceImpl.class.getInterfaces());
try{
FileOutputStream out = new FileOutputStream(new File("c:/$Proxy1.class"));
out.write(bt);
out.flush();
out.close();
}catch(Exception e){
e.printStackTrace();
}
}
看下,反编译后的代理类的代码
import cn.bing.jdkproxy.UserService;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class $Proxy1 extends Proxy
implements UserService
{
private static Method m3;
private static Method m1;
private static Method m0;
private static Method m2;
public $Proxy1(InvocationHandler paramInvocationHandler)
throws
{
super(paramInvocationHandler);
}
public final void sayHello()
throws
{
try
{
this.h.invoke(this, m3, null);
return;
}
catch (RuntimeException localRuntimeException)
{
throw localRuntimeException;
}
catch (Throwable localThrowable)
{
}
throw new UndeclaredThrowableException(localThrowable);
}
public final boolean equals(Object paramObject)
throws
{
try
{
return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
}
catch (RuntimeException localRuntimeException)
{
throw localRuntimeException;
}
catch (Throwable localThrowable)
{
}
throw new UndeclaredThrowableException(localThrowable);
}
public final int hashCode()
throws
{
try
{
return ((Integer)this.h.invoke(this, m0, null)).intValue();
}
catch (RuntimeException localRuntimeException)
{
throw localRuntimeException;
}
catch (Throwable localThrowable)
{
}
throw new UndeclaredThrowableException(localThrowable);
}
public final String toString()
throws
{
try
{
return (String)this.h.invoke(this, m2, null);
}
catch (RuntimeException localRuntimeException)
{
throw localRuntimeException;
}
catch (Throwable localThrowable)
{
}
throw new UndeclaredThrowableException(localThrowable);
}
static
{
try
{
m3 = Class.forName("cn.bing.jdkproxy.UserService").getMethod("sayHello", new Class[0]);
m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
return;
}
catch (NoSuchMethodException localNoSuchMethodException)
{
throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
}
catch (ClassNotFoundException localClassNotFoundException)
{
}
throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
}
}
关注点:
1. 创建的代理对象是继承了Proxy,java里面只能是单继承,也就意味着如果一个类只是extends其他类(没有实现接口),就不能生成代理对象。
2. 从sayHello方法里面,我们看到实际上的调用invocationhandler的invoke方法,这里才回去调用invoke方法。
参考文章:http://rejoy.iteye.com/blog/1627405