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

java动态代理用在很多地方。spring框架,RPC框架中都使用了动态代理,动态代理很重要。
首先看看静态代理:
相对静态代理而已,静态代理需要对每一个方法做一次处理。如下:
定义一个实体列,交个代理类,然后由代理帮忙做事
   
   
  1. public static void main(String[] args) {
  2. People people = new Students();
  3. ProxyManager proxyManager = new ProxyManager(people);
  4. proxyManager.findJob();
  5. }
接口
   
   
  1. public interface People {
  2. public void findJob();
  3. }
实体类:
   
   
  1. public class Students implements People{
  2. @Override
  3. public void findJob() {
  4. System.out.println("I am student ,I am looking for a job");
  5. }
  6. }
代理类:
   
   
  1. public class ProxyManager implements People {
  2. People people ;
  3. public ProxyManager(People people){
  4. this.people = people;
  5. }
  6. @Override
  7. public void findJob() {
  8. System.out.println("I am Manager, I am help other find job");
  9. people.findJob();
  10. System.out.println("");
  11. }
  12. }
,如果实体类有多个方法,那么静态的代理类就需要复写多个方法,哪怕是做同样的事情,所以就出现动态代理。

添加一个动态代理类:
   
   
  1. public class ProxyD {
  2. Class target;
  3. Object object;
  4. public ProxyD(Class target,Object object){
  5. this.target=target;
  6. this.object=object;
  7. }
  8. public Object getPeopele() throws Throwable{
  9. return Proxy.newProxyInstance(target.getClassLoader(),
  10. new Class[]{target}, new ObjectHandle(this.object));
  11. }
  12. class ObjectHandle implements InvocationHandler{
  13. Object target;
  14. public ObjectHandle(Object object) {
  15. this.target = object;
  16. }
  17. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  18. System.out.println("I am Manager, I am help other find job");
  19. Object o = method.invoke(target, args);
  20. System.out.println("");
  21. return o;
  22. }
  23. }
  24. }
然后在看测试类:
   
   
  1. People people = new Students();
  2. ProxyD proxyD=new ProxyD(People.class,people);
  3. People proxyManager =(People) proxyD.getPeopele();
  4. proxyManager.findJob();
从这里看动态类和静态的没有什么区别,但是如果接口添加一个方法,那么静态代理类将必须重写这个方法,但是动态代理就不需要,可以直接调用,
   
   
  1. People people = new Students();
  2. ProxyD proxyD=new ProxyD(People.class,people);
  3. People proxyManager =(People) proxyD.getPeopele();
  4. proxyManager.findJob();
  5. proxyManager.findGirl();
这就是动态代理的好处,比如在做web的拦截器时,只需要在
System . out . println ( "I am Manager, I am help other find job" ); 改为对method的判断或者
对参数的判断,就可以达到拦截的处理。比如
if(method.getName.endwith(".jpg")){
return null;
}

接下来看看proxy底层代码是怎么实现的。

   
   
  1. public static Object newProxyInstance(ClassLoader loader,
  2. Class<?>[] interfaces,
  3. InvocationHandler h)
  4. throws IllegalArgumentException
  5. {
  6. Objects.requireNonNull(h);
  7.         //接口复制
  8. final Class<?>[] intfs = interfaces.clone();
  9.         //安全判断,一般不会设置安全问题
  10. final SecurityManager sm = System.getSecurityManager();
  11. if (sm != null) {
  12. checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
  13. }
  14. /*
  15. * Look up or generate the designated proxy class.
  16. */
  17.         //去缓存查看是否已经生成过,如果生存过直接获取。没有就生存并保存到缓存中
  18. Class<?> cl = getProxyClass0(loader, intfs);
  19. /*
  20. * Invoke its constructor with the designated invocation handler.
  21. */
  22. try {
  23. if (sm != null) {
  24. checkNewProxyPermission(Reflection.getCallerClass(), cl);
  25. }
  26.             //获取类的构造函数
  27. final Constructor<?> cons = cl.getConstructor(constructorParams);
  28. final InvocationHandler ih = h;
  29. if (!Modifier.isPublic(cl.getModifiers())) {
  30. AccessController.doPrivileged(new PrivilegedAction<Void>() {
  31. public Void run() {
  32.                         //如果私有,需要设置setAccessible为true才能读取
  33. cons.setAccessible(true);
  34. return null;
  35. }
  36. });
  37. }
  38.             //反射生存对象
  39. return cons.newInstance(new Object[]{h});
  40. ...
  41.       ...
  42. }

底层就是通过反射完成的。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值