您的位置:首页 > 编程语言 > Java开发

jdk 源码分析(21)java 动态代理和反射

2017-08-09 23:09 711 查看
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});

...

      ...

}


底层就是通过反射完成的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  jdk 源代码