天天看點

Spring中應用反射機制淺析

我們知道,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這個類,有三種方法:

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());

二 利用class這個類執行個體化類

①無參構造

public class person {

    private string name;

    private int age;

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

    @override

    public string tostring()

          return "person [name=" + name + ", age=" + age + "]";

    }

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();

               }  

     }

②有參構造

public class person

     public person(stringname,int age){

                 this.name = name;

                 this.age = age;

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

import java.lang.reflect.constructor;

    // 如果沒有一個空構造方法

          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類調用方法

    public void add()

           system.out.println("add");

    public void addwithparameters(string name, int age)

            system.out.println("add帶參數方法" + name + age);

import java.lang.reflect.method;

             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方法。

    省略getter,setter  

 }

           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);

         }

          e.printstacktrace();

   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 id="id" class="com.xy.student">

    <property name="stuname" value="xy" />

</bean>

spring将采用的代碼建立代碼java執行個體,并注入值:

通過一些操作擷取對stuname對應的setter方法名

string setname = "set" + "stuname";

method method = c.getmehod(setname,string.class);

method.invoke(bean,"xy");

這樣就完成了最基本的注入操作。當然,spring還可以通過構造函數進行注入。這樣就參考第二點有參構造的class的使用。

class還可以通路annotation,這樣就spring使用注解的時候,可以完成注入的功能。

七 總結

反射的内容還是很多的,需要系統的學習。當然,spring也是。

Spring中應用反射機制淺析