代理模式精講(手寫JDK動態代理),源碼展示

代理模式精講(手寫JDK動態代理),源碼展示

Java/Jdk

代理模式是一種架構型模式,表現出來就是一個類代表另一個類的功能,一般用在想對訪問一個類的時候做一些控制,同時又不想影響正常的業務,這種代理模式在現實的生活中應用的也非常的廣泛,我用窮舉法給舉幾個好理解的例子:

1.像我們在大城市裡的中介找房子的網站,房東、租戶、中間商的三角關係,就是典型的代理模式。

2.還有就是幫助人找媳婦的媒婆,也是代理模式。

3.還有黃牛黨等等還有很多。

正向代理和反向代理的區別:

1.正向代理代理的是用戶,用戶->代理服務器->谷歌的原網站模式,通過代理服務器訪問谷歌。

2.反向代理代理的是服務器,比如我們訪問百度的時候,其實感覺像訪問一臺電腦,其實在後面有成千上萬臺的服務器,比如通過代理服務器代理後臺的服務器進行分發請求。

下面咱們通過代碼進行一步一步的進行演進:

靜態代理

父親給兒子找對象,從代碼不靈活進行演變。

package pattern.proxy;
/**
* 父親給兒子找對象,父親有兒子的引用
* 才可以給兒子找對象
*/
public class Father {
private Son person;
public Father(Son person){
this.person=person;
}
public void findLove(){
System.out.println("根據你的要求物色");
this.person.findLove();
System.out.println("雙色父母是不是同意");
}
}
package pattern.proxy;
public class Son {
public void findLove(){
System.out.println("找對象,腿長的,漂亮的");
}
}
package pattern.proxy;
public class ProxyTest {
public static void main(String[] args) {
//父親給兒子找對象
Father father=new Father(new Son());
father.findLove();
}
}

下面使用接口進行改造:

package pattern.proxy;
public interface Person {
public void findLove();
public void findHouse();
}
package pattern.proxy;
/**
* 父親給兒子找對象,父親有兒子的引用
* 才可以給兒子找對象
*/
public class Father implements Person {
private Person person;
public Father(Person person){
this.person=person;
}
public void findLove(){
System.out.println("根據你的要求物色");
person.findLove();
System.out.println("雙色父母是不是同意");
}
@Override
public void findHouse() {
person.findHouse();
}
}
package pattern.proxy;
public class Son implements Person {
public void findLove(){
System.out.println("找對象,腿長的,漂亮的");
}
@Override
public void findHouse() {
System.out.println("找房子了");
}
}
package pattern.proxy; 

public class ProxyTest {
public static void main(String[] args) {
//父親給兒子找對象
Person father=new Father(new Son());
father.findLove();
}
}

其實如果接口裡面代理的方法太多,是比較麻煩的,下面使用動態代理進行改造。

JDK動態代理

package pattern.proxy.jdk;
public interface Person {
public void findLove();
}
package pattern.proxy.jdk;
public class XieMu implements Person {
public void findLove(){
System.out.println("xiemu要找對象了,要求比較高,漂亮,美");
}
}
package pattern.proxy.jdk;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JdkMeiPo implements InvocationHandler {
//被代理的對象
private Person target;
public Object getInstance(XieMu target){
this.target=target;
Class> clazz=target.getClass();
//生成一個新的對象,通過字節碼重組
return Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

System.out.println("我是媒婆,我要給你找對象,現在已經拿到你的需求");
System.out.println("開始物色");
method.invoke(target,args);
System.out.println("如果合適,那就辦事了");
return null;
}
}
package pattern.proxy.jdk;
public class JdkMeiPoTest {
public static void main(String[] args) {
Person person=(Person) new JdkMeiPo().getInstance(new XieMu());
person.findLove();
}
}

這裡面的JdkMeiPo持有被代理人的對象,同時實現InvocationHandler接口,還有一個Proxy.newProxyInstance()的方法用來生成一個新的對象,通過字節碼重組。

cglib動態代理

cglib是面向方法就可以進行代理,但是是通過字節碼重組動態生成的接口。

package pattern.proxy.cglib;
public class ZhangSan {
public void findLove(){
System.out.println("漂亮的美美");
}
}
package pattern.proxy.cglib;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;

