BeanSoft's Java Blog
免费电子书/视频《MyEclipse 6 Java 开发中文教程》作者刘长炯官方博客 经济危机 珍惜生命 远离培训

我们学习 EJB 3 的时候, 经常会看到这样的代码:

@TimerService

private TimerService timerService;

然后书上会告诉你容器会实例化 bean 然后注入对应的值, 但是到底怎么实现的呢? 首先是 private 的变量啊. 经过一番研究, BeanSoft 终于实现了自己的元数据注入微容器(呵呵, jdon 的最爱啊)原型代码:

首先是调用, 肯定不能 new 了, 否则容器就无用武之地了.

package metadataDI.test;

import metadataDI.container.MetadataDIContainer;
import metadataDI.entity.UserBean;

/**
* @author Administrator
*
*/
public class TestMetadataDIContainer {

public static void main(String[] args) {
MetadataDIContainer container = new MetadataDIContainer();
UserBean bean = (UserBean) container.getUserBean();
System.out.println("被容器实例化过的 Bean 的 name 属性值是: " + bean.getName());
}

}

先 show 一下运行结果:

 

容器已经加载了 Bean 类
容器已经实例化了 Bean 类
容器将检查类里面的所有变量看是否有 @UserName 标注
列出类里面的所有变量
private java.lang.String name;
一共1个元数据注释
发现了 @UserName 标注, 将给实例的该字段设置值(注入值).
列出类里面的所有变量
private java.lang.String password;
一共0个元数据注释
被容器实例化过的 Bean 的 name 属性值是: 容器注入的用户名

Bean:

 

/**
*
*/
package metadataDI.entity;

import metadataDI.annotation.UserName;

/**
* 用户类.
*/
public class UserBean {
/**
* 名称变量
*/
@UserName
private String name;

private String password;

public UserBean() {
}
/**
* @return the password
*/
public String getPassword() {
return password;
}

/**
* @param password the password to set
*/
public void setPassword(String password) {
this.password = password;
}

/**
* @return the 名称变量
*/
public String getName() {
return name;
}

/**
* @param name the 名称变量 to set
*/
public void setName(String name) {
this.name = name;
}

}

注释类:

 

/**
*
*/
package metadataDI.annotation;

import java.lang.annotation.*;

/**
* 这个标注指明被标注的类的成员变量的值运行时将会被
* 设置为一个固定的值: "容器注入的用户名"
*/
@Documented
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.FIELD})//指定目标, 必须包含私有变量
@Retention(RetentionPolicy.RUNTIME)//设置保持性
@Inherited
public @interface UserName {

}

最重要的: 容器类

 

/**
*
*/
package metadataDI.container;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

import metadataDI.annotation.UserName;

/**
* 元数据依赖注入容器, 这里将加载 UserBean 然后实例化, 把
* 标注有 @UserName 的变量设置一个初始值: "容器注入的用户名".
*/
public class MetadataDIContainer {
/** bean 实例 */
private Object bean;
/**
* 容器初始化, 加载 JavaBean类, 实例化, 将里面的标有元数据的变量设置一个初始值.
*/
public MetadataDIContainer() {
try {
// 加载类, 类名可以是任意的 JavaBean 名称
Class clz = Class.forName("metadataDI.entity.UserBean");
System.out.println("容器已经加载了 Bean 类");
bean = clz.newInstance();
System.out.println("容器已经实例化了 Bean 类");
System.out.println("容器将检查类里面的所有变量看是否有 @UserName 标注");
Field[] fields = clz.getDeclaredFields();

for (Field f : fields)
{
System.out.println("列出类里面的所有变量");
Class type = f.getType();
String name = f.getName();
System.out.print(" " + Modifier.toString(f.getModifiers()));
System.out.println(" " + type.getName() + " " + name + "");
Annotation[] annotation = f.getAnnotations();
System.out.println("一共" + annotation.length + "个元数据注释");
if(f.getAnnotation(UserName.class) != null) {
System.out.println("发现了 @UserName 标注, 将给实例的该字段设置值(注入值).");
f.setAccessible(true);// 设置为 true 可以允许反射访问私有变量, 忽略 Java 的默认访问规则
f.set(bean, "容器注入的用户名");
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 通过容器获得生成的 Bean 实例.
* @return
*/
public Object getUserBean() {
return bean;
}

}

posted on 2007-07-27 14:30 BeanSoft 阅读(1194) 评论(3)  编辑  收藏 所属分类: Java EE