当前位置: 首页 > news >正文

转载 Spring中应用反射机制浅析

为什么80%的码农都做不了架构师?>>>   hot3.png


我们知道,spring中大量使用了反射机制,那么究竟是什么地方使用了呢?就从源头说起吧。

 

一  反射源头Class类

对类的概念我们已经非常熟悉了。比如可以有Student这个类,Person这个类。但是我们要知道,有一个叫Class的类,它是反射的源头。

 

正常方式:通过完整的类名—>通过new实例化—>取得实例化对象

反射方式:实例化对象—>getClass()方法—>通过完整的类名

 

一个简单的例子:

 

package cn.classes;

public class OneClass {

}


package cn.test;

import cn.classes.OneClass;

public class Test {
    public static void main(String[] args) {
        OneClass c = new OneClass();
        System.out.println(c.getClass().getName());
   }
}

输出结果:cn.classes.OneClass


我们需要使用反射,就要获得Class这个类,有三种方法:

package cn.classes;

public class OneClass {

}


import cn.classes.OneClass;

public class Test {
public static void main(String[] args) {
     Class<?> c1 = null;
     Class<?> c2 = null;
     Class<?> c3 = null;

     try 
    {
         // 方法一:forName(重要)
         c1 = Class.forName("cn.classes.OneClass");
    } 
    catch (ClassNotFoundException e) 
    {
         e.printStackTrace();
    }
     // 方法二
     c2 = new OneClass().getClass();
  
     // 方法三
     c3 = OneClass.class;

     System.out.println(c1.getName());
     System.out.println(c2.getName());
     System.out.println(c3.getName());
   }
}

输出结果:cn.classes.OneClass

 

 

二 利用Class这个类实例化类

 

①无参构造

package cn.classes;

public class Person {
    private String name;
    private int age;

     .............省略getter,setter..............

    @Override
    public String toString()
    {
          return "Person [name=" + name + ", age=" + age + "]";
    }

}


package cn.test;

import cn.classes.Person;

public class Test
{
    // 这样做必须在类中有一个空构造方法
    public static void main(String[] args)
    {
              Class<?> c = null;
               try
               {
                      c = Class.forName("cn.classes.Person");
                      Person p = (Person)c.newInstance();

                      p.setName("xy");
                      p.setAge(20);
                      System.out.println(p);
               } 
              catch (Exception e)
              {
                      e.printStackTrace();
               }  
     }
}

 

②有参构造

package cn.classes;

public class Person
{
    private String name;
    private int age;

     public Person(Stringname,int age){

                 this.name = name;

                 this.age = age;

    }

    .............省略getter,setter..............    

    @Override
    public String toString()
    {
          return "Person [name=" + name + ", age=" + age + "]";
    }
}


package cn.test;

import Java.lang.reflect.Constructor;

import cn.classes.Person;

public class Test
{
    // 如果没有一个空构造方法
    public static void main(String[] args)
    {
          Class<?> c = null;
          try
          {
                  c = Class.forName("cn.classes.Person");
                  Constructor<?> con = c.getConstructors(String.class,int.class);

                  Person p = (Person)con.newInstance("xy",20);
                  System.out.println(p);
          } 
         catch (Exception e)
         {
                e.printStackTrace();
         }  
    }
}

 

三 Spring中使用Class实例化

bean.xml
<bean id="id" class="com.xy.Student" />

 

Spring将采用的代码创建代码Java实例
Class c = Class.forName("com.xy.Student");
Object bean = c.newInstance();

 

 

四 Class类调用方法

package cn.classes;

public class Person
{
    public void add()
    {
           System.out.println("add");
    }

    public void addWithParameters(String name, int age)
    {
            System.out.println("add带参数方法" + name + age);
    }
}


package cn.test;

import java.lang.reflect.Method;

public class Test
{
    public static void main(String[] args)
    {
             Class<?> c1 = null;
             try
             {

                   c1 = Class.forName("cn.classes.Person");

                   // 不带参数的方法调用
                   Method m = c1.getMethod("add");
                   m.invoke(c1.newInstance());

 

                   // 带参数方法调用
                   Method m1 = c1.getMethod("addWithParameters", String.class, int.class);
                   m1.invoke(c1.newInstance(), "xy", 22);

            }
            catch (Exception e)
            {
                   e.printStackTrace();
            }
    }
}

 

 

五 Class获得getter,setter方法

Class这个类可以获得类的很多信息,比如获得该类的接口,构造函数,属性,方法等。我们来看如何获得getter,setter方法。

package cn.classes;

public class Person
{
    private String name;
    private int age;

    省略getter,setter  

 }

 

package cn.test;

import java.lang.reflect.Method;

public class Test
{
    public static void main(String[] args)
    {
           Class<?> c1 = null;
           Object obj = null;
           try
           {
                     c1 = Class.forName("cn.classes.Person");
                     obj = c1.newInstance();
                     setter(obj, "name", "xy", String.class);
                     setter(obj, "age", 20, int.class);
                     getter(obj, "name");
                     getter(obj, "age");
           }
           catch (Exception e)
            {
                    e.printStackTrace();
            }
   }

