Spring的反射机制和依赖注⼊
我们知道,Spring中⼤量使⽤了反射机制,那么究竟是什么地⽅使⽤了呢?
spring的⼀⼤核⼼概念是注⼊,
但是,这存在的⼀个前提就是类是由spring管理起来的。
反射是根据className⽣成⼀个具体的实例,
这是⼀个很实⽤的思想。
⽐如:当我们需要根据传进来的参数的类型,选择具体的实现类时,
反射机制就能很好的解决问题。
然⽽,⼀般我们使⽤反射机制,创建的代理类是根据构造函数实例化的。
⽽不是从spring容器中注⼊。
这样就会导致⼀个问题,⽆法在创建的代理类中实现注⼊功能。
当然,如果你⼀定要使⽤的话,系统会提⽰空指针错误。
这个时候,如果把反射创建的类由spring注⼊就可以有效的解决这个问题。
这样也存在⼀个问题。
就是获得spring的ApplicationContext.
如果我们重新获得⼀遍的话,
这样就是对系统资源极⼤的浪费。
这样我们可以声明⼀个静态变量将ApplicationContext保存起来
// 声明⼀个静态变量保存
public void setApplicationContext(ApplicationContext contex)
throws BeansException {
}
并将其⽤spring容器管理起来。
这样的话,我们就可以很轻松的获得ApplicationContext,⽽不需要消耗太多的系统资源。
从⽽,很简单的,
当我们的实现类全部继承⼀个相同的接⼝时,
我们的接⼝便可以通过反射初始化。
从⽽,创建不同的具体实现类。
同时,因为所有的类都是通过spring管理起来的。
很明显,在创建的实现类中也是可以使⽤spring的注⼊。
⽽不是有空指针错误。
⼀反射源头Class类
对类的概念我们已经⾮常熟悉了。⽐如可以有Student这个类,Person这个类。但是我们要知道,有⼀个叫Class的类,它是反射的源头。
正常⽅式:通过完整的类名—>通过new实例化—>取得实例化对象
反射⽅式:实例化对象—>getClass()⽅法—>通过完整的类名
⼀个简单的例⼦:
package cn.classes;
public class OneClass {
}
st;
import cn.classes.OneClass;
public class Test {
public static void main(String[] args) {
OneClass c = new OneClass();
System.out.Class().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.Name());
System.out.Name());
System.out.Name());
}
}
输出结果:cn.classes.OneClass
⼆利⽤Class这个类实例化类
①⽆参构造
package cn.classes;
public class Person {
private String name;
private int age;
.............省略
@Override
public String toString()
{
return "Person [name=" + name + ", age=" + age + "]"; }
}
st;
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 = (wInstance(); 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;
.............省略
@Override
public String toString()
{
实例化bean的三种方式return "Person [name=" + name + ", age=" + age + "]";
}
}
st;
import flect.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<?>[] cons = c.getConstructors(); Person p = (Person)cons[0].newInstance("xy",20);
System.out.println(p);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
三 Spring中使⽤Class实例化
<bean id="id" class="Student" />
Spring将采⽤的代码创建代码Java实例
Class c = Class.forName("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);
}
}
st;
import flect.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.wInstance());
// 带参数⽅法调⽤
Method m1 = c1.getMethod("addWithParameters", String.class, int.class); m1.wInstance(), "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
}
st;
import flect.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 = Class().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 = Class().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="Student">
<property name="stuName" value="xy" /></bean>
Spring将采⽤的代码创建代码Java实例,并注⼊值:
Class c = Class.forName("Student"); Object bean = c.newInstance();
通过⼀些操作获取对stuName对应的setter⽅法名
String setname = "set" + "StuName"; Method method = c.getMehod(setname,String.Class); method.invoke(bean,"xy");
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论