public class CglibMeiPo implements MethodInterceptor{
public Object getInstance(Class> clazz) throws Exception{
Enhancer enhancer=new Enhancer();
//要把哪個設置為即將生成的新類父類
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
//業務的增強
System.out.println("我是媒婆,我要給你找對象,現在已經拿到你的需求");
System.out.println("開始物色");
methodProxy.invokeSuper(o,objects);
System.out.println("如果合適,那就辦事了");
return null;
}
}
package pattern.proxy.cglib;
public class CglibTest {
public static void main(String[] args) throws Exception {
ZhangSan obj=(ZhangSan) new CglibMeiPo().getInstance(ZhangSan.class);
obj.findLove();
}
}

手寫JDK動態代理

把動態代理生成的代理類保存到文件裡:

package pattern.proxy.jdk;
import sun.misc.ProxyGenerator;
import java.io.FileOutputStream;
public class JdkMeiPoTest {
public static void main(String[] args) throws Exception {//原理:
//1、拿到被代理對象的引用,並且獲取到它的所有的接口,反射獲取

//2、JDK Proxy類重新生成一個新的類、同時新的類要實現被代理類所有實現的所有的接口
//3、動態生成Java代碼,把新加的業務邏輯方法由一定的邏輯代碼去調用(在代碼中體現)
//4、編譯新生成的Java代碼.class
//5、再重新加載到JVM中運行
//以上這個過程就叫字節碼重組
//JDK中有個規範,只要要是$開頭的一般都是自動生成的
byte[] bytes=ProxyGenerator.generateProxyClass("$Proxy0",new Class[]{Person.class});
FileOutputStream fos=new FileOutputStream("D://$proxy0.class");
fos.write(bytes);
fos.flush();
fos.close();
}
}

生成的$Proxy0文件:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import pattern.proxy.jdk.Person;
public final class $Proxy0 extends Proxy implements Person {
private static Method m1;
//m3調用的是findLove(),從下面的靜態快可以看出來
private static Method m3;
private static Method m2;
private static Method m0;
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
//Object對象的
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);
}
}
//代理類實現了Person類,重寫了findLove的方法
public final void findLove() throws {
try {
//$Proxy0繼承了Proxy類,就可以用Proxy裡的InvocationHandler裡的h,這個其實就是JdkMeiPo實現的接口InvocationHander.
//調用JdkMeiPo的invoke方法,傳入當先的對象和invoke中執行的findLove方法,參數為空
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
//Object對象的
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);
}
}

//Object對象的
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"));
m3 = Class.forName("pattern.proxy.jdk.Person").getMethod("findLove");
m2 = Class.forName("java.lang.Object").getMethod("toString");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");

} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
package java.lang.reflect;
import java.lang.ref.WeakReference;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Arrays;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.BiFunction;
import sun.misc.ProxyGenerator;
import sun.misc.VM;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
import sun.reflect.misc.ReflectUtil;
import sun.security.util.SecurityConstants;
public class Proxy implements java.io.Serializable {
private static final long serialVersionUID = -2222568056686623797L;
/** parameter types of a proxy class constructor */
private static final Class>[] constructorParams =
{ InvocationHandler.class };
/**
* a cache of proxy classes
*/
private static final WeakCache[], Class>>
proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
/**
* the invocation handler for this proxy instance.
* @serial
*/
protected InvocationHandler h;
/**
* Prohibits instantiation.
*/
private Proxy() {
}
protected Proxy(InvocationHandler h) {
Objects.requireNonNull(h);
this.h = h;
}

@CallerSensitive
public static Class> getProxyClass(ClassLoader loader,
Class>... interfaces)
throws IllegalArgumentException
{
final Class>[] intfs = interfaces.clone();
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
return getProxyClass0(loader, intfs);
}
private static void checkProxyAccess(Class> caller,
ClassLoader loader,
Class>... interfaces)
{
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
ClassLoader ccl = caller.getClassLoader();
if (VM.isSystemDomainLoader(loader) && !VM.isSystemDomainLoader(ccl)) {
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
}
ReflectUtil.checkProxyPackageAccess(ccl, interfaces);
}
}
/**
* Generate a proxy class. Must call the checkProxyAccess method
* to perform permission checks before calling this.
*/
private static Class> getProxyClass0(ClassLoader loader,
Class>... interfaces) {
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
}
// If the proxy class defined by the given loader implementing
// the given interfaces exists, this will simply return the cached copy;
// otherwise, it will create the proxy class via the ProxyClassFactory
return proxyClassCache.get(loader, interfaces);
}
/*
* a key used for proxy class with 0 implemented interfaces
*/
private static final Object key0 = new Object();
/*
* Key1 and Key2 are optimized for the common use of dynamic proxies
* that implement 1 or 2 interfaces.
*/
/*
* a key used for proxy class with 1 implemented interface
*/

