自定义一个IOC框架
要实现的功能:
- 将对象的实例化交给自定的ioc容器.
- 通过注解的方式对接口进行依赖注入
- 通过getBean("userName")方法那到对象,使用对象的方法
首先,创建一个对象,定义对象的构造函数
package cn.lisongyu.ioc.demo.bean; import cn.lisongyu.ioc.annotation.Component; /**
* @author lisongyu
* @ClassName cn.lisongyu.ioc.demo.bean.UserBean
* @description userbean
* @create 2018年11月22日 11:08
*/
@Component //自定义的组件,让ioc容器扫描带有指定注解的类,将当前类装配到ioc容器中
public class UserBean { @Autowired //自定义的注入注解
private Service service; public UserBean() {
System.out.println("UserBean -> instance");
} public void getUser(){
service.test(); //接口的方法,如果注入失败,将报空指针异常
System.out.println("用户详情展示");
}
}
package cn.lisongyu.ioc.demo.a.b.c; import cn.lisongyu.ioc.annotation.Component;
import cn.lisongyu.ioc.demo.a.b.Service; /**
* @author lisongyu
* @ClassName cn.lisongyu.ioc.demo.a.b.c.TestService
* @description Service实现类
* @create 2018年11月22日 11:22
*/
@Component
public class TestService implements Service { public TestService() {
System.out.println("TestService -> instance");
} @Override
public void test() {
System.out.println("Service 接口实现方法");
}
}
package cn.lisongyu.ioc.demo.a.b; /**
* /**
*
* @author lisongyu
* @ClassName cn.lisongyu.ioc.demo.a.b.Service
* @description Service接口
* @create 2018年11月22日 17:31
*/
public interface Service { void test();
}
创建自定义的注解
package cn.lisongyu.ioc.annotation; 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) //只能注解到字段上
public @interface Autowired {
}package cn.lisongyu.ioc.annotation; 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.TYPE) //该注解指定标注的位置 TYPE:类
public @interface Component {
}
定义一个接口,用来获取bean对象的方法
package cn.lisongyu.ioc.context; /**
* /**
* Application 接口
* @author lisongyu
* @ClassName cn.lisongyu.ioc.context.Application
* @description
* @create 2018年11月22日 11:24
*/
public interface Application { Object getBean(String beanName);
}package cn.lisongyu.ioc.context; import cn.lisongyu.ioc.annotation.Component; import java.io.File;
import java.io.FileFilter;
import java.net.URL;
import java.sql.SQLOutput;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.concurrent.ConcurrentHashMap; /**
* @author lisongyu
* @ClassName cn.lisongyu.ioc.context.ApplicationImpl
* @description Application的实现类
* @create 2018年11月22日 11:24
*/
public class ApplicationImpl implements Application { //定义存放所有类对象的集合
private List<Class<?>> classList = new ArrayList<>(); //定义存放类的实例对象的集合
private Map<String,Object> instanceMap = new ConcurrentHashMap<>(); //无参构造
public ApplicationImpl() {
} /**
* 有参构造,通过传入的包路径来实现扫描
* @param basePackage
*/
public ApplicationImpl(String basePackage) {
//扫描包路径
doScan(basePackage); //实例化
doIoc(); System.out.println(instanceMap); //依赖注入
doDi();
} /**
* 实例化对象
*/
private void doIoc() {
//首先判断一下当前类集合中是否含有元素
if (classList == null){
return;
}
//遍历集合
classList.forEach((clz) ->{
try {
//通过类对象,实例化一个对象
Object instance = clz.newInstance();
//创建key
String key = getKeyName(clz.getSimpleName());
//存放到map集合中
//如果集合中存在则报错
if (instanceMap.containsKey(key)){
throw new RuntimeException("相同的类名");
}
//放入ioc容器中
instanceMap.put(key,instance);
//判断当前类是否实现了接口
Class<?>[] interfaces = clz.getInterfaces();
for (Class<?> inter : interfaces) {
instanceMap.put(inter.getName(),instance);
}
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
});
} //改名,获取一个首字母小写的类名
private String getKeyName(String simpleName) {
char[] chars = simpleName.toCharArray();
chars[0] += 32;
return String.valueOf(chars);
} //依赖注入
private void doDi() {
//首先判断实例对象是否有
if (instanceMap.size() == 0)
return;
//遍历所有的实例对象
instanceMap.forEach((k,v) -> {
Object instance = v;
//注入实体对象
Object injectionInstance = null;
//通过反射获取类对象
Class<?> clz = v.getClass();
//获取当前类对象的所有声明的字段
Field[] fields = clz.getDeclaredFields();
//循环遍历所有字段
for (Field field : fields) {
//判断字段是否含有@Autowired注解
if(field.isAnnotationPresent(Autowired.class)){
String name = field.getType().getName();
injectionInstance = this.instanceMap.get(name);
}
// 通过反射注入到该属性中
field.setAccessible(true);
try {
field.set(instance,injectionInstance);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
});
} //包扫描方法
private void doScan(String basePackage) {
//获取当前包的位置
URL resource = this.getClass().getClassLoader().getResource(basePackage.replaceAll("\\.", "/"));
//创建一个文件对象
File file = new File(resource.getPath()); //遍历文件
File[] fileNames = file.listFiles(new FileFilter() {
@Override
public boolean accept(File childFile) {
//判断当前文件是否是一个文件夹
if (childFile.isDirectory()){ //如果是文件夹,递归,获取所有的class文件
doScan(basePackage+"."+childFile.getName());
}else {
//判断当前文件是否是一个类文件
if (childFile.getName().endsWith(".class")){
String classPath = basePackage + "." + childFile.getName().replaceAll("\\.class", "");
Class<?> clz = null;
try {
clz = Class.forName(classPath);
//判断是否是有@Component注解的类
if (clz.isAnnotationPresent(Component.class)){
classList.add(clz);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} }
}
return false;
}
}); } @Override
public Object getBean(String beanName) {
return this.instanceMap.get(beanName);
}
}
运行main()
package cn.lisongyu.ioc; import cn.lisongyu.ioc.context.Application;
import cn.lisongyu.ioc.context.ApplicationImpl;
import cn.lisongyu.ioc.demo.bean.UserBean; import java.util.*; /**
* Hello world!
*
*/
public class App
{
public static void main( String[] args ) { //包路径
Application app = new ApplicationImpl("cn.lisongyu.ioc.demo"); UserBean userBean = (UserBean) app.getBean("userBean"); userBean.getUser(); } }
结果:
TestService -> instance //接口实现类的初始化
UserBean -> instance //对象类的初始化
{cn.lisongyu.ioc.demo.a.b.Service=cn.lisongyu.ioc.demo.a.b.c.TestService@4dd8dc3, testService=cn.lisongyu.ioc.demo.a.b.c.TestService@4dd8dc3, userBean=cn.lisongyu.ioc.demo.bean.UserBean@6d03e736} //装配到容器中的类
Service 接口实现方法 //service.test();
用户详情展示 //userBean.getUser();
自定义一个IOC框架的更多相关文章
- Android Afinal框架学习(二) FinalActivity 一个IOC框架
框架地址:https://github.com/yangfuhai/afinal 相应的源代码: net.tsz.afinal.annotation.view.* FinalActivity Fina ...
- 解读 IoC 框架 InversifyJS
原文链接 InversityJS 是一个 IoC 框架.IoC(Inversion of Control) 包括依赖注入(Dependency Injection) 和依赖查询(Dependency ...
- Android 玩转IOC,Retfotit源码解析,教你徒手实现自定义的Retrofit框架
CSDN:码小白 原文地址: http://blog.csdn.net/sk719887916/article/details/51957819 前言 Retrofit用法和介绍的文章实在是多的数不清 ...
- 【Android开发经验】来,咱们自己写一个Android的IOC框架!
到眼下位置.afinal开发框架也是用了好几个月了,还记得第一次使用凝视完毕控件的初始化和事件绑定的时候,当时的心情是多么的兴奋- -代码居然能够这样写!然后随着不断的学习,也慢慢的对IOC框架和注解 ...
- ASP.NET Core 6框架揭秘实例演示[28]:自定义一个服务器
作为ASP.NET Core请求处理管道的"龙头"的服务器负责监听和接收请求并最终完成对请求的响应.它将原始的请求上下文描述为相应的特性(Feature),并以此将HttpCont ...
- 轻量级IOC框架SwiftSuspenders
该框架的1.6版本位于https://github.com/tschneidereit/SwiftSuspenders/blob/the-past/,现在已经出了重新架构的2.0版本,所以我决定先研究 ...
- 轻量级IOC框架:Ninject (下)
一,创建依赖链(Chains of Dependency) 当我们向Ninject请求创建一个类型时,Ninject会去检查该类型和其他类型之间的耦合关系.如果有额外的依赖,Ninject也会解析它们 ...
- IOC框架Ninject实践总结
原文地址:http://www.cnblogs.com/jeffwongishandsome/archive/2012/04/15/2450462.html IOC框架Ninject实践总结 一.控制 ...
- 国人编写的开源 .net Ioc 框架——My.Ioc 简介
My.Ioc 是作者开发的一款开源 IoC/DI 框架,下载地址在此处.它具有下面一些特点: 高效 在实现手段上,My.Ioc 通过使用泛型.缓存.动态生成代码.延迟注册.尽量使用抽象类而非接口等方式 ...
随机推荐
- C# 类如何声明索引器以提供对类的类似数组的访问的代码
研发期间,将内容过程中比较常用的内容段做个收藏,如下内容内容是关于 C# 类如何声明索引器以提供对类的类似数组的访问.的内容,希望能对各位有用处. using System;using System. ...
- QT使用websocket进行长连接
一般我们用的最多的就是http请求,但是频繁的请求可能对服务造成的压力很大,所以今天谈谈websocket长连接,一句话:简单 1.什么是长连接? A:一次请求连接,终身使用,就可以长久的保持信息的交 ...
- c#高级编程_第10版 云盘地址
下载地址 链接:https://pan.baidu.com/s/1u8PcY4RJhRB1yfm-2XaTEQ 密码:159z
- mssql sqlserver 使用sql脚本 清空所有数据库表数据的方法分享
摘要: 下文讲述清空数据库中所有表信息的方法分享,如下所示: 实验环境:sql server 2008 实现思路: 1.禁用所有约束,外键 2.禁用所有触发器 3.删除表数据 4.开启触发器 5.开启 ...
- Asp.net mvc 项目返回Json
因mvc控制器返回类型JsonResult 在处理对象转JSON的时候,对日期的格式化处理并不太符合要求,所以重新继承抽象类ActionResult使用Newtonsoft.Json来系列化 usin ...
- SQL Server数据库————连接查询和分组查询
SQL Server数据库————连接查询和分组查询 分组查询 select 列from <表名> where …… group by 列 注意:跟order by一样group ...
- 什么是tomcat集群?
什么是tomcat集群? 利用nginx对请求进行分流,将请求分配给不同的tomcat去处理,减少每个tomcat的负载量,提高服务器的响应速度. 目标 实现高性能负载均衡的tomcat集群. 工具 ...
- SQLServer之创建Transact-SQL DDL触发器
DDL触发器原理 DDL 触发器用于响应各种数据定义语言 (DDL) 事件. 这些事件主要与以关键字 CREATE.ALTER.DROP.GRANT.DENY.REVOKE 或 UPDATE STAT ...
- SQLServer修改表数据
使用SSMS数据库管理工具修改数据 修改任意一条或者多条都可以 1:打开数据库,选择数据表,右键点击->编辑所有行(如未配置,点击编辑前200行). 2.编辑需要修改的数据->编辑完成后, ...
- Django组件--forms组件(注册用)
一.forms组件--校验类的使用 二.form组件--校验类的参数 三.forms组件校验的局部钩子--自定义校验规则(要看源码理解) 四.forms组件校验的全局钩子--校验form表单两次密码输 ...