LSFramework 手写山寨版 Spring 项目简介
手写山寨版 spring,学习aop、ioc思想的demo,没看过Spring的源码,因为实在是太庞大了,参考部分网上博客及开源代码完成。面向学习,不面向生产。IOC先扫描注解装配,后加载配置文件注解方式:@LSBean
public class Service {
@LSAutowired
Service2 service2;
@LSAutowired("service3")
Service3 service3;
@LSAround(Action2.class)
public void test() {
service2.test();
}
public void test2() {
service3.test3();
}
}初始化时会扫描@LSBean注解修饰的类实例化到bean容器中,必须有无参构造函数,目前需要依赖注入的类成员变量只支持@LSAutowired注解注入。 因为是先全部实例化后进行依赖注入,所以不会有循环依赖@LSConfiguration注解,会扫描LSConfiguration注解的类里的所有@LSBean注解修饰的方法,将返回值注入bean容器,方法参数是需要注入的参数, @LSAutowired标注注入的beanName,发现没法控制加载顺序,所以改成根据方法名排序后执行,所以需要控制同一个配置类里的方法执行顺序的时候方法名可定义成这样:get1XXX,get2XXX@LSConfiguration
public class TestConfig {
@LSBean
public TestConfigDI getTestConfigDI(@LSParam("service3") IService service2, Service3 service3) {
return new TestConfigDI(service2, service3);
}
}配置文件方式//beans.json
[
{
"name": "testBean2", //在bean容器中的名字
"className": "com.ls.framework.core.bean.TestBean2", //类名
"constructor": [10, "${testBean}"], //构造函数的参数,个数和顺序必须一一对应
"properties": { //成员变量,键值对结构
"val1": 1,
"val2": "123",
// "testBean": "${testBean1}"
}
}
]数组格式,${xxx}表示从bean容器中取名为xxx的bean,需要AOP强化的化必须含有无参构造函数,所以得把被依赖的bean放在上面先实例化,暂未解决循环依赖AOP@LSBean
@LSAspect(value = wdemo.webBean2")
public class Action3 extends AopAction {
@Override
public void invoke(Invocation invocation) throws Throwable {
if (invocation.getMethod().isAnnotationPresent(LSAround.class)){
return;
}
System.out.println("aop3 before");
invocation.invoke();
System.out.println("aop3 after");
}
}继承AopAction实现invoke方法并且加上@LSBean注解即可实现一个切面类实现简单的环切,调用invocation.invoke();继续执行拦截链@LSAspect注解定义被切入的类,value为包名(必填),cls为切入的类名(选填),cls为空的情况下此拦截器切入包下的所有类被切入的类必须被实例化在bean容器中@LSAround可用于类和方法之上,参数为切面类,参数为数组,可传入多个切面类,按顺序执行优先级为@LSAspect > 类级@LSAround > 方法级@LSAround@LSClear注解作用于方法上,用于清除作用于的类上的指定切面(传入需要清除的类数组)或清空切面(不传参数)JDBC可直接查询javabean, bean数组, beanList,参数只能传基本类型或者基本类型的数组、集合@LSMapper
public interface TestMapper2 {
@LSQuery("SELECT * FROM tbl_result")
List<ResultBean> selectList();
@LSQuery("SELECT count(*) FROM tbl_result")
long selectCount();
@LSQuery("SELECT * FROM tbl_result limit 1")
ResultBean selectOne();
@LSQuery("SELECT * FROM tbl_result WHERE day = ${day} limit 1")
ResultBean selectOneByDay(@LSDbParam("day")String day);
@LSQuery("SELECT * FROM tbl_result")
ResultBean[] selectArray();
@LSQuery("INSERT INTO tbl_result VALUES(${day}, ${result})")
@LSModifying
long insert(@LSDbParam("result") String result, @LSDbParam("day") String day);
@LSQuery("UPDATE tbl_result SET result=${result} WHERE day = ${day}")
@LSModifying
long update(@LSDbParam("result") String result, @LSDbParam("day") String day);
@LSQuery("UPDATE tbl_result SET result=${result} WHERE day = ${day}")
@LSModifying
void updateWithoutReturn(@LSDbParam("result") String result, @LSDbParam("day") String day);
@LSQuery("DELETE FROM tbl_result WHERE day = ${day}")
@LSModifying
long delete(@LSDbParam("day") String day);
}
public class Service {
@LSAutowired
Service2 service2;
@LSAutowired("service3")
Service3 service3;
@LSAround(Action2.class)
public void test() {
service2.test();
}
public void test2() {
service3.test3();
}
}初始化时会扫描@LSBean注解修饰的类实例化到bean容器中,必须有无参构造函数,目前需要依赖注入的类成员变量只支持@LSAutowired注解注入。 因为是先全部实例化后进行依赖注入,所以不会有循环依赖@LSConfiguration注解,会扫描LSConfiguration注解的类里的所有@LSBean注解修饰的方法,将返回值注入bean容器,方法参数是需要注入的参数, @LSAutowired标注注入的beanName,发现没法控制加载顺序,所以改成根据方法名排序后执行,所以需要控制同一个配置类里的方法执行顺序的时候方法名可定义成这样:get1XXX,get2XXX@LSConfiguration
public class TestConfig {
@LSBean
public TestConfigDI getTestConfigDI(@LSParam("service3") IService service2, Service3 service3) {
return new TestConfigDI(service2, service3);
}
}配置文件方式//beans.json
[
{
"name": "testBean2", //在bean容器中的名字
"className": "com.ls.framework.core.bean.TestBean2", //类名
"constructor": [10, "${testBean}"], //构造函数的参数,个数和顺序必须一一对应
"properties": { //成员变量,键值对结构
"val1": 1,
"val2": "123",
// "testBean": "${testBean1}"
}
}
]数组格式,${xxx}表示从bean容器中取名为xxx的bean,需要AOP强化的化必须含有无参构造函数,所以得把被依赖的bean放在上面先实例化,暂未解决循环依赖AOP@LSBean
@LSAspect(value = wdemo.webBean2")
public class Action3 extends AopAction {
@Override
public void invoke(Invocation invocation) throws Throwable {
if (invocation.getMethod().isAnnotationPresent(LSAround.class)){
return;
}
System.out.println("aop3 before");
invocation.invoke();
System.out.println("aop3 after");
}
}继承AopAction实现invoke方法并且加上@LSBean注解即可实现一个切面类实现简单的环切,调用invocation.invoke();继续执行拦截链@LSAspect注解定义被切入的类,value为包名(必填),cls为切入的类名(选填),cls为空的情况下此拦截器切入包下的所有类被切入的类必须被实例化在bean容器中@LSAround可用于类和方法之上,参数为切面类,参数为数组,可传入多个切面类,按顺序执行优先级为@LSAspect > 类级@LSAround > 方法级@LSAround@LSClear注解作用于方法上,用于清除作用于的类上的指定切面(传入需要清除的类数组)或清空切面(不传参数)JDBC可直接查询javabean, bean数组, beanList,参数只能传基本类型或者基本类型的数组、集合@LSMapper
public interface TestMapper2 {
@LSQuery("SELECT * FROM tbl_result")
List<ResultBean> selectList();
@LSQuery("SELECT count(*) FROM tbl_result")
long selectCount();
@LSQuery("SELECT * FROM tbl_result limit 1")
ResultBean selectOne();
@LSQuery("SELECT * FROM tbl_result WHERE day = ${day} limit 1")
ResultBean selectOneByDay(@LSDbParam("day")String day);
@LSQuery("SELECT * FROM tbl_result")
ResultBean[] selectArray();
@LSQuery("INSERT INTO tbl_result VALUES(${day}, ${result})")
@LSModifying
long insert(@LSDbParam("result") String result, @LSDbParam("day") String day);
@LSQuery("UPDATE tbl_result SET result=${result} WHERE day = ${day}")
@LSModifying
long update(@LSDbParam("result") String result, @LSDbParam("day") String day);
@LSQuery("UPDATE tbl_result SET result=${result} WHERE day = ${day}")
@LSModifying
void updateWithoutReturn(@LSDbParam("result") String result, @LSDbParam("day") String day);
@LSQuery("DELETE FROM tbl_result WHERE day = ${day}")
@LSModifying
long delete(@LSDbParam("day") String day);
}