在上一篇文章中说说java反射(1)我们已经了解了反射的基本概念以及它的原理,但是我们知道反射只能能用它来做些什么呢?
其实在我们很多已经很熟的框架中都有它的身影,例如Hibernate框架中的关联映射,Spring框架:IOC(控制反转).反射可以实现各种框架功能,接下来我们通过一个实例来写一个很小很小的框架,通过此例子来理解反射真正的价值所在.
接下来的例子主要功能是通过java反射来获取配置文件中的信息.通过配置文件,在程序运行的时候实例化所需要的类型的实例.
首先先建立一个资源文件,这里我们用config.properties来进行配置相关信息.
config.properties文件内容如下:指定类型为ArrayList类型.
- ClassName=java.util.ArrayList
接下来建立一个反射测试类:
- package com.tgb.java;
- import java.io.FileInputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.util.Collection;
- import java.util.Properties;
- /**
- * 通过一个小例子来演示通过反射技术实现一个简单的框架.
- *
- * @author jnqqls
- * @group TGB
- * @version 1.0
- *
- * @comments
- */
- public class ReflectTest {
- /**
- * @param args
- * @throws IOException
- * @throws ClassNotFoundException
- * @throws IllegalAccessException
- * @throws InstantiationException
- */
- public static void main(String[] args) throws IOException,
- InstantiationException, IllegalAccessException,
- ClassNotFoundException {
- // 将文件读入数据流
- InputStream ipt = new FileInputStream("config.properties");
- // 创建Properties对象
- Properties ppt = new Properties();
- // 将数据流载入到ppt对象中.
- ppt.load(ipt);
- // 关闭占用资源.
- ipt.close();
- // 获取配置文件中的名字.
- String className = ppt.getProperty("ClassName");
- // 通过反射创建className所对应的类的一个实例.
- @SuppressWarnings("unchecked")
- Collection<String> collections = (Collection<String>) Class.forName(
- className).newInstance();
- collections.add(new String("a"));
- collections.add(new String("b"));
- System.out.println(collections.size());
- }
- }
通过测试,输出的数字为2.也就是集合中有两个对象.这里和我们通常的new是不一样的概念,我们的例子是在运行时所创建的对象,而我们常用的new是在编译的时候所生成的对象,因为可以配置我们想要的类型和生成的对象,这便为各种框架提高了支撑.
现在对框架有了一个最简单的例子,通过对反射有了一定的了解便会更进一步的了解Spring框架,对于Spring框架的铺垫就是这些.接下来会继续介绍Spring框架的使用.
Class.forName( )静态方法的目的是为了动态加载类。在加载完成后,一般还要调用Class下的newInstance( )静态方法来实例化对象以便操作。因此,Class.forName( )是动态加载类是没有用的,其最终目的是为了实例化对象。调用 forName("X") 将导致命名为 X 的类被初始化。
01
|
package com.java.jvm;
|
02
|
03
|
public class ClassTest
{
|
04
|
public static void main(String[]
arg){
|
05
|
try {
|
06
|
Class
userClass = Class.forName("com.java.jvm.User");
|
07
|
System.out.println("userClass="+userClass);
|
08
|
User
user = (User) userClass.newInstance();
|
09
|
System.out.println("user="+user);
|
10
|
} catch (ClassNotFoundException
e) {
|
11
|
e.printStackTrace();
|
12
|
} catch (InstantiationException
e) {
|
13
|
e.printStackTrace();
|
14
|
} catch (IllegalAccessException
e) {
|
15
|
e.printStackTrace();
|
16
|
}
|
17
|
}
|
18
|
}
|
1
|
userClass=class com.java.jvm.User
|
2
|
user=User
[name=null,
age=null,
address=null]
|
Class.forName("").newInstance()返回的是object 其实和new 的关键字作用相同。
调用 forName("X") 将导致命名为 X 的类被初始化,这句话是官网API上的一句话,很迷茫,有点不理解,所以在User类中,添加了static语句块和User构造函数
01
|
package com.java.jvm;
|
02
|
03
|
public class User
{
|
04
|
|
05
|
static{
|
06
|
System.out.println("static
---");
|
07
|
}
|
08
|
|
09
|
public User(){
|
10
|
System.out.println("name="+name);
|
11
|
name="xiaotian";
|
12
|
}
|
13
|
|
14
|
private String
name;
|
15
|
private Integer
age;
|
16
|
private String
address;
|
17
|
|
18
|
public String
getName() {
|
19
|
return name;
|
20
|
}
|
21
|
public void setName(String
name) {
|
22
|
this.name
= name;
|
23
|
}
|
24
|
public Integer
getAge() {
|
25
|
return age;
|
26
|
}
|
27
|
public void setAge(Integer
age) {
|
28
|
this.age
= age;
|
29
|
}
|
30
|
public String
getAddress() {
|
31
|
return address;
|
32
|
}
|
33
|
public void setAddress(String
address) {
|
34
|
this.address
= address;
|
35
|
}
|
36
|
@Override
|
37
|
public String
toString() {
|
38
|
return "User
[name=" +
name + ",
age=" +
age + ",
address=" +
address
|
39
|
+ "]";
|
40
|
}
|
41
|
|
42
|
}
|
1
|
static ---
|
2
|
userClass=class com.java.jvm.User
|
3
|
name=null
|
4
|
user=User
[name=xiaotian, age=null,
address=null]
|
forName("X") 执行的时候,调用了User中的静态语句块,newInstance()执行的时候调用了构造函数。
连接数据库的简单代码
01
|
//
驱动程序名
|
02
|
String
driver = "com.mysql.jdbc.Driver";
|
03
|
04
|
//
URL指向要访问的数据库名student
|
05
|
String
url = "jdbc:mysql://127.0.0.1:3306/student";
|
06
|
07
|
//
MySQL配置时的用户名
|
08
|
String
user = "root";
|
09
|
10
|
//
MySQL配置时的密码
|
11
|
String
password = "root";
|
12
|
13
|
try {
|
14
|
//
加载驱动程序
|
15
|
Class.forName(driver);
|
16
|
17
|
//
连续数据库
|
18
|
Connection
conn = DriverManager.getConnection(url, user, password);
|
19
|
20
|
if(!conn.isClosed())
|
21
|
System.out.println("Succeeded
connecting to the Database!");
|
22
|
23
|
//
statement用来执行SQL语句
|
24
|
Statement
statement = conn.createStatement();
|
25
|
26
|
//
要执行的SQL语句
|
27
|
String
sql = "select
* from student";
|
28
|
29
|
//
结果集
|
30
|
ResultSet
rs = statement.executeQuery(sql);
|
Class.forName(driver);加载mysql驱动,执行static语句块,使将Driver对象注册到DriverManager中,然后上面就获得了数据库连接
01
|
package com.mysql.jdbc
|
02
|
|
03
|
public class Driver extends NonRegisteringDriver implements java.sql.Driver
{
|
04
|
//
~ Static fields/initializers
|
05
|
//
--------------------------------------------- // A
|
06
|
//
Register ourselves with the DriverManager
|
07
|
//
|
08
|
static {
|
09
|
t
ry { //使将Driver对象注册到DriverManager中
|
10
|
java.sql.DriverManager.registerDriver(new Driver());
|
11
|
} catch (SQLException
E) {
|
12
|
throw new RuntimeException("Can't
register driver!");
|
13
|
}
|
14
|
}
|
15
|
//
~ Constructors
|
16
|
//
-----------------------------------------------------------
|
17
|
/**
|
18
|
*
Construct a new driver and register it with DriverManager
|
19
|
*
|
20
|
*
@throws SQLException
|
21
|
*
if a database error occurs.
|
22
|
*/ |
23
|
public Driver() throws SQLException
{
|
24
|
//
Required for Class.forName().newInstance()
|
25
|
}
|
26
|
}
|