因为IoC这个名字比较晦涩,因此业界又提出了DI(依赖注入:Dependency Injection)的概念用以代替IoC,
即让调用类对某一接口的实现类的依赖关系由容器注入,以移除调用类对这一接口实现的依赖.其中,spring就是这样一个容器,
它通过配置文件或注解描述类和类之间的依赖关系,自动完成类的初始化和依赖注入工作.spring为什么这么神奇呢,
这样神奇的力量完全归功于java语言本身的类反射功能,闲话少说,让我简单回顾一下java语言的反射知识吧.
1.java语言反射机制介绍.
java语言允许通过程序化的方式间接对Class的对象实例操作,Class文件由类装载器装载后,在JVM中将形成一份
描述Class结构的元信息对象,通过这些元信息对象可以获取Class的结构信息,如构造函数,属性和方法等.
首先看一个简单的例子,直接看代码.
package com.ilucky.spring.reflect;
/**
* @author IluckySi
* @date 20140424
*/
public class User {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public void getUserInfo() {
System.out.println(username + ":" + password);
}
}
package com.ilucky.spring.reflect;
/**
* @author IluckySi
* @date 20140424
*/
public class RegularMainTest {
public static void main(String[] args) {
User user = new User();
user.setUsername("Ilucky");
user.setPassword("123456");
user.getUserInfo();
}
}
/**
输出结果:
Ilucky:123456
*/
如上的主方法是采用传统方式直接调用目标类的方法,下面我们通过java反射机制间接的操作目标类.
直接看代码.
package com.ilucky.spring.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
/**
* @author IluckySi
* @date 20140424
*/
public class ReflectMainTest {
@SuppressWarnings({ "unchecked", "rawtypes" })
public static void main(String[] args) throws Throwable {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Class clazz = classLoader.loadClass("com.ilucky.spring.reflect.User");
//通过反射机制创建User对象,相当于new User();
Constructor constructors= clazz.getDeclaredConstructor((Class[])null);//空构造函数.
User user = (User)constructors.newInstance();
//通过反射机制设置属性.相当于setUsername("ilucky")和setPassword("123456").
Method setUsername = clazz.getMethod("setUsername", String.class);//String.class方法中的参数.
setUsername.invoke(user, "Ilucky");
Method setPassword = clazz.getMethod("setPassword", String.class);
setPassword.invoke(user, "123456");
//输出用户信息.
Method getUserInfo = clazz.getMethod("getUserInfo");
getUserInfo.invoke(user);
}
}
/**
输出结果:
Ilucky:123456
*/
2.类装载器ClassLoader工作机制.类装载器是寻找类的字节码文件并构造出类在JVM内部表示的对象组件.在java中,类装载器把一个类装入JVM中,
主要经过三个步骤:1.装载-查找和导入class文件.2.链接-检查载入的class文件数据的正确定,
给类的静态变量分配存储空间,将符号的引用转换成直接引用.3.初始化-对类的静态变量,静态代码块执行初始化工作.
类装载工作由ClassLoader及其子类负责,ClassLoader是一个重要的java运行时系统,他负责在运行时查找和装入class
的字节码文件.
JVM在运行时会产生三个ClassLoader:根装载器,ExtClassLoader(扩展类装载器)和AppClasLoader(系统类
装载器).其中,根装载器不是ClassLoader的子类,它使用C++编写,因此我们在java中看不到他,根装载器负责装载JRE的核心类库,
如JRE目录下的rt.jar和chartset.jar等.ExtClassLoader和AppClassLoader是ClassLoader的子类,其中ExtClassLoader负责装载
JRE扩展目录ext中的JAR类包,AppClassLoader负责装载Classpath路径下的类包.直接通过代码看他们之间的关系:
package com.ilucky.spring.classloader;
/**
* @author IluckySi
* @date 20140424
*/
public class ClassLoaderTest {
public static void main(String[] args) {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
System.out.println("current loader" + classLoader);
System.out.println("parent loader" + classLoader.getParent());
System.out.println("parent loader" + classLoader.getParent().getParent());
}
}
/**
输出结果:
current loadersun.misc.Launcher$AppClassLoader@192d342
parent loadersun.misc.Launcher$ExtClassLoader@6b97fd
parent loadernull
*/
通过上面的输出结果,可以得知加载class路径下的类包的装载器是AppClassLoader,AppClassLoader的父亲是ExtClassLoader,ExtClassLoader的父类是根装载器,因为根装载器是用C++编写的,所以在java中无法获得它的句柄,所以返回结果null.
JVM装载类时使用"全盘负责委托机制",即先委托父装载器寻找目标类,只有在找不到的情况下,才从自己的类路径下查找并装载目标类.
ClasLoader是一个抽象类,位于java.lang包中,在这个类里面有很多重要的方法,在这里暂时不做介绍.
3.java反射类.
Class反射对象描述类语义结构,可以从Class对象中获取构造函数,成员变量和方法等.这些反射类在java.reflect包中,
其中最主要的三个反射类是Constructor,Method和Field.在这三个反射类中有很多中要的方法,在这里暂时不做介绍.
此外,java还提供了package反射类,在jdk5.0中还为注解提供了AnnotatedElement发射类.总之,java反射体系保证了可以通过
程序化的方式访问类中所有的元素,对于private和protected的成员变量和方法,只要JVM的安全机制允许,也可以通过反射进行调用.
直接通过代码比较.
package com.ilucky.spring.reflect2;
/**
* @author IluckySi
* @date 20140424
*/
public class PrivateUser {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@SuppressWarnings("unused")
private void getUserInfo() {
System.out.println(username + ":" + password);
}
}
package com.ilucky.spring.reflect2;
/**
* @author IluckySi
* @date 20140424
*/
public class RegularMainTest {
public static void main(String[] args) {
PrivateUser user = new PrivateUser();
user.setUsername("Ilucky");
user.setPassword("123456");
//如下语句报错: The method getUserInfo() from the type PrivateUser is not visible.
//user.getUserInfo();
}
}
package com.ilucky.spring.reflect2;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
/**
* @author IluckySi
* @date 20140424
*/
public class ReflectMainTest {
@SuppressWarnings({ "unchecked", "rawtypes" })
public static void main(String[] args) throws Throwable {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Class clazz = classLoader.loadClass("com.ilucky.spring.reflect2.PrivateUser");
//通过反射机制创建User对象,相当于new User();
Constructor constructors= clazz.getDeclaredConstructor((Class[])null);//空构造函数.
PrivateUser user = (PrivateUser)constructors.newInstance();
//通过反射机制设置属性.相当于setUsername("ilucky")和setPassword("123456").
Method setUsername = clazz.getMethod("setUsername", String.class);//String.class方法中的参数.
setUsername.invoke(user, "Ilucky");
Method setPassword = clazz.getMethod("setPassword", String.class);
setPassword.invoke(user, "123456");
//输出用户信息.
Method getUserInfo = clazz.getDeclaredMethod("getUserInfo");
getUserInfo.setAccessible(true);
getUserInfo.invoke(user, (Object[])null);
}
}
/**
输出结果:
Ilucky:123456
*/
对于java反射机制的知识先写到这里,这里只是做一下简单的回顾,要想了解更多关于java反射类的知识,上网查吧......