下面通过一个例子模拟Spring使用注解读取配置。
注解@Bean:
package org.zzj.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(value = ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Bean {
}
被该注解标记的类将会被Spring容器实例化。
package org.zzj.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(value = { ElementType.FIELD, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface Inject {
InjectType injectType() default InjectType.NAME;
}
该注解用于Bean注入。
注入类型InjectType:
package org.zzj.annotation;
/**
* 注入类型
*
* @author lenovo
*
*/
public enum InjectType {
NAME, TYPE
}
定义了名称注入和类型注入。
扫描器ScanProcessor:
package org.zzj.test;
import java.io.File;
import java.io.FileFilter;
import java.util.ArrayList;
import java.util.List;
/**
* 扫描器
*
* @author lenovo
*
*/
public class ScanProcessor {
private List<Class<?>> beanClazzes = new ArrayList<Class<?>>();
private String parentPkgFile;
private String parentPkgFileEX;
private FileFilter fileFilter = new FileFilter() {
public boolean accept(File pathname) {
if (pathname == null) {
return false;
}
if (pathname.isFile()) {
return pathname.getName().endsWith(".class");
} else {
return true;
}
}
};
public ScanProcessor(String parentPkg) {
this.parentPkgFile = parentPkg.replace(".", "/");
System.out.println(parentPkgFile);
this.parentPkgFileEX = parentPkg.replace(".", "\\");
System.out.println(parentPkgFileEX);
}
public List<Class<?>> scan() {
String path = ScanProcessor.class.getClassLoader()
.getResource(parentPkgFile).getPath();
System.out.println(path);
File file = new File(path);
getBeanClazz(file);
return beanClazzes;
}
private void getBeanClazz(File file) {
if (file.isFile()) {
String fileName = file.getPath();
String classPath = fileName.substring(fileName
.indexOf(parentPkgFileEX));
String className = classPath.replace("\\", ".");
// 截掉后缀名
className = className.substring(0, className.lastIndexOf(".class"));
try {
beanClazzes.add(Class.forName(className));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} else {
File[] files = file.listFiles(fileFilter);
for (File childFile : files) {
getBeanClazz(childFile);
}
}
}
public static void main(String[] args) {
ScanProcessor processor = new ScanProcessor("org.zzj");
List<Class<?>> list = processor.scan();
for (Class<?> clazz : list) {
System.out.println(clazz.getName());
}
}
}
该扫描器能扫描指定包下所有的class文件(包括所有子包)。
注解处理器AnnotationProcessor:
package org.zzj.test;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.zzj.annotation.Bean;
import org.zzj.annotation.Inject;
import org.zzj.annotation.InjectType;
/**
* 注解处理器
*
* @author lenovo
*
*/
public class AnnotationProcessor {
private ScanProcessor scanProcessor;
private Map<String, Object> beans = new HashMap<String, Object>();
public AnnotationProcessor(String parentPkg) {
scanProcessor = new ScanProcessor(parentPkg);
}
public Map<String, Object> getBean() throws Exception {
List<Class<?>> classes = scanProcessor.scan();
for (Class<?> clazz : classes) {
Bean bean = clazz.getAnnotation(Bean.class);
if (bean != null) {
addBean(clazz);
}
}
inject();
return beans;
}
private void inject() throws Exception {
for (Object bean : beans.values()) {
Field[] fields = bean.getClass().getDeclaredFields();
for (Field field : fields) {// 字段注入
Inject inject = field.getAnnotation(Inject.class);
if (inject != null) {
InjectType injectType = inject.injectType();
if (injectType == InjectType.NAME) {// 根据名称注入
Object injectBean = beans.get(field.getName());
field.setAccessible(true);
field.set(bean, injectBean);// 注入
} else if (injectType == InjectType.TYPE) {
// TODO 根据类型注入
}
}
}
Method[] methods = bean.getClass().getDeclaredMethods();
for (Method method : methods) {// 方法注入
Inject inject = method.getAnnotation(Inject.class);
if (inject != null) {
// TODO
}
}
}
}
private void addBean(Class<?> clazz) throws InstantiationException,
IllegalAccessException {
String beanName = clazz.getSimpleName();
beanName = beanName.replace(beanName.substring(0, 1),
(beanName.substring(0, 1)).toLowerCase());
Object beanObj = clazz.newInstance();
beans.put(beanName, beanObj);
}
}
注解处理器用来实例化Bean以及完成注入。
应用上下文ApplicationContext:
package org.zzj.test;
import java.util.Map;
public class ApplicationContext {
private AnnotationProcessor annotationProcessor;
private Map<String, Object> beans;
public ApplicationContext(String parentPkg) {
annotationProcessor = new AnnotationProcessor(parentPkg);
try {
beans = annotationProcessor.getBean();
} catch (Exception e) {
e.printStackTrace();
}
}
public Object getBean(String name) {
return beans.get(name);
}
}
应用上下文用来管理Bean。
package org.zzj.entity;
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;
}
}
Dao类:
package org.zzj.dao;
import org.zzj.annotation.Bean;
import org.zzj.entity.User;
@Bean
public class UserDao {
public boolean addUser(User user){
return true;
}
}
Service类:
package org.zzj.service;
import org.zzj.annotation.Bean;
import org.zzj.annotation.Inject;
import org.zzj.annotation.InjectType;
import org.zzj.dao.UserDao;
import org.zzj.entity.User;
@Bean
public class UserService {
@Inject(injectType = InjectType.NAME)
private UserDao userDao;
public boolean add(User user) {
System.out.println("添加用户...");
return userDao.addUser(user);
}
}
测试:
package org.zzj.test;
import org.zzj.entity.User;
import org.zzj.service.UserService;
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
ApplicationContext context = new ApplicationContext("org.zzj");
UserService userService = (UserService) context.getBean("userService");
System.out.println(userService.add(new User()));
}
}
输出:
org/zzj
org\zzj
/E:/myeclipse/annotation/WebRoot/WEB-INF/classes/org/zzj
添加用户...
true