private static final class Key1 extends WeakReference> {
private final int hash;
Key1(Class> intf) {
super(intf);
this.hash = intf.hashCode();
}
@Override
public int hashCode() {
return hash;
}
@Override
public boolean equals(Object obj) {
Class> intf;
return this == obj ||
obj != null &&
obj.getClass() == Key1.class &&
(intf = get()) != null &&
intf == ((Key1) obj).get();
}
}
/*
* a key used for proxy class with 2 implemented interfaces
*/
private static final class Key2 extends WeakReference> {
private final int hash;
private final WeakReference> ref2;
Key2(Class> intf1, Class> intf2) {
super(intf1);
hash = 31 * intf1.hashCode() + intf2.hashCode();
ref2 = new WeakReference>(intf2);
}
@Override
public int hashCode() {
return hash;
}
@Override
public boolean equals(Object obj) {
Class> intf1, intf2;
return this == obj ||
obj != null &&
obj.getClass() == Key2.class &&
(intf1 = get()) != null &&
intf1 == ((Key2) obj).get() &&
(intf2 = ref2.get()) != null &&
intf2 == ((Key2) obj).ref2.get();
}

}
/*
* a key used for proxy class with any number of implemented interfaces
* (used here for 3 or more only)
*/
private static final class KeyX {
private final int hash;
private final WeakReference>[] refs;
@SuppressWarnings("unchecked")
KeyX(Class>[] interfaces) {
hash = Arrays.hashCode(interfaces);
refs = (WeakReference>[])new WeakReference>[interfaces.length];
for (int i = 0; i < interfaces.length; i++) {
refs[i] = new WeakReference<>(interfaces[i]);
}
}
@Override
public int hashCode() {
return hash;
}
@Override
public boolean equals(Object obj) {
return this == obj ||
obj != null &&
obj.getClass() == KeyX.class &&
equals(refs, ((KeyX) obj).refs);
}
private static boolean equals(WeakReference>[] refs1,
WeakReference>[] refs2) {
if (refs1.length != refs2.length) {
return false;
}
for (int i = 0; i < refs1.length; i++) {
Class> intf = refs1[i].get();
if (intf == null || intf != refs2[i].get()) {
return false;
}
}
return true;
}
}
/**
* A function that maps an array of interfaces to an optimal key where
* Class objects representing interfaces are weakly referenced.
*/
private static final class KeyFactory

