Java中ioc加载Ben的原理_JAVA项目实战-Spring的DI和IOC加载原理

/*** @description:

*@author: ZhuCJ

* @date: 2020-08-27 10:16*/

public class AnnotationBeanFactory implementsBaseFactory {private static final Logger logger = LoggerFactory.getLogger(AnnotationBeanFactory.class);privateString packerName ;private static final String EXT = "class";

@OverridepublicObject getBean(String beanName) {returnBEAN_MAP.get(beanName);

}publicAnnotationBeanFactory(String packerName){this.packerName =packerName;//加载注解Bean

loadBean();//加载注入的属性Bean

loadInjectBean();

}/*** 加载bean到容器中*/

public voidloadBean(){//读取包名的路径

String packerPath = null;try{

packerPath=getPkgPath(packerName);

}catch(UnsupportedEncodingException e) {

logger.info("文件路径编码异常:{}",e.getMessage());throw new RuntimeException("packerName path error");

}

logger.info("扫描文件目录的路径:{}", packerPath);//查找包含Component注解的类

Map, Set>> classesMap = scanClassesByAnnotations(packerName, packerPath, true,

Arrays.asList(ServiceTest.class));if (classesMap.size() == 0){

logger.error("目录:{}下,未获取到需要加载的类", packerPath);return;

}//标记的反射对象

Set> classSet = new HashSet<>();

classesMap.forEach((k, v)->{

classSet.addAll(v);

});//默认设置类名为类名小写

for (Class>classObj:classSet){

Object object= null;try{

object=classObj.newInstance();

}catch(InstantiationException e) {throw new RuntimeException(classObj.getSimpleName()+ " create error");

}catch(IllegalAccessException e) {throw new RuntimeException(classObj.getSimpleName()+ " create error");

}

BEAN_MAP.put(StringUtils.uncapitalize(classObj.getSimpleName()),object);

}

}/*** 加载注入的Bean属性*/

public voidloadInjectBean(){

BEAN_MAP.forEach((k,v)->{

setAttributeValue(v);

});

}/*** 根据包名获取包的URL

*@parampkgName com.demo.controller

*@return

*/

public static String getPkgPath(String pkgName) throwsUnsupportedEncodingException {

String pkgDirName= pkgName.replace('.', File.separatorChar);

URL url=Thread.currentThread().getContextClassLoader().getResource(pkgDirName);return url == null ? null : URLDecoder.decode(url.getFile(), "UTF-8");

}/*** 获取指定包下包含指定注解的所有类对象的集合

*@parampkgName 包名(com.demo.controller)

*@parampkgPath 包路径(/Users/xxx/workspace/java/project/out/production/classes/com/demo/controller)

*@paramrecursive 是否递归遍历子目录

*@paramtargetAnnotations 指定注解

*@return以注解和对应类集合构成的键值对*/

public static Map, Set>>scanClassesByAnnotations(

String pkgName, String pkgPath,final booleanrecursive,

List>targetAnnotations){

Map, Set>> resultMap = new HashMap<>(16);

Collection allClassFile =getAllClassFile(pkgPath, recursive);for(File curFile : allClassFile){try{

Class> curClass =getClassObj(curFile, pkgPath, pkgName);for (Class extends Annotation>annotation : targetAnnotations){if(curClass.isAnnotationPresent(annotation)){if (!resultMap.containsKey(annotation)){

resultMap.put(annotation,new HashSet>());

}

resultMap.get(annotation).add(curClass);

}

}

}catch(ClassNotFoundException e) {

logger.error("load class fail", e);

}

}returnresultMap;

}/*** 遍历指定目录下所有扩展名为class的文件

*@parampkgPath 包目录

*@paramrecursive 是否递归遍历子目录

*@return

*/

private static Collection getAllClassFile(String pkgPath, booleanrecursive){

File fPkgDir= newFile(pkgPath);if (!(fPkgDir.exists() &&fPkgDir.isDirectory())){

logger.error("the directory to package is empty: {}", pkgPath);return null;

}return FileUtils.listFiles(fPkgDir, newString[]{EXT}, recursive);

}/*** 加载类

*@paramfile

*@parampkgPath

*@parampkgName

*@return*@throwsClassNotFoundException*/

private static Class> getClassObj(File file, String pkgPath, String pkgName) throwsClassNotFoundException{//考虑class文件在子目录中的情况

String absPath = file.getAbsolutePath().substring(0, file.getAbsolutePath().length() - EXT.length() - 1);

String className= absPath.substring(pkgPath.length()).replace(File.separatorChar, '.');

className= className.startsWith(".") ? pkgName + className : pkgName + "." +className;returnThread.currentThread().getContextClassLoader().loadClass(className);

}/*** 属性赋值

*@paramobject*/

private static voidsetAttributeValue(Object object){

Class> aClass =object.getClass();

Field[] declaredFields=aClass.getDeclaredFields();for(Field field:declaredFields){if (field.isAnnotationPresent(AutowiredTest.class)){//默认取属性值类型小写为 BeanId

String simpleName =field.getType().getSimpleName();

Object obj=BEAN_MAP.get(StringUtils.uncapitalize(simpleName));//允许私有属性赋值

field.setAccessible(true);try{

field.set(object,obj);

}catch(IllegalAccessException e) {throw new RuntimeException(field.getName() +" attribute set value exception");

}

}

}

}public static voidmain(String[] args) {

BaseFactory baseFactory= new AnnotationBeanFactory("com.spring");

BaseFactory baseFactory1= new XmlBeanFactory("/spring/test.xml");

Body body= (Body) baseFactory.getBean("body");

System.out.println("加载类:"+BaseFactory.BEAN_MAP.size()+"个");

Object apple= baseFactory.getBean("apple");

System.out.println(body);

System.out.println(apple);

Order order= newOrder();for(Field field:order.getClass().getDeclaredFields()){

System.out.println(field.getName());

System.out.println(field.getType().getSimpleName());

}

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值