您的位置:首页 > 房产 > 建筑 > 标准的网络推广计划书的目录_南京网站设计制作_关键词排名优化怎么做_投广告的平台有哪些

标准的网络推广计划书的目录_南京网站设计制作_关键词排名优化怎么做_投广告的平台有哪些

2024/12/23 9:17:34 来源:https://blog.csdn.net/2301_80295548/article/details/143349438  浏览:    关键词:标准的网络推广计划书的目录_南京网站设计制作_关键词排名优化怎么做_投广告的平台有哪些
标准的网络推广计划书的目录_南京网站设计制作_关键词排名优化怎么做_投广告的平台有哪些

一、概述

主要是通过仿照Beanfactory的思想,利用反射来实现一个非常简单的ioc容器。大体思想为:

  1. 自定义注解
  2. 实现ioc容器的管理功能,通过识别注解标识的类,利用反射创建对象并加入beanfactory中
  3. 实现依赖注入,为容器中对象,若其属性有注解标示,则为其赋值

以上就是大体的思路了,我们在实现的时候只关注核心功能,一些细节之处便不再关注,如异常处理,这里便直接throws Exception了

二、创建注解

我们首先创建两个注解,@Bean@di分别用于表示bean的管理和依赖的注入

  • @Bean
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Bean {
}
  • @di
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Di {
}

这里面有几个要注意的点:

@Target表示注解作用的范围,ElementType.TYPE和ElementType.FIELD分别表示作用于类本身和类的字段上。

@ 是 Java 注解的一个元注解,用于指定注解的保留策略。RetentionPolicy 枚举类型定义了注解的保留策略,有三种可能的值:

  1. SOURCE:注解仅保留在源代码级别,编译时会被丢弃,不会出现在字节码中。
  2. CLASS:注解会保留在编译后的字节码中,但在运行时不可见(即无法通过反射获取)。
  3. RUNTIME:注解会保留在编译后的字节码中,并且在运行时可以通过反射获取

三、创建父接口ApplicationContext

核心功能就一个,根据传入的类的class对象获得bean

public interface ApplicationContext {Object getBean(Class clazz);
}

四、创建实现类,实现主要的功能

  • 首先是有两个属性,beanFactory是最核心的一个字段,存储了类class对象和类对象的一个映射。BasePath存储的是类的绝对路径的前半部分,主要是便于后续操作。
  • 通过有参构造,传入包的全路径,表示扫描该包及其子包中的类。
public class AnnotationApplicationContext implements ApplicationContext {public   Map<Class,Object> beanFactory=new HashMap<Class,Object>();private  String BasePath;public AnnotationApplicationContext(String basePackage) throws Exception {}public Object getBean(Class clazz) {return beanFactory.get(clazz);}
}
  • 现在来具体实现以下步骤
    • 将传入包的类路径转换成文件资源的绝对路径
    • 扫描该路径下的资源,找到.class文件
    • 判断是否携带有注解,有则创建对象,加入beanFactory中
public AnnotationApplicationContext(String basePackage) throws Exception {//替换包包路径中中的.为\,注意要进行转义String basePackagePath = basePackage.replaceAll("\\.", "\\\\");//获得绝对路径Enumeration<URL> resources= Thread.currentThread().getContextClassLoader().getResources(basePackagePath);while (resources.hasMoreElements()) {URL url = resources.nextElement();//这里有一个细节,由于我们之前将.替换为了\,此时的\为编码值,还未进行解码String absolutePath = URLDecoder.decode(url.getFile(), "UTF-8");BasePath=absolutePath.substring(0,absolutePath.length()-basePackagePath.length());//传入该路径的File对象,后续核心代码在loadBean中进行,避免构造函数冗余loadBean(new File(absolutePath));}loadDi();
}private void loadBean(File baseFile) throws Exception {//判断是否为文件夹if(baseFile.isDirectory()){//获取子资源File[] childFiles = baseFile.listFiles();for (File childFile : childFiles) {//如果与子资源也是一个文件夹,就继续递归调用if(childFile.isDirectory()){loadBean(childFile);}else if(childFile==null||childFile.length()==0){return;}else{//此时为不空的文件资源String absolutePath = childFile.getAbsolutePath();//判断是否为.class文件if(!absolutePath.endsWith(".class")){return;}//拿到类的全名称String classPath = absolutePath.substring(BasePath.length() - 1).replaceAll(".class","").replaceAll("\\\\",".");Class clazz = Class.forName(classPath);//获得非接口带注解的类对象if(clazz.isInterface()){return;}Annotation annotation = clazz.getAnnotation(Bean.class);if(annotation==null){return;}Object o = clazz.getDeclaredConstructor().newInstance();//判断其是否实现有接口,有的话默认以第一个接口作为map的keyClass[] interfaces = clazz.getInterfaces();if(interfaces!=null){beanFactory.put(interfaces[0],o);}else{beanFactory.put(clazz,o);}}}}
}
  • 实现依赖注入功能

    这个就比较简单了,大体思路是先遍历beanFactory中的对象,再判断每个类对象的属性中是否有@Di注解,有则为其赋值

private void loadDi() throws Exception{//遍历map集合for (Map.Entry<Class, Object> beanEntry : beanFactory.entrySet()) {//获取类对象,然后通过对象获得它的class对象,再通过反射获得其所有的字段Class beanClazz= beanEntry.getValue().getClass();for (Field field : beanClazz.getDeclaredFields()) {//判断是否有注解Di di = field.getAnnotation(Di.class);if (di != null) {//设置访问权限field.setAccessible(true);//field.getType()获得该字段的class对象,再通过beanFactory进行赋值field.set(beanEntry.getValue(),beanFactory.get(field.getType()));}}}
}

五、小结

以上便是对spring中ioc容器的一个简易的实现,总的来说还是比较简单,就是利用反射技术。大家可以先理清思路,再写一遍会更加清晰。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com