implements BiFunction[], Object>
{
@Override
public Object apply(ClassLoader classLoader, Class>[] interfaces) {
switch (interfaces.length) {
case 1: return new Key1(interfaces[0]); // the most frequent
case 2: return new Key2(interfaces[0], interfaces[1]);
case 0: return key0;
default: return new KeyX(interfaces);
}
}
}
/**
* A factory function that generates, defines and returns the proxy class given
* the ClassLoader and array of interfaces.
*/
private static final class ProxyClassFactory
implements BiFunction[], Class>>
{
private static final String proxyClassNamePrefix = "$Proxy";
private static final AtomicLong nextUniqueNumber = new AtomicLong();
@Override
public Class> apply(ClassLoader loader, Class>[] interfaces) {
Map, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
for (Class> intf : interfaces) {
Class> interfaceClass = null;
try {
interfaceClass = Class.forName(intf.getName(), false, loader);
} catch (ClassNotFoundException e) {
}
if (interfaceClass != intf) {
throw new IllegalArgumentException(
intf + " 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.put(interfaceClass, Boolean.TRUE) != null) {
throw new IllegalArgumentException(

"repeated interface: " + interfaceClass.getName());
}
}
String proxyPkg = null; // package to define proxy class in
int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
/*
* Record the package of a non-public proxy interface so that the
* proxy class will be defined in the same package. Verify that
* all non-public proxy interfaces are in the same package.
*/
for (Class> intf : interfaces) {
int flags = intf.getModifiers();
if (!Modifier.isPublic(flags)) {
accessFlags = Modifier.FINAL;
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) {
// if no non-public proxy interfaces, use com.sun.proxy package
proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
}
long num = nextUniqueNumber.getAndIncrement();
String proxyName = proxyPkg + proxyClassNamePrefix + num;
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);
try {
return defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
} catch (ClassFormatError e) {

throw new IllegalArgumentException(e.toString());
}
}
}

//loalder類加載器
//實現的接口數組
//h所有動態代理類的方法調用,都會交由InvocationHandler接口實現類裡的invoke()方法去處理。這是動態代理的關鍵所在

@CallerSensitive
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() {
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);
}
}
private static void checkNewProxyPermission(Class> caller, Class> proxyClass) {
SecurityManager sm = System.getSecurityManager();

if (sm != null) {
if (ReflectUtil.isNonPublicProxyClass(proxyClass)) {
ClassLoader ccl = caller.getClassLoader();
ClassLoader pcl = proxyClass.getClassLoader();
// do permission check if the caller is in a different runtime package
// of the proxy class
int n = proxyClass.getName().lastIndexOf('.');
String pkg = (n == -1) ? "" : proxyClass.getName().substring(0, n);
n = caller.getName().lastIndexOf('.');
String callerPkg = (n == -1) ? "" : caller.getName().substring(0, n);
if (pcl != ccl || !pkg.equals(callerPkg)) {
sm.checkPermission(new ReflectPermission("newProxyInPackage." + pkg));
}
}
}
}
public static boolean isProxyClass(Class> cl) {
return Proxy.class.isAssignableFrom(cl) && proxyClassCache.containsValue(cl);
}
@CallerSensitive
public static InvocationHandler getInvocationHandler(Object proxy)
throws IllegalArgumentException
{
if (!isProxyClass(proxy.getClass())) {
throw new IllegalArgumentException("not a proxy instance");
}
final Proxy p = (Proxy) proxy;
final InvocationHandler ih = p.h;
if (System.getSecurityManager() != null) {
Class> ihClass = ih.getClass();
Class> caller = Reflection.getCallerClass();
if (ReflectUtil.needsPackageAccessCheck(caller.getClassLoader(),
ihClass.getClassLoader()))
{
ReflectUtil.checkPackageAccess(ihClass);
}
}
return ih;
}
private static native Class> defineClass0(ClassLoader loader, String name,
byte[] b, int off, int len);
}

下面實現一個自己的動態代理:

