代理分为静态代理和动态代理:
字面理解代理得含义:代理类似经纪人,经纪人知道明星们所包含得技能,什么唱歌,跳舞,跑步之类得,代言活动方就直接找经纪人谈事情,但是具体得参与活动还是需要明星自己去处理.
一. 静态代理: 为每个需要代理得对象(目标对象)生成一个代理类.那么有多少明星,就需要多少经纪人了,就导致了经纪人太多了,
public interface Star{
int getAge();
String getName();
}
public class NBAStar implements Person {
public int getAge() {
return 1998;
}
public String getName() {
return "java development";
}
}
NBAStar 就相当于明星;经纪人在代理的时候 还可以格外进行包装;
public class StaticProxy implements Star{
private Star star ;
public StaticProxy(Star star){
this.tar = star;
}
public int getAge() {
//包装下?
return star.getAge();
}
public String getName() {
return star .getName();
}
}
StaticProxy 就相当于经纪人,代理明星,但是需要代理其他得明星,比如singleStar,那么就需要单独重新创建一个 SingleStarProxy,相对于比较重复;如果修改接口,那么静态代理类也需做出相应得改变;
测试:
public static void staticProxyDemo(){
StaticProxy staticProxy =new StaticProxy(new NBAStar());
int age = staticProxy.getAge();
String name = staticProxy.getName();
System.out.println("age:" + age + ",name:" + name);
}
为了减少工作量,就出现了动态代理:
二.动态代理
1,什么是动态代理?
动态代理是指程序运行时动态得生成代理对象,不必为每一个目标对象生成代理类,前提必须是接口;
2,动态代理作用是啥?
和静态代理的作用大致相同;
3,动态代理怎么实现?
使用jdk的Proxy类动态得生成代理对象:
Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces, InvocationHandler h);
测试代码:
public class ProxyHandler implements InvocationHandler{
private Object object;
public ProxyHandler(Object object){
this.object = object;
}
/**
* 目标类得 所有方法执行都是通过这里执行得
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(object,args);
return result;
}
}
调用:
private static void dynamicProxyDemo() {
Star star = (Star) Proxy.newProxyInstance(Star.class.getClassLoader(), new Class[]{Star.class}, new ProxyHandler(new NBAStar()));
int age = star.getAge();
System.out.println(age);
}
三,看下具体源码: 主要是三步,标红得地方
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
Objects.requireNonNull(h);
(1)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.
*/
(2)Class<?> cl = getProxyClass0(loader, intfs);//通过jdk,生成代理类,生成字节码
/*
* 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<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
return (3)cons.newInstance(new Object[]{h});//将invocatonHandler中包含得具体对象设置到生成得代理类中
} 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);
}
}
/** 由于动态代理生成的class文件放在jdk里面,我们看不见,下面得代码可以测试生成 代理code */
byte[] arrayOfByte = ProxyGenerator.generateProxyClass("$Proxy0", new Class[]{Person.class});
Class localClass1 = null;
String path = "E:\\sanguo\\NIOlearn\\bin\\StuProxy.class";
try{
FileOutputStream fos = new FileOutputStream(path);
fos.write(arrayOfByte);
fos.flush();
System.out.println("代理类class文件写入成功");
} catch (Exception e) {
System.out.println("写文件错误");
}