Skip to content

aagu/TinyIOC

Repository files navigation

Tiny IOC

利用尽量少的依赖(目前依赖dom4j,cglib,aspectjweaver)实现一个支持AOP的IOC容器模仿Spring的框架,功能包括:IOC、AOP、模块化与自动配置、orm、事务、MVC支持(计划中)、web容器支持(计划中)

设计思路参考手写Spring---IOC容器(1)手写Spring---DI依赖注入(2)手写Spring---AOP面向切面编程(3)手写Spring---AOP面向切面编程(4) 在此基础上扩展支持基于xml的bean定义和基于注解的bean定义,实现bean的自动化扫描。后续将支持AOP织入(已支持)。

IOC容器功能

注意:XML方式容器已停止开发

实现的功能 注解方式 xml方式
bean扫描 [x] [x]
单例支持 [x] [x]
通过名称获取实例 [x] [x]
通过类名获取实例 [x] [x]
自定义构造、解构函数 [x] [x]
值注入 [x] [x]
依赖注入 [x] [x]
构造函数注入 [x] [x]

AOP支持

计划的功能 实现
AOP所需代理类生成 100%
基于类和方法的切点定义 100%
基于正则式的切点定义 30%(未完整测试)
切面扫描 100%
切面自动注册 100%
自动配置AOP开闭 100%

数据库支持

计划的功能 实现
自动配置数据库功能开闭 [x]
数据库连接池 部分实现
结果集映射到POJO 基本可用
基于接口的Dao层实现 [x]
SQL语句占位符 部分可用
事务支持(封装JDBC) 部分可用

注解方式设计约定

  • 默认情况下,标注@Bean或者@Config的类才能被扫描。@Bean作用在类上必须提供无参构造函数,若必须带参数,则可以在标记了@Config的类中将相应的 工厂方法标记为@Bean来定义bean,此时若@Bean注解没有提供beanName则默认使用该方法名,此种bean定义不支持通过class获取实例
  • 使用@InitMethod@DestroyMethod标记构造和解构函数
  • 使用@Wire注入依赖,你可以在接口前使用@Wire注解,容器将尝试使用标记了@Bean的对应实现类或者兼容的工厂方法去完成依赖注入
  • 使用@Value注入值,包裹在"#{}"中的定义将会从指定的property文件读取,同时可在“#{}”后添加“:default"来指定默认值(将default替换成需要的默认值),否则按照字面值解释
  • 可以通过向PropertiesApplicationContext(注解方式下默认的IOC容器)添加PackageScanner.Filter来自定义扫描过程。
  • 目前框架的自动配置器会去主动扫描的自动配置类定义在core模块的com.aagu.ioc.context.ConfigurationCenter.java,需要修改代码才能添加额外的自动配置。

xml方式设计约定

  • 所有的bean都定义在标签<container></container>
  • <bean></bean>标签中是一个bean的定义
  • name属性声明bean的名称,必须有
  • class属性声明bean的java类,必须有
  • scope属性声明bean的类型,可选属性,有singleton和prototype两种值
  • <initMethod></initMethod>标签值为java class中自定义的初始化方法,可选
  • <destroyMethod></destroyMethod>标签值为java class中自定义的销毁方法,可选
  • <property></property>标签表示bean的注入,name属性是java class中依赖的名称。ref属性声明被注入的bean的名称(与bean的声明的名称保持一致)。type表明注入值的类型,value表明注入值的真实值,这两者配合使用,且不能和ref同时使用
  • <constructor></constructor>标签表明构造函数,每个参数单独声明在<param></param>中,name属性表示参数名称,type属性表示参数类型,类注入统一标记为bean,value属性表示参数真实值(对于类注入,就是bean的名称)

数据库设计约定

要想使用数据库,需要在配置文件中声明enable-data=true,并提供数据库Url,Driver,User(可选),Password(可选)

数据库支持的设计思路参考Mybatis,Dao层接口用@Repository标识,提供@Select@Insert@Update@Delete注解,每种注解需要声明sql语句,暂不支持占位。配合@Wire注解自动注入实现类。当然也可以获取sessionFactory实例,手动执行sql,返回结果为ResultSet

数据库支持利用@Transactional声明事务,目前仅支持将一个方法中的数据库操作纳入一个事务管理,捕获异常自动回滚,否则提交。不支持嵌套事务、事务传播、隔离 级别定义。当@Transactional作用于方法时,该方法将纳入事务管理,当@Transactional作用于类时,该类声明的全部公开方法都将纳入事务管理。

编程式事务可以通过获取transactionManager这个bean手动控制

Web服务器

该项目内置的Web服务器处于非常初级的阶段,并未在开发计划中(其实就是我自己玩玩)

目前,web服务器分为webmvc两个模块,前者提供web服务器,后者提供mvc支持。web监听http请求,并封装为HttpServlet形式,调用HttpServlet接口提供的service方法响应请求。理论上讲,任何HttpServlet接口的实现类都能用来提供HTTP响应。mvc模块提供一个类似Spring MVC的框架,根据@Controller@RequestMapping注解进行路由扫描和注册,路由支持*通配和:subpath形式具名匹配,后者可以通过@PathVar注解注入到方法的入参中,另外框架支持@RequestParam注解向方法入参注入请求参数。如果需要web功能,可以通过继承TinyWebApplication快速开始。

如何使用

程序的入口定义在TinyIocApplication中,实际使用时我们需要新建一个它的子类并实现run方法,待容器初始化完成后将从此处开始运行。对于Web应用,可以通过继承TinyWebApplication类快速开始,避免手动编码开启web服务器。 同时我们的子类必须加入@Application注解,我们可以在该注解上填写basePackage指定扫描的包(默认为我们的子类所在的包)。要想使用xml方式的容器,需要在@Application注解上填写xmlLocation注明xml文件所在路径。 另外@Application还可通过property指定property文件,从文件读取值的定义。

目前仅支持注解方式的AOP使用,标记@Aspect的类将被识别为切面定义。 目前支持前置、后置、环绕和异常四种切点定义,分别使用@Before@After@Around@AfterThrow标记,并为expression参数传入AspectJ形式的匹配语法。 方法名没有限定,前置、后置和异常切点入参为JointPoint类,环绕切点入参为ProceedJointPoint。通过@Order注解添加切面顺序,数字越小优先级越高,默认为0

!!!注意:AOP默认关闭,需要在property中加入enable-aop = true手动开启

About

手写简易版IOC容器

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages