简单实现Spring框架--注解版
自己写的Spring框架——简单实现IoC容器功能
前几天在网上看了篇帖子,是用xml的方式实现spring的ioc容器,觉得挺有意思的,这边自己试着用注解的形式造了一套轮子。
工程结构

codeing
ScopeType.java
package xyz.tmlh.type; import org.apache.commons.lang.StringUtils; /**
* <p>
* Description: bean的作用域
* </p>
*/
public enum ScopeType { /**
* 原型
*/
PROTOTYPE, /**
* 单例
*/
SINGLETON; public static ScopeType getScopt(String name){
if(StringUtils.equalsIgnoreCase(name, PROTOTYPE.toString())) {
return PROTOTYPE;
}
return SINGLETON;
}
}
Bean.java
/*
* $Id: Bean.java, 2019年1月15日 下午4:07:10 TianXin Exp $
*
* Copyright (c) 2018 Vnierlai Technologies Co.,Ltd
* All rights reserved.
*
* This software is copyrighted and owned by Vnierlai or the copyright holder
* specified, unless otherwise noted, and may not be reproduced or distributed
* in whole or in part in any form or medium without express written permission.
*/
package xyz.tmlh.annotation; import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import xyz.tmlh.type.ScopeType; /**
* <p>
* Description:
* </p>
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Bean { String name() default ""; ScopeType scope() default ScopeType.SINGLETON; }
Configuration.java
package xyz.tmlh.annotation; import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; /**
* <p>
* Description: 用来标注这是一个配置类
* </p>
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Configuration { String value() default ""; }
AnnotationConfigMange.java
package xyz.tmlh.config; import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map; import org.apache.commons.lang.StringUtils; import xyz.tmlh.annotation.Bean;
import xyz.tmlh.annotation.Configuration;
import xyz.tmlh.entity.Property;
import xyz.tmlh.type.ScopeType; public class AnnotationConfigMange{ /**
* 读取配置文件并返回读取结果
* 返回Map集合便于注入,key是每个Bean的name属性,value是对应的那个Bean对象
* @throws InvocationTargetException
* @throws IllegalArgumentException
* @throws IllegalAccessException
*/
public Map<String, xyz.tmlh.entity.Bean> getConfig(Class<?> clazz) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Map<String, xyz.tmlh.entity.Bean> map = new HashMap<String, xyz.tmlh.entity.Bean>(); if(!isExistAnnotation(clazz.getAnnotations())) {
throw new RuntimeException("not found annotation Configuration");
}
//获取类中的所有方法
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
Bean beanMethod = method.getAnnotation(Bean.class);
if(beanMethod != null) {
xyz.tmlh.entity.Bean bean = new xyz.tmlh.entity.Bean();
bean.setId(method.getName());
try {
Object newInstance = clazz.newInstance();
bean.setObj( method.invoke(newInstance, null));
bean.setScope(beanMethod.scope());
if(StringUtils.isEmpty(beanMethod.name())) {
map.put(method.getName(), bean);
}else {
map.put(beanMethod.name(), bean);
} } catch (InstantiationException e) {
e.printStackTrace();
}
}
}
return map;
} private boolean isExistAnnotation(Annotation[] annotations){
for (Annotation annotation : annotations) {
if(Configuration.class == annotation.annotationType()) {
return true;
}
}
return false;
} }
接口BeanFactory继承图

BeanFactory.java
public interface BeanFactory {
Object getBean(String name);
<T>T getBean(Class<T> clazz) throws Exception;
Object createBean(Bean bean);
}
AbstractBeanFactoryHandler.java
package xyz.tmlh.support; import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry; import xyz.tmlh.entity.Bean;
import xyz.tmlh.type.ScopeType; public abstract class AbstractBeanFactoryHandler implements BeanFactory{ /**
* 获得读取的配置文件中的Map信息
*/
protected Map<String, Bean> map; /**
* 作为IOC容器使用,放置spring放置的对象
*/
protected Map<String, Object> context = new HashMap<String, Object>(); public Object createBean(Bean bean) {
// 创建该类对象
Object obj = bean.getObj();
if (obj == null) {
throw new RuntimeException(bean.getClassName() + "not found");
}
return obj;
} @Deprecated
public <T>T getBean(Class<T> clazz) throws Exception {
throw new RuntimeException("Please use the method getBean(String beanNme)!");
} @Deprecated
public Object getBean(String name) {
Object bean = context.get(name);
// 如果为空说明scope不是singleton,那么容器中是没有的,这里现场创建
if (bean == null) {
throw new RuntimeException("Named is " + name + " cannot be found in the ioc!");
}
return bean;
} }
AnnotationConfigApplicationContext.java
package xyz.tmlh.support; import java.util.Map.Entry; import org.apache.commons.beanutils.BeanUtils; import xyz.tmlh.config.AnnotationConfigMange;
import xyz.tmlh.entity.Bean;
import xyz.tmlh.type.ScopeType; /**
* <p>
* Description: 注解版启动
* </p>
*/
public class AnnotationConfigApplicationContext extends AbstractBeanFactoryHandler { public AnnotationConfigApplicationContext(Class<?> clazz) throws Exception {
AnnotationConfigMange configManager = new AnnotationConfigMange();
// 1.读取配置文件得到需要初始化的Bean信息
map = configManager.getConfig(clazz);
// 2.遍历配置,初始化Bean
init();
} public void init() {
for (Entry<String, Bean> en : map.entrySet()) {
String beanName = en.getKey();
Bean bean = en.getValue(); Object existBean = context.get(beanName);
// 当容器中为空并且bean的scope属性为singleton时
if (existBean == null && bean.getScope().equals(ScopeType.SINGLETON)) {
// 根据字符串创建Bean对象
Object beanObj = createBean(bean);
// 把创建好的bean对象放置到map中去
context.put(beanName, beanObj);
}
}
} @SuppressWarnings("unchecked")
public <T> T getBean(Class<T> clazz) throws Exception {
T bean = null;
int n = 0;
for (Entry<String, Object> entry : context.entrySet()) {
if (entry.getValue().getClass() == clazz) {
bean = (T)entry.getValue();
n++;
}
}
if (n == 2) {
throw new RuntimeException("容器中存在多个" + clazz.getSimpleName());
}
if (n == 0) {
for (Entry<String, Bean> entry : map.entrySet()) {
if (entry.getValue().getObj().getClass() == clazz) {
if (entry.getValue().getScope().equals(ScopeType.PROTOTYPE)) {
T newInstance = (T)entry.getValue().getObj().getClass().newInstance();
BeanUtils.copyProperties(newInstance, entry.getValue().getObj());
return newInstance;
}
return (T)entry.getValue().getObj();
}
}
throw new RuntimeException("ioc not found " + clazz.getName());
} return bean;
} }
测试的代码就不发了
这里贴上github地址有兴趣的可以看看: https://github.com/tmlh98/start-work-series/tree/master/MySpring
简单实现Spring框架--注解版的更多相关文章
- 搭建简单的Spring框架
1.Spring框架相关jar包下载地址http://repo.springsource.org/libs-release-local/org/springframework/spring,复制,进入 ...
- JavaWeb_(Spring框架)注解配置
系列博文 JavaWeb_(Spring框架)xml配置文件 传送门 JavaWeb_(Spring框架)注解配置 传送门 Spring注解配置 a)导包和约束:基本包.aop包+context约束 ...
- spring mvc注解版01
spring mvc是基于servlet实现的在spring mvc xml版中已经说过了,注解版相较于xml版更加简洁灵活. web项目的jar包: commons-logging-1.1.3.ja ...
- Spring 定时任务 注解版
Task类: ManageSql.Java对应代码: package com.axb.cheney.task; import java.sql.ResultSet; import java.sql.S ...
- spring中整合ssm框架注解版
和xml版差不多,只不过创建对象的方式是由spring自动扫描包名,然后命名空间多一行context代码在application.xml中,然后将每个对象通过注解创建和注入: 直接上代码: 1.use ...
- spring mvc简单的demo(注解版)
tomcat配置文件:web.xml <?xml version="1.0" encoding="UTF-8"? > <web-app ver ...
- 课程5:Spring框架2016版视频--视频列表目录
\day01视频\01-今天内容介绍.avi; \day01视频\02-spring的相关概念.avi; \day01视频\03-spring的ioc底层原理(一).avi; \day01视频\04- ...
- 菜鸟学习Spring——SpringMVC注解版前台向后台传值的两种方式
一.概述. 在很多企业的开法中常常用到SpringMVC+Spring+Hibernate(mybatis)这样的架构,SpringMVC相当于Struts是页面到Contorller直接的交互的框架 ...
- 【Spring】简单的Spring AOP注解示例
引入相关包: <properties> <spring.version>3.0.5.RELEASE</spring.version> <aspectj.ver ...
随机推荐
- 数组中超过N分之一的数字
寻找数组中超过一半的元素,这是一道十分经典和普遍的面试题了,实现起来比较容易,只是需要写技巧,将问题扩展就可以衍生到求数组中几个超过N分一的元素,例如找出数组中3个出现次数超过1/4的元素. /*** ...
- IT项目管理流程以及每个步骤用到的文档
IT项目管理从大的方面可分为:1)项目启动阶段:2)项目计划阶段:3)项目的实施阶段:4)项目的结项阶段 1)项目启动阶段: 1.项目启动流程规范: 1.1项目启动的简介.目的和范围 1.2目的可行性 ...
- iOS 使用代码创建约束,实现自动布局
///与下面约束对象属性截图相对应//使用Auto Layout约束,禁止将Autoresizing Mask转换为约束 [self.funcView setTranslatesAutoresizin ...
- 使用nohup后台执行ftp传输命令
因为有的时候会需要长时间传输文件,所以想用nohup 结合shell脚本一起使用,就不用一直在电脑面前了 . nohup 用法: nohup command & 然后就会出现 对应的 pid ...
- [leet code 198]House Robber
1 题目 You are a professional robber planning to rob houses along a street. Each house has a certain a ...
- SQL Server nested loop join 效率试验
从很多网页上都看到,SQL Server有三种Join的算法, nested loop join, merge join, hash join. 其中最常用的就是nested loop join. 在 ...
- 解决SHAREJPOINT 跨域问题
目前仅支持IE7/8不支持IE11和谷歌 对于跨域情况,目前找到如果jquery是get获取方式,可以配置web.config相关属性,具体powershell命令如下: Add-PSSnapin M ...
- dubbo实现原理之SPI简介
dubbo采用微内核+插件体系,设计优雅,扩展性很强.微内核+插件体系是如何实现的呢?想必大家都知道SPI(service provider interface)机制.这种机制的原理是假如我们定义了服 ...
- Linq to xml修改CDATA节点值
增加节点时,我们是这样写的: xop.Document.Element("messages").Add( new XElement("message", new ...
- zabbix 监控安装
注意:此篇是在安装好lnmp环境后才能部署的操作,所以,做之前准备好lnmp环境,或者可以参考我做的lnmp环境,之后接着此篇开始安装 监控系统Zabbix-3.2.1的安装 zabbix-serve ...