简单实现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 ...
随机推荐
- HDU3506环形石子合并问题
HDU3506环形石子合并问题 线性的石子合并问题比较好理解,环形的转成线性的方法就是扩展数组 1 2 3 . . . n 1 2 3 ... n 依据是我们最优的取值可以是 1 --- n也能是 2 ...
- Linux Shell学习笔记:exit退出状态代码
inux提供$?特殊变量来保存最后一条命令执行结束的退出状态.执行完一条命令后,立即执行echo$?,可以查看最后一条命令的退出状态值. 正常的情况下,命令成功执行完成的退出状态是0,如果非0,则命令 ...
- [php]PHP_函数收集
//http://php.net/manual/en/control-structures.break.php //break ends execution of the current for, f ...
- jacoco初探
# 背景 集团的代码覆盖率平台因为网络问题无法使用,只能自己研究下. 覆盖率是衡量自动化用例效果产品的一个指标,但只是一个辅助指标,覆盖率高并不意味着质量好,但覆盖率低却能说明一些问题, # 对比 覆 ...
- 在 Ubuntu 16.04上安装 vsFTPd
在 Ubuntu 16.04上安装 vsFTPd Ubuntu vsFTPd 关于 vsFTPd vsFTPd 代表 Very Secure File Transfer Protocol Daemon ...
- 在ASP.NET Core中,静态类如何读取配置文件
这是今天下午一个同事问我的问题,如何在静态类中读取json配置文件.我当时并没有告诉他如何如何去做,办法肯定是有,但是这种编程思维确实得改改了.静态类.静态方法不是面向对象编程的最佳实践..NET C ...
- C# 动态创建数据库三(MySQL)
前面有说明使用EF动态新建数据库与表,数据库使用的是SQL SERVER2008的,在使用MYSQL的时候还是有所不同 一.添加 EntityFramework.dll ,System.Data.En ...
- 06_python_小数据池/ is == /编码
一.小数据池 1.代码块 python程序是由代码块构成的.一个代码块的文本作为python程序执行的单元.代码块: 一个模块, 一个函数, 一个类, 甚至每一个command命令都是一个代码块. 一 ...
- [JavaScript] Nginx实现跨域设置
假如跨域请求的接口为:http://xxx.cn/was5/web/search Nginx配置: 在conf/nginx.conf文件中 location / { root html; index ...
- springBoot的搭建使用记录
一: 首次搭建:https://blog.csdn.net/u013187139/article/details/68944972 整合mybatis: https://www.jianshu.com ...