手写spring 框架——第三篇(注解的方式)

简介: 手写spring 框架——第三篇(注解的方式)

(1)注解类

package com.jd.xq.spring.annotation;
/**
 * @author
 * @Date 2019-12-27 17:05
 **/
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)//注解处理在运行时刻
@Target({ElementType.FIELD,ElementType.METHOD})//对字段和方法使用注解
public @interface YhdResource {
    String value() default "";//注解里面只能声明属性,不能声明方法,声明属性的方式比较特殊:
}

(2)使用注解类

package com.jd.xq.spring.bean;
import com.jd.xq.spring.annotation.YhdResource;
/**
 * @author
 * @Date 2019-12-27 11:54
 **/
public class Person {
    @YhdResource(value = "xq")
    private String name;
    @YhdResource(value = "12")
    private String age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getAge() {
        return age;
    }
    public void setAge(String age) {
        this.age = age;
    }
}

(3)注解解析

package com.jd.xq.spring.context;
import com.alibaba.fastjson.JSONObject;
import com.jd.xq.spring.annotation.YhdResource;
import com.jd.xq.spring.bean.BeanDefinition;
import com.jd.xq.spring.bean.PropertyDefinition;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.*;
/**
 * @author
 * @Date 2019-12-27 15:06
 **/
public class XqAnnotationClassPathXmlApplicationContext {
    private List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>();//用来存储所有的beans
    private Map<String, Object> sigletons = new HashMap<String, Object>();//用来存储实例化后的bean
    /**
     * 构造方法,用来模拟spring的行为
     *
     * @param fileName
     */
    public XqAnnotationClassPathXmlApplicationContext(String fileName) {
        try {
            //1.read xml
            this.readXml(fileName);
            //2.实例化bean
            this.instanceBeans();
            //3.注解方式
            this.annotationInject();
        } catch (Exception e) {
        }
    }
    /**
     * 根据文件名读取xml的配置文件
     */
    private void readXml(String fileName) {
        // TODO Auto-generated method stub
        //创建一个读取器
        SAXReader saxReader = new SAXReader();
        Document document = null;
        try {
            //获取要读取的配置文件的路径
            URL xmlPath = this.getClass().getClassLoader().getResource(fileName);
            //读取文件内容
            document = saxReader.read(xmlPath);
            //获取xml中的根元素
            Element rootElement = document.getRootElement();
            for (Iterator iterator = rootElement.elementIterator(); iterator.hasNext(); ) {
                Element element = (Element) iterator.next();
                String id = element.attributeValue("id");//获取bean的id属性值
                String clazz = element.attributeValue("class");//获取bean的class属性值
                BeanDefinition beanDefinition = new BeanDefinition(id, clazz);
                //获取bean的Property属性
                for (Iterator subElementIterator = element.elementIterator(); subElementIterator.hasNext(); ) {
                    Element subElement = (Element) subElementIterator.next();
                    String propertyName = subElement.attributeValue("name");
                    String propertyValue = subElement.attributeValue("value");
                    PropertyDefinition propertyDefinition = new PropertyDefinition(propertyName, propertyValue);
                    beanDefinition.getPropertyDefinitions().add(propertyDefinition);
                }
                beanDefines.add(beanDefinition);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 实例化bean
     */
    private void instanceBeans() {
        if (beanDefines != null && beanDefines.size() > 0) {
            //对每个bean进行实例化
            for (BeanDefinition beanDefinition : beanDefines) {
                try {
                    //bean的class属性存在的时候才进行实例化,否则不进行实例化
                    if (beanDefinition.getClassName() != null && !beanDefinition.getClassName().equals("")) {
                        //实例化的关键操作
                        sigletons.put(beanDefinition.getId(), Class.forName(beanDefinition.getClassName()).newInstance());
                        System.out.println("id为:" + beanDefinition.getId() + "的bean实例化成功");
                    }
                } catch (Exception e) {
                    System.out.println("bean实例化失败");
                    e.printStackTrace();
                }
            }
        }
    }
    /**
     * 注解方式注入
     * <p>
     * Administer
     * 2013-9-24 下午8:08:29
     */
    private void annotationInject() throws IllegalAccessException {
        //遍历所有的bean
        for (String beanName : sigletons.keySet()) {
            Object bean = sigletons.get(beanName);//获取需要注入的bean
            if (bean != null) {
                //再对字段进行处理,即对字段上标识有注解
                Field[] fields = bean.getClass().getDeclaredFields();//取得声明的所有字段
                for (Field field : fields) {
                    //判断字段上是否存在注解,若存在
                    if (field.isAnnotationPresent(YhdResource.class)) {
                        YhdResource resource = field.getAnnotation(YhdResource.class);//取得字段上的注解
                        //字段上存在注解,并且字段上注解的name属性不为空
                        System.out.println(JSONObject.toJSONString(field));
                        System.out.println(JSONObject.toJSONString(resource));
                        field.setAccessible(true);
                        field.set(bean, resource.value());
                    }
                }
            }
        }
    }
    public Object getBean(String beanName) {
        return sigletons.get(beanName);
    }
}

(4)使用

XqAnnotationClassPathXmlApplicationContext xqAnnotationClassPathXmlApplicationContext = new XqAnnotationClassPathXmlApplicationContext("spring.xml");
        Person person = (Person) xqAnnotationClassPathXmlApplicationContext.getBean("person");
        System.out.println(person.getName());

代码地址:

https://github.com/zhugezifang/my-spring-framework



相关文章
|
16天前
|
XML Java 测试技术
Spring IOC—基于注解配置和管理Bean 万字详解(通俗易懂)
Spring 第三节 IOC——基于注解配置和管理Bean 万字详解!
104 26
|
19天前
|
缓存 Java 数据库
SpringBoot缓存注解使用
Spring Boot 提供了一套方便的缓存注解,用于简化缓存管理。通过 `@Cacheable`、`@CachePut`、`@CacheEvict` 和 `@Caching` 等注解,开发者可以轻松地实现方法级别的缓存操作,从而提升应用的性能和响应速度。合理使用这些注解可以大大减少数据库的访问频率,优化系统性能。
169 89
|
1天前
|
前端开发 Java 数据库连接
Spring框架初识
Spring 是一个分层的轻量级开源框架,核心功能包括控制反转(IOC)和面向切面编程(AOP)。主要模块有核心容器、Spring 上下文、AOP、DAO、ORM、Web 模块和 MVC 框架。它通过 IOC 将配置与代码分离,简化开发;AOP 提供了声明性事务管理等增强功能。
33 21
Spring框架初识
|
2月前
|
Java Spring
【Spring】方法注解@Bean,配置类扫描路径
@Bean方法注解,如何在同一个类下面定义多个Bean对象,配置扫描路径
183 73
|
6天前
|
监控 Java Spring
SpringBoot:SpringBoot通过注解监测Controller接口
本文详细介绍了如何通过Spring Boot注解监测Controller接口,包括自定义注解、AOP切面的创建和使用以及具体的示例代码。通过这种方式,可以方便地在Controller方法执行前后添加日志记录、性能监控和异常处理逻辑,而无需修改方法本身的代码。这种方法不仅提高了代码的可维护性,还增强了系统的监控能力。希望本文能帮助您更好地理解和应用Spring Boot中的注解监测技术。
34 16
|
19天前
|
SQL Java 数据库连接
对Spring、SpringMVC、MyBatis框架的介绍与解释
Spring 框架提供了全面的基础设施支持,Spring MVC 专注于 Web 层的开发,而 MyBatis 则是一个高效的持久层框架。这三个框架结合使用,可以显著提升 Java 企业级应用的开发效率和质量。通过理解它们的核心特性和使用方法,开发者可以更好地构建和维护复杂的应用程序。
110 29
|
8天前
|
XML Java 开发者
通过springboot框架创建对象(一)
在Spring Boot中,对象创建依赖于Spring框架的核心特性——控制反转(IoC)和依赖注入(DI)。IoC将对象的创建和管理交由Spring应用上下文负责,开发者只需定义依赖关系。DI通过构造函数、setter方法或字段注入实现依赖对象的传递。Spring Boot的自动配置机制基于类路径和配置文件,自动为应用程序配置Spring容器,简化开发过程。Bean的生命周期包括定义扫描、实例化、依赖注入、初始化和销毁回调,均由Spring容器管理。这些特性提高了开发效率并简化了代码维护。
|
1月前
|
开发框架 运维 监控
Spring Boot中的日志框架选择
在Spring Boot开发中,日志管理至关重要。常见的日志框架有Logback、Log4j2、Java Util Logging和Slf4j。选择合适的日志框架需考虑性能、灵活性、社区支持及集成配置。本文以Logback为例,演示了如何记录不同级别的日志消息,并强调合理配置日志框架对提升系统可靠性和开发效率的重要性。
|
2月前
|
Java Spring 容器
【SpringFramework】Spring IoC-基于注解的实现
本文主要记录基于Spring注解实现IoC容器和DI相关知识。
62 21
|
2月前
|
设计模式 XML Java
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
本文详细介绍了Spring框架的核心功能,并通过手写自定义Spring框架的方式,深入理解了Spring的IOC(控制反转)和DI(依赖注入)功能,并且学会实际运用设计模式到真实开发中。
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能