简易的通过注解自动实例化bean 应用

  • 两个注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Service {
	String value() default "";
}

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface ComponentScan {
	String value() default "";
}
  • 配置类,指定扫描哪个包
@ComponentScan("com.qhf")
class AppConfig {
	
}
  • 组件标注的类,在com.qhf.spring 包下,自动实例化此包下的类
package com.qhf;

@Service("userService")
class UserService {
	
}
  • productService
package com.qhf.service;

import com.qhf.Service;

@Service
public class ProductService {

}

 

  • 工厂类
public class BeanFactory {
	private Map<String, Object> objMap = new ConcurrentHashMap<>();
	private Map<Class<?>, String> clsMap = new ConcurrentHashMap<Class<?>, String>();//记录所有Service 注解的字节码对象
	
	public BeanFactory() {
		
	}
	
	/**
	 * 对含有ComponentScan 注解的包进行扫描,获取字节码对象存在Set集合中,暂不实例化对象,当使用时再实例化存在Map 中
	 */
	public BeanFactory(Class<?> configClass) throws Exception {
		ComponentScan componentScan = configClass.getAnnotation(ComponentScan.class);
		String pack = componentScan.value();
		if ("".equals(pack)) {
			pack = configClass.getPackage().getName();
		}
		
		String packPath = pack.replace(".", "/");
		URL url = ClassLoader.getSystemResource(packPath);
		// 若有中文路径
		String realPath = URLDecoder.decode(url.getPath(), "gbk");
		
		File dir = new File(realPath);
		loopDir(dir, pack);
		System.out.println(clsMap);
	}
	
	private void loopDir(File dir, String pack) throws Exception {
		File[] files = dir.listFiles();
		for (File file : files) {
			if (file.isFile()) {
				if (!file.getName().endsWith(".class")) {
					continue;
				}
				// 是class 文件并且有@Service 注解,则加入clsMap
				String simpleName = file.getName().split("\\.")[0];
				Class<?> clazz = Class.forName(pack + "." + simpleName);
				if (clazz.isAnnotationPresent(Service.class)) {
					clsMap.put(clazz, simpleName.substring(0,1).toLowerCase() + simpleName.substring(1));
				}
				
			} else {
				// 是目录, 递归
				loopDir(file, pack + "." + file.getName());
			}
		}
		
	}

	private Object newInstance(String beanName, Class<?> clazz) throws Exception {
		if (!clsMap.containsKey(clazz))
			return null;
		if (beanName == null) {
			String simpleName = clazz.getSimpleName().substring(0,1).toLowerCase() + clazz.getSimpleName().substring(1);
			if (objMap.containsKey(simpleName)) {
				return objMap.get(simpleName);
			} else {
				Object instance = clazz.newInstance();
				objMap.put(simpleName, instance);
				return instance;
			}
		} else {
			if (objMap.containsKey(beanName)) {
				return objMap.get(beanName);
			} else {
				return null;
			}
		}
	}
	
	public <T>T getBean(Class<T> clazz) throws Exception {
		return (T)newInstance(null, clazz);
	}
	
	public <T>T getBean(String beanName, Class<T> clazz) throws Exception {
		return (T)newInstance(beanName, clazz);
	}
	
	public static void main(String[] args) throws Exception {
		BeanFactory factory = new BeanFactory(AppConfig.class);
		ProductService ps = factory.getBean(ProductService.class);
		
		UserService us1 = factory.getBean(UserService.class);
		UserService us2 = factory.getBean("userService", UserService.class);
		
		System.out.println(ps);
		System.out.println(us1);
		System.out.println(us2);
		System.out.println(us1 == us2);
	}
}
  • 结果

{class com.qhf.service.ProductService=productService, class com.qhf.UserService=userService}
com.qhf.service.ProductService@45ee12a7
com.qhf.UserService@330bedb4
com.qhf.UserService@330bedb4
true

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值