package pattern.proxy.custom;
public interface Person {
public void findLove();
}
package pattern.proxy.custom;
public class XieMu implements Person {
public void findLove(){
System.out.println("xiemu要找對象了,要求比較高,漂亮,美");
}
}
package pattern.proxy.custom;
import java.lang.reflect.Method;
public class CustomMeiPo implements JavaInvocationHandler {
private Person target;
public Object getInstance(Person target){
this.target=target;
Class> clazz=target.getClass();
return JavaProxy.newProxyInstance(new JavaClassLoader(),clazz.getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("我是媒婆,我要給你找對象,現在已經拿到你的需求");
System.out.println("開始物色");
method.invoke(target,args);
System.out.println("如果合適,那就辦事了");
return null;
}
}

根據kdk裡面的主要java類創建自定義的類:

package pattern.proxy.custom;
import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Iterator;
public class JavaProxy {
public static final String Ln="\r\n";
public static Object newProxyInstance(JavaClassLoader classLoader,
Class>[] interfaces,
JavaInvocationHandler h){
try {
//1.動態生成源代碼.java文件
String class="lazy" src="//p2.ttnews.xyz/loading.gif" data-original=generateSrc(interfaces);
//2.java文件輸出到磁盤
String filePath=JavaProxy.class.getResource("").getPath();
System.out.println(filePath);
File file=new File(filePath+"$Proxy0.java");
FileWriter fw=new FileWriter(file);

fw.write(src);
fw.flush();
fw.close();
//3.把生成的.java文件編譯成.class文件
JavaCompiler compiler= ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager manage=compiler.getStandardFileManager(null,null,null);
Iterable iterable=manage.getJavaFileObjects(file);
JavaCompiler.CompilationTask task=compiler.getTask(null,null,null,null,null,null);
task.call();
manage.close();
//4.編譯生成的.class文件加載到JVM中來
Class proxyClass=classLoader.findClass("$Proxy0");
Constructor c=proxyClass.getConstructor(JavaInvocationHandler.class);
file.delete();
//5.返回字節碼重組後新的對象
return c.newInstance(h);
}catch (Exception e){
e.printStackTrace();
}
return null;
}
public static String generateSrc(Class>[] interfaces){
StringBuffer sb=new StringBuffer();
sb.append("package pattern.proxy.custom;" + Ln);
sb.append("import java.lang.reflect.Method;"+ Ln);
sb.append("public class $Proxy0 implements " + interfaces[0].getName() + "{" + Ln);
sb.append("public JavaInvocationHandler h;" + Ln);
sb.append("public $Proxy0(JavaInvocationHandler h) { "+Ln);
sb.append("this.h=h;"+Ln);
sb.append("}"+Ln);
for (Method m:interfaces[0].getMethods()){
sb.append("public "+ m.getReturnType().getName() + " " +m.getName() + "(){"+ Ln);
sb.append("try{"+Ln);
sb.append("Method m="+interfaces[0].getName()+".class.getMethod("" + m.getName() + "",new Class[]{});" + Ln);
sb.append("this.h.invoke(this,m,null);"+Ln);
sb.append("}catch(Throwable e){" + Ln);
sb.append("e.printStackTrace();" + Ln);
sb.append("}" + Ln);
sb.append("}" + Ln);
}
sb.append("}" + Ln);
return sb.toString();
}
}
package pattern.proxy.custom; 

import java.lang.reflect.Method;
public interface JavaInvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
package pattern.proxy.custom;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class JavaClassLoader extends ClassLoader {
private File classPathFile;
public JavaClassLoader(){
String classPath=JavaClassLoader.class.getResource("").getPath();
this.classPathFile=new File(classPath);
}
@Override
protected Class> findClass(String name) throws ClassNotFoundException {
String className=JavaClassLoader.class.getPackage().getName()+"."+name;
if(classPathFile!=null){
File classFile=new File(classPathFile,name.replaceAll("\\.","/")+".class");
if(classFile.exists()){
FileInputStream in=null;
ByteArrayOutputStream out=null;
try {
in=new FileInputStream(classFile);
out=new ByteArrayOutputStream();
byte[] buff=new byte[1024];
int len;
while ((len=in.read(buff))!=-1){
out.write(buff,0,len);
}
return defineClass(className,out.toByteArray(),0,out.size());
}catch (Exception e){
e.printStackTrace();
}finally {
if(in!=null){
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(out!=null){
try {
out.close();
} catch (IOException e) {
e.printStackTrace();

}
}
}
}
}
return null;
}
}

測試類:

package pattern.proxy.custom;
public class CustomProxyTest {
public static void main(String[] args) {
Person person=(Person) new CustomMeiPo().getInstance(new XieMu());
person.findLove();
}
}

效果:

我是媒婆,我要給你找對象,現在已經拿到你的需求
開始物色
xiemu要找對象了,要求比較高,漂亮,美
如果合適,那就辦事了

喜歡和喜歡學習的一起交流技術!

加Java架構師進階交流群獲取Java工程化、高性能及分佈式、高性能、深入淺出。高架構。性能調優、Spring,MyBatis,Netty源碼分析和大數據等多個知識點高級進階乾貨的直播免費學習權限 都是大牛帶飛 讓你少走很多的彎路的 群號是:338549832 對了 小白勿進 最好是有開發經驗

注:加群要求

1、具有工作經驗的,面對目前流行的技術不知從何下手,需要突破技術瓶頸的可以加。

2、在公司待久了,過得很安逸,但跳槽時面試碰壁。需要在短時間內進修、跳槽拿高薪的可以加。

3、如果沒有工作經驗,但基礎非常紮實,對java工作機制,常用設計思想,常用java開發框架掌握熟練的,可以加。

4、覺得自己很牛B,一般需求都能搞定。但是所學的知識點沒有系統化,很難在技術領域繼續突破的可以加。

5.阿里Java高級大牛直播講解知識點,分享知識,多年工作經驗的梳理和總結,帶著大家全面、科學地建立自己的技術體系和技術認知!


分享到:


相關文章: