java动态代理用在很多地方。spring框架,RPC框架中都使用了动态代理,动态代理很重要。
首先看看静态代理:
相对静态代理而已,静态代理需要对每一个方法做一次处理。如下:
定义一个实体列,交个代理类,然后由代理帮忙做事
public static void main(String[] args) {
People people = new Students();
ProxyManager proxyManager = new ProxyManager(people);
proxyManager.findJob();
}
接口
public interface People {
public void findJob();
}
实体类:
public class Students implements People{
@Override
public void findJob() {
System.out.println("I am student ,I am looking for a job");
}
}
代理类:
public class ProxyManager implements People {
People people ;
public ProxyManager(People people){
this.people = people;
}
@Override
public void findJob() {
System.out.println("I am Manager, I am help other find job");
people.findJob();
System.out.println("");
}
}
,如果实体类有多个方法,那么静态的代理类就需要复写多个方法,哪怕是做同样的事情,所以就出现动态代理。
添加一个动态代理类:
public class ProxyD {
Class target;
Object object;
public ProxyD(Class target,Object object){
this.target=target;
this.object=object;
}
public Object getPeopele() throws Throwable{
return Proxy.newProxyInstance(target.getClassLoader(),
new Class[]{target}, new ObjectHandle(this.object));
}
class ObjectHandle implements InvocationHandler{
Object target;
public ObjectHandle(Object object) {
this.target = object;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("I am Manager, I am help other find job");
Object o = method.invoke(target, args);
System.out.println("");
return o;
}
}
}
然后在看测试类:
People people = new Students();
ProxyD proxyD=new ProxyD(People.class,people);
People proxyManager =(People) proxyD.getPeopele();
proxyManager.findJob();
从这里看动态类和静态的没有什么区别,但是如果接口添加一个方法,那么静态代理类将必须重写这个方法,但是动态代理就不需要,可以直接调用,
People people = new Students();
ProxyD proxyD=new ProxyD(People.class,people);
People proxyManager =(People) proxyD.getPeopele();
proxyManager.findJob();
proxyManager.findGirl();
这就是动态代理的好处,比如在做web的拦截器时,只需要在
System
.
out
.
println
(
"I am Manager, I am help other find job"
); 改为对method的判断或者
对参数的判断,就可以达到拦截的处理。比如
if(method.getName.endwith(".jpg")){
return null;
}
接下来看看proxy底层代码是怎么实现的。
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<Void>() {
public Void run() {
//如果私有,需要设置
setAccessible为true才能读取cons.setAccessible(true);
return null;
}
});
}
//反射生存对象
return cons.newInstance(new Object[]{h});
...
...
}
底层就是通过反射完成的。