   /**
    * @param obj:要操作的对象
    * @param att:要操作的属性
    * @param value:要设置的属性内容
    * @param type:要设置的属性类型
    */
    public static void setter(Object obj, String att, Object value, Class<?> type)
    {
         try
         {
            // 得到setter方法
          Method m = obj.getClass().getMethod("set" + initStr(att), type);
          m.invoke(obj, value);
         }
         catch (Exception e)
         {
          e.printStackTrace();
         }
   }

   /**
    * @param obj:要操作的对象
    * @param att:要操作的属性
    */
   public static void getter(Object obj, String att)
   {
        try
        {
               // 得到getter方法
               Method m = obj.getClass().getMethod("get" + initStr(att));
               System.out.println(m.invoke(obj));
        }
       catch (Exception e)
       {
               e.printStackTrace();
       }
   }

   public static String initStr(String oldStr)
   {
         String newStr = oldStr.substring(0, 1).toUpperCase() + oldStr.substring(1);
         return newStr;
   }
}

 

六 Spring调用getter,setter方法

我们以setter注入例子

bean.xml
<bean id="id" class="com.xy.Student">
    <property name="stuName" value="xy" />
</bean>


Spring将采用的代码创建代码Java实例,并注入值:
Class c = Class.forName("com.xy.Student");
Object bean = c.newInstance();


通过一些操作获取对stuName对应的setter方法名
String setname = "set" + "StuName";
Method method = c.getMehod(setname,String.Class);
method.invoke(bean,"xy");

这样就完成了最基本的注入操作。当然,Spring还可以通过构造函数进行注入。这样就参考第二点有参构造的Class的使用。

Class还可以访问Annotation,这样就Spring使用注解的时候,可以完成注入的功能。

 

七 总结

反射的内容还是很多的,需要系统的学习。当然,Spring也是。

 

转载于:https://my.oschina.net/jywm/blog/698823

相关文章:

  • MyCat_全局表及其死锁问题
  • TortoiseGit状态图标不能正常显示的解决办法
  • 怎么在Beyond Compare中同步压缩文件夹
  • iOS import framework头文件时报错could not build module xxx
  • java 多线程和线程池
  • jQuery Ajax无刷新操作
  • JavaScript里的数组转化新方法Array.From
  • 我的业余项目总结
  • 【编码】-360实习笔试编程题(二)-2016.03.29
  • 如何获取drawable目录下的图片绝对路径
  • iOS开发多线程篇 09 —NSOperation简单介绍
  • nb
  • PHP字符串操作相关
  • dtrace 手册
  • Nginxt rewrite企业应用实例
  • (三)从jvm层面了解线程的启动和停止
  • 【108天】Java——《Head First Java》笔记(第1-4章)
  • angular学习第一篇-----环境搭建
  • flutter的key在widget list的作用以及必要性
  • Idea+maven+scala构建包并在spark on yarn 运行
  • iOS动画编程-View动画[ 1 ] 基础View动画
  • Iterator 和 for...of 循环
  • Traffic-Sign Detection and Classification in the Wild 论文笔记
  • Vue.js-Day01
  • 阿里云容器服务区块链解决方案全新升级 支持Hyperledger Fabric v1.1
  • 诡异!React stopPropagation失灵
  • 解决jsp引用其他项目时出现的 cannot be resolved to a type错误
  • 如何邀请好友注册您的网站(模拟百度网盘)
  • 算法系列——算法入门之递归分而治之思想的实现
  • 它承受着该等级不该有的简单, leetcode 564 寻找最近的回文数
  • 学习使用ExpressJS 4.0中的新Router
  • 追踪解析 FutureTask 源码
  • Play Store发现SimBad恶意软件,1.5亿Android用户成受害者 ...
  • #HarmonyOS:软件安装window和mac预览Hello World
  • #if和#ifdef区别
  • %3cscript放入php,跟bWAPP学WEB安全(PHP代码)--XSS跨站脚本攻击
  • (day6) 319. 灯泡开关
  • (动态规划)5. 最长回文子串 java解决
  • (附源码)springboot人体健康检测微信小程序 毕业设计 012142
  • (剑指Offer)面试题41:和为s的连续正数序列
  • (接口自动化)Python3操作MySQL数据库
  • (删)Java线程同步实现一:synchronzied和wait()/notify()
  • (正则)提取页面里的img标签
  • (转)Android学习系列(31)--App自动化之使用Ant编译项目多渠道打包
  • (转)Spring4.2.5+Hibernate4.3.11+Struts1.3.8集成方案一
  • ***微信公众号支付+微信H5支付+微信扫码支付+小程序支付+APP微信支付解决方案总结...
  • .net core 6 redis操作类
  • .NET Framework 的 bug?try-catch-when 中如果 when 语句抛出异常,程序将彻底崩溃
  • .NET gRPC 和RESTful简单对比
  • .NET 的程序集加载上下文
  • .NET/C# 在代码中测量代码执行耗时的建议(比较系统性能计数器和系统时间)...
  • .NET的数据绑定
  • .net对接阿里云CSB服务
  • .NET国产化改造探索(一)、VMware安装银河麒麟
  • .NET开发者必备的11款免费工具