Spring中应用反射机制浅析

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

一  反射源头Class类

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

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

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

一个简单的例子:

双击代码全选
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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这个类,有三种方法:

双击代码全选
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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这个类实例化类

①无参构造

双击代码全选
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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();  
                }    
      }  
}

②有参构造

双击代码全选
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
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实例化

双击代码全选
1
2
bean.xml  
<bean id= "id" class = "com.xy.Student" />

Spring将采用的代码创建代码Java实例

双击代码全选
1
2
Class c = Class.forName( "com.xy.Student" );  
Object bean = c.newInstance();

四 Class类调用方法

双击代码全选
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
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方法。

双击代码全选
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
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注入例子

双击代码全选
1
2
3
4
bean.xml  
<bean id= "id" class = "com.xy.Student" >  
     <property name= "stuName" value= "xy" />  
</bean>

Spring将采用的代码创建代码Java实例,并注入值:

双击代码全选
1
2
Class c = Class.forName( "com.xy.Student" );  
Object bean = c.newInstance();

通过一些操作获取对stuName对应的setter方法名

双击代码全选
1
2
3
String setname = "set" + "StuName" ;  
Method method = c.getMehod(setname,String.Class);  
method.invoke(bean, "xy" );

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

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

七 总结

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

本文出自 “IT Fat Man” 博客,请务必保留此出处http://woshixy.blog.51cto.com/5637578/1060263


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值