├── .classpath
├── .project
├── .settings
├── org.eclipse.core.resources.prefs
├── org.eclipse.jdt.core.prefs
└── org.eclipse.m2e.core.prefs
├── README.md
├── pom.xml
├── src
└── main
│ ├── java
│ └── com
│ │ └── wang
│ │ ├── demo
│ │ ├── Application.java
│ │ ├── configuration
│ │ │ └── JedisConfig.java
│ │ ├── controller
│ │ │ └── TestController.java
│ │ ├── dao
│ │ │ └── UserMapper.java
│ │ ├── interceptor
│ │ │ └── Interceptor.java
│ │ ├── model
│ │ │ ├── JedisFake.java
│ │ │ ├── ResponseEntity.java
│ │ │ ├── User.java
│ │ │ └── UserRequest.java
│ │ └── service
│ │ │ ├── IUserService.java
│ │ │ ├── UserService.java
│ │ │ └── UserService2.java
│ │ ├── mybatis
│ │ ├── annotation
│ │ │ ├── Delete.java
│ │ │ ├── Insert.java
│ │ │ ├── Mapper.java
│ │ │ ├── Param.java
│ │ │ ├── Select.java
│ │ │ └── Update.java
│ │ ├── constant
│ │ │ └── SqlTypeConstant.java
│ │ ├── core
│ │ │ ├── CGLibMapperProxy.java
│ │ │ ├── MapperHelper.java
│ │ │ ├── MethodDetails.java
│ │ │ ├── SqlResultCache.java
│ │ │ └── SqlSource.java
│ │ ├── datasource
│ │ │ ├── DataSource.java
│ │ │ ├── NormalDataSource.java
│ │ │ └── PoolDataSource.java
│ │ ├── executor
│ │ │ ├── Executor.java
│ │ │ ├── ExecutorFactory.java
│ │ │ └── SimpleExecutor.java
│ │ ├── handler
│ │ │ ├── PreparedStatementHandler.java
│ │ │ └── ResultSetHandler.java
│ │ └── transaction
│ │ │ ├── SimpleTransactionManager.java
│ │ │ ├── TransactionFactory.java
│ │ │ ├── TransactionManager.java
│ │ │ └── TransactionStatus.java
│ │ └── spring
│ │ ├── annotation
│ │ ├── aop
│ │ │ ├── After.java
│ │ │ ├── AfterReturning.java
│ │ │ ├── AfterThrowing.java
│ │ │ ├── Around.java
│ │ │ ├── Aspect.java
│ │ │ ├── Before.java
│ │ │ ├── Pointcut.java
│ │ │ └── Transactional.java
│ │ ├── ioc
│ │ │ ├── Autowired.java
│ │ │ ├── Bean.java
│ │ │ ├── Component.java
│ │ │ ├── Configuration.java
│ │ │ ├── Qualifier.java
│ │ │ ├── Resource.java
│ │ │ ├── Service.java
│ │ │ └── Value.java
│ │ └── mvc
│ │ │ ├── Controller.java
│ │ │ ├── PathVariable.java
│ │ │ ├── RequestBody.java
│ │ │ ├── RequestMapping.java
│ │ │ ├── RequestParam.java
│ │ │ └── ResponseBody.java
│ │ ├── aop
│ │ ├── AOPHelper.java
│ │ ├── Advice.java
│ │ ├── CGLibProxy.java
│ │ └── JoinPoint.java
│ │ ├── common
│ │ └── MyProxy.java
│ │ ├── constants
│ │ ├── AdviceTypeConstant.java
│ │ ├── BeanScope.java
│ │ ├── ConfigConstant.java
│ │ ├── IsolationLevelConstant.java
│ │ ├── PropagationLevelConstant.java
│ │ └── RequestMethod.java
│ │ ├── ioc
│ │ ├── BeanDefinition.java
│ │ ├── BeanDefinitionRegistry.java
│ │ ├── BeanFactory.java
│ │ ├── ClassSetHelper.java
│ │ ├── DefaultBeanFactory.java
│ │ ├── GenericBeanDefinition.java
│ │ └── ObjectFactory.java
│ │ ├── mvc
│ │ ├── DispatcherServlet.java
│ │ ├── Handler.java
│ │ ├── HandlerAdapter.java
│ │ ├── ModelAndView.java
│ │ ├── Request.java
│ │ └── ResultResolverHandler.java
│ │ ├── tomcat
│ │ └── TomcatServer.java
│ │ └── utils
│ │ ├── ClassUtil.java
│ │ ├── ConfigUtil.java
│ │ ├── PropsUtil.java
│ │ └── ReflectionUtil.java
│ └── resources
│ ├── WEB-INF
│ └── view
│ │ ├── login_failed.html
│ │ └── login_sucess.html
│ └── application.properties
└── target
└── classes
├── WEB-INF
└── view
│ ├── login_failed.html
│ └── login_sucess.html
├── application.properties
└── com
└── wang
├── demo
├── Application.class
├── configuration
│ └── JedisConfig.class
├── controller
│ └── TestController.class
├── dao
│ └── UserMapper.class
├── interceptor
│ └── Interceptor.class
├── model
│ ├── JedisFake.class
│ ├── ResponseEntity.class
│ ├── User.class
│ └── UserRequest.class
└── service
│ ├── IUserService.class
│ ├── UserService.class
│ └── UserService2.class
├── mybatis
├── annotation
│ ├── Delete.class
│ ├── Insert.class
│ ├── Mapper.class
│ ├── Param.class
│ ├── Select.class
│ └── Update.class
├── constant
│ └── SqlTypeConstant.class
├── core
│ ├── CGLibMapperProxy.class
│ ├── MapperHelper.class
│ ├── MethodDetails.class
│ ├── SqlResultCache.class
│ └── SqlSource.class
├── datasource
│ ├── DataSource.class
│ ├── NormalDataSource.class
│ └── PoolDataSource.class
├── executor
│ ├── Executor.class
│ ├── ExecutorFactory.class
│ └── SimpleExecutor.class
├── handler
│ ├── PreparedStatementHandler.class
│ └── ResultSetHandler.class
└── transaction
│ ├── SimpleTransactionManager.class
│ ├── TransactionFactory.class
│ ├── TransactionManager.class
│ └── TransactionStatus.class
└── spring
├── annotation
├── aop
│ ├── After.class
│ ├── AfterReturning.class
│ ├── AfterThrowing.class
│ ├── Around.class
│ ├── Aspect.class
│ ├── Before.class
│ ├── Pointcut.class
│ └── Transactional.class
├── ioc
│ ├── Autowired.class
│ ├── Bean.class
│ ├── Component.class
│ ├── Configuration.class
│ ├── Qualifier.class
│ ├── Resource.class
│ ├── Service.class
│ └── Value.class
└── mvc
│ ├── Controller.class
│ ├── PathVariable.class
│ ├── RequestBody.class
│ ├── RequestMapping.class
│ ├── RequestParam.class
│ └── ResponseBody.class
├── aop
├── AOPHelper$1.class
├── AOPHelper.class
├── Advice.class
├── CGLibProxy.class
└── JoinPoint.class
├── common
└── MyProxy.class
├── constants
├── AdviceTypeConstant.class
├── BeanScope.class
├── ConfigConstant.class
├── IsolationLevelConstant.class
├── PropagationLevelConstant.class
└── RequestMethod.class
├── ioc
├── BeanDefinition.class
├── BeanDefinitionRegistry.class
├── BeanFactory.class
├── ClassSetHelper.class
├── DefaultBeanFactory$1.class
├── DefaultBeanFactory.class
├── GenericBeanDefinition.class
└── ObjectFactory.class
├── mvc
├── DispatcherServlet.class
├── Handler.class
├── HandlerAdapter.class
├── ModelAndView.class
├── Request.class
└── ResultResolverHandler.class
├── tomcat
└── TomcatServer.class
└── utils
├── ClassUtil$1.class
├── ClassUtil.class
├── ConfigUtil.class
├── PropsUtil.class
└── ReflectionUtil.class
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | MySpringImpl
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 | org.eclipse.m2e.core.maven2Builder
15 |
16 |
17 |
18 |
19 |
20 | org.eclipse.jdt.core.javanature
21 | org.eclipse.m2e.core.maven2Nature
22 |
23 |
24 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.core.resources.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | encoding//src/main/java=UTF-8
3 | encoding//src/main/resources=UTF-8
4 | encoding//src/main/resources/WEB-INF/view/login_sucess.html=UTF-8
5 | encoding//src/main/resources/application.properties=UTF-8
6 | encoding//src/test/java=UTF-8
7 | encoding//src/test/resources=UTF-8
8 | encoding/=UTF-8
9 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
3 | org.eclipse.jdt.core.compiler.compliance=1.8
4 | org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
5 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
6 | org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
7 | org.eclipse.jdt.core.compiler.release=disabled
8 | org.eclipse.jdt.core.compiler.source=1.8
9 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.m2e.core.prefs:
--------------------------------------------------------------------------------
1 | activeProfiles=
2 | eclipse.preferences.version=1
3 | resolveWorkspaceProjects=true
4 | version=1
5 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 手写简易版仿Springboot框架,实现了IOC,AOP,MVC,Mybatis等模块,此外还实现事务管理,能够连接外置Jedis,Kafka等客户端,内嵌了tomcat服务器和Freemarker解析器,可进行简单的增删改查和实现动态页面。所有注解基本和Springboot的一毛一样,不需要进行XML配置,简单易用,代码简单结构清晰,有比较详细的代码注释。
2 |
3 | 1.实现了IOC容器和依赖注入,用单例模式实现Bean工厂类,通过反射自动进行Service,Component,Controller类的自动生成和注入,通过三级缓存解决了循环依赖问题,有多种注解方式进行注入,@Autowired,@Qualifier,@Resource的语义和用法与Spring的一样,此外还实现了@Configuration中的配置的Bean的自动注入,通过手动配置能够连接外部Jedis,Kafka等客服端。
4 |
5 | 2.通过CGLib动态代理实现了AOP(面向切面编程),使用注解来配置切面,有@Before,@After,@Around,@Afterthrowing,@AfterReturning等多种通知,可通过@Pointcut配置切点。能实现对同一个方法的多次增强,并通过通知的order变量配置增强的顺序。通过动态代理还实现了Spring的事务管理,在类或者方法上加上@Transactional即可获得事务管理功能,可配置事务的四种隔离级别、回滚异常类和六种传播行为(Propagation.NESTED仍存在问题),使用ThreadLocal缓存连接和ThreadLocal>缓存上级事务连接来实现事务的传播行为,并保证事务中的操作获取到的是同一个连接,可进行事务提交,出错时自动进行事务回滚。
6 |
7 | 3.MVC模块实现了DispatcherServlet解析和处理请求的主要流程,能够从HttpServletRequest对@RequestParam,@PathVariable,@RequestBody等注解的方法参数进行解析,能够实现HandlerMapping和HanderAdapter的初始化,请求到来时将请求映射为hander后,通过handerAdapter来实际处理请求,handerAdapter对请求处理完成之后根据实际返回的类型来进行解析,并返回给用户;如果有@ResponseBody则解析为Json字符串返回,如果返回一个ModelAndView对象,则使用内置的Freemarker解析器进行解析,解析渲染之后将html页面返回给用户。
8 |
9 | 4.实现了类似于Mybatis的功能,通过在@Mapper声明的接口上使用注解@Select,@Update,@Insert,@Delete来方法上声明要执行的sql语句,就可以通过动态代理来生成实际的代理对象,通过调用Executor来执行实际的Sql语句,生成的代理对象通过IOC容器也可以自动注入到其他对象的属性中。Sql语句的参数的注入使用了#{ }和${ }两种方式,语义和Mybatis的一样。通过JDBC来进行低层的数据库连接,通过阻塞队列实现了内置的数据库连接池,可配置是否使用。实现了查询结果集ResultSet到实际对象或对象列表的映射,能自动进行基本数据类型和包装类型属性的注入。通过TransactionManager来进行连接的获取的事务的实现,可进行事务隔离级别的配置,与AOP中的代理工厂配合使用实现事务管理。
10 |
11 |
12 |
13 | 包的说明:
14 | com.wang.spring包下实现了Spring的IOC,AOP,MVC的功能模块;
15 | com.wang.mybatis包下实现了仿Mybatis的功能模块,可通过注解进行数据库增删改查,完成对象关系映射;
16 | com.wang.demo包下是一个简单的通过mysql和redis实现的注册登录例子。
17 |
18 | 例子运行方法:
19 | 1.修改resources下的application.properties配置文件,修改数据库的url,账号,密码的配置,修改com.wang.demo.configuration包下的Jedis Bean的手动配置。
20 | 2.在数据库中生成表,字段名和类型见User类,字段名一定要相等。(后续会增加别名功能)
21 | 3.启动主类Application.java,使用postman进行接口测试。
22 |
23 |
24 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 | com.wang
4 | MySpringImpl
5 | 0.0.1-SNAPSHOT
6 |
7 |
8 | UTF-8
9 |
10 |
11 |
12 |
13 |
14 | javax.servlet
15 | javax.servlet-api
16 | 3.1.0
17 | provided
18 |
19 |
20 | redis.clients
21 | jedis
22 | 3.1.0
23 |
24 |
25 |
26 | org.freemarker
27 | freemarker
28 | 2.3.28
29 |
30 |
31 |
32 | javax.servlet.jsp
33 | jsp-api
34 | 2.2
35 | provided
36 |
37 |
38 |
39 | javax.servlet
40 | jstl
41 | 1.2
42 | runtime
43 |
44 |
45 |
46 | mysql
47 | mysql-connector-java
48 | 5.1.33
49 |
50 |
51 |
52 | org.apache.commons
53 | commons-dbcp2
54 | 2.0.1
55 |
56 |
57 |
58 | commons-dbutils
59 | commons-dbutils
60 | 1.6
61 |
62 |
63 |
64 | org.slf4j
65 | slf4j-log4j12
66 | 1.7.7
67 |
68 |
69 |
70 | cglib
71 | cglib
72 | 2.2.2
73 |
74 |
75 |
76 | org.apache.commons
77 | commons-lang3
78 | 3.3.2
79 |
80 |
81 |
82 | org.apache.commons
83 | commons-collections4
84 | 4.0
85 |
86 |
87 |
88 | com.alibaba
89 | fastjson
90 | 1.2.49
91 |
92 |
93 | org.apache.tomcat.embed
94 | tomcat-embed-core
95 | 8.0.32
96 |
97 |
98 |
99 | org.apache.tomcat.embed
100 | tomcat-embed-jasper
101 | 8.0.32
102 |
103 |
104 | org.apache.tomcat.embed
105 | tomcat-embed-logging-juli
106 | 8.0.32
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 | org.apache.maven.plugins
116 | maven-compiler-plugin
117 | 3.3
118 |
119 | 1.8
120 | 1.8
121 |
122 |
123 |
124 |
125 | org.apache.maven.plugins
126 | maven-surefire-plugin
127 | 2.18.1
128 |
129 | true
130 |
131 |
132 |
133 |
134 |
--------------------------------------------------------------------------------
/src/main/java/com/wang/demo/Application.java:
--------------------------------------------------------------------------------
1 | package com.wang.demo;
2 |
3 | import org.apache.catalina.LifecycleException;
4 | import com.wang.spring.tomcat.TomcatServer;
5 |
6 | public class Application {
7 |
8 | public static void main(String[] args) {
9 | TomcatServer tomcatServer = new TomcatServer(args);
10 | try {
11 | tomcatServer.startServer();
12 | } catch (LifecycleException e) {
13 | e.printStackTrace();
14 | }
15 |
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/wang/demo/configuration/JedisConfig.java:
--------------------------------------------------------------------------------
1 | package com.wang.demo.configuration;
2 | import com.wang.spring.annotation.ioc.Bean;
3 | import com.wang.spring.annotation.ioc.Configuration;
4 |
5 | import redis.clients.jedis.Jedis;
6 | import redis.clients.jedis.JedisPool;
7 | import redis.clients.jedis.JedisPoolConfig;
8 |
9 | @Configuration
10 | public class JedisConfig {
11 | @Bean
12 | public Jedis getJedis() {
13 | JedisPoolConfig config = new JedisPoolConfig();
14 | config.setMaxTotal(100);
15 | config.setMaxIdle(50);
16 | config.setMinIdle(10);
17 | //设置连接时的最大等待毫秒数
18 | config.setMaxWaitMillis(10000);
19 | //设置在获取连接时,是否检查连接的有效性
20 | config.setTestOnBorrow(true);
21 | //设置释放连接到池中时是否检查有效性
22 | config.setTestOnReturn(true);
23 |
24 | //在连接空闲时,是否检查连接有效性
25 | config.setTestWhileIdle(true);
26 |
27 | //两次扫描之间的时间间隔毫秒数
28 | config.setTimeBetweenEvictionRunsMillis(30000);
29 | //每次扫描的最多的对象数
30 | config.setNumTestsPerEvictionRun(10);
31 | //逐出连接的最小空闲时间,默认是180000(30分钟)
32 | config.setMinEvictableIdleTimeMillis(60000);
33 | String redisHost = "" ;//Jedis服务器地址
34 | Integer port = 6379;
35 | String password = "";
36 | Jedis resource = new JedisPool(config, redisHost, 6379, 30000, password, 0).getResource();
37 | return resource;
38 | }
39 |
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/com/wang/demo/controller/TestController.java:
--------------------------------------------------------------------------------
1 | package com.wang.demo.controller;
2 |
3 | import com.wang.demo.model.ResponseEntity;
4 | import com.wang.demo.model.User;
5 | import com.wang.demo.model.UserRequest;
6 | import com.wang.demo.service.IUserService;
7 | import com.wang.demo.service.UserService;
8 | import com.wang.spring.annotation.ioc.Autowired;
9 | import com.wang.spring.annotation.mvc.Controller;
10 | import com.wang.spring.annotation.mvc.PathVariable;
11 | import com.wang.spring.annotation.mvc.RequestBody;
12 | import com.wang.spring.annotation.mvc.RequestMapping;
13 | import com.wang.spring.annotation.mvc.RequestParam;
14 | import com.wang.spring.annotation.mvc.ResponseBody;
15 | import com.wang.spring.constants.RequestMethod;
16 | import com.wang.spring.mvc.ModelAndView;
17 |
18 | @Controller
19 | @RequestMapping(value = "/user")
20 | public class TestController {
21 |
22 | @Autowired
23 | UserService userService;
24 |
25 | @ResponseBody
26 | @RequestMapping(value = "/register",method = RequestMethod.POST)
27 | public ResponseEntity registerUser(@RequestBody UserRequest userRequest) {
28 | try {
29 | boolean isRegister = userService.registerUser(userRequest);
30 | if(isRegister) {
31 | return ResponseEntity.success(null, userRequest.getUserName()+"注册成功...");
32 | }
33 | } catch (Exception e) {
34 | // TODO: handle exception
35 | e.printStackTrace();
36 | }
37 | return ResponseEntity.fail("注册失败");
38 | }
39 |
40 | @ResponseBody
41 | @RequestMapping(value = "/login",method = RequestMethod.POST)
42 | public ResponseEntity login(@RequestBody UserRequest userRequest){
43 | try {
44 | User user = userService.loginUser(userRequest);
45 | if(user!=null) {
46 | return ResponseEntity.success(user, userRequest.getUserName()+"登录成功");
47 | }
48 | } catch (Exception e) {
49 | // TODO: handle exception
50 | e.printStackTrace();
51 | }
52 | return ResponseEntity.fail("用户名或密码错误");
53 | }
54 |
55 | @RequestMapping(value = "/isLogin",method = RequestMethod.GET)
56 | public ModelAndView isLogin(@RequestParam(value = "username") String username){
57 | try {
58 | boolean isLogin = userService.isUserLogin(username);
59 | if(isLogin) {
60 | return new ModelAndView("login_sucess.html").addModel("user", username);
61 | }
62 | } catch (Exception e) {
63 | // TODO: handle exception
64 | e.printStackTrace();
65 | }
66 | return new ModelAndView("login_failed.html").addModel("user", username);
67 | }
68 |
69 | @ResponseBody
70 | @RequestMapping(value = "/logout",method = RequestMethod.GET)
71 | public ResponseEntity loginout(@RequestParam(value = "username") String username){
72 | try {
73 | boolean isLogout = userService.logout(username);
74 | if(isLogout) {
75 | return ResponseEntity.success(null, username+"注销成功");
76 | }
77 | } catch (Exception e) {
78 | // TODO: handle exception
79 | e.printStackTrace();
80 | }
81 | return ResponseEntity.fail(username+"注销失败");
82 | }
83 |
84 | @ResponseBody
85 | @RequestMapping(value = "/findUser/{id}",method = RequestMethod.GET)
86 | public ResponseEntity loginout(@PathVariable("id") Integer id){
87 | try {
88 | User user= userService.findUser(id);
89 | System.out.println("测试循环依赖,如果相等则解决: "+userService+" "+userService.userservice2.userService);
90 | if(user!=null) {
91 | return ResponseEntity.success(user, "成功找到id="+id+"的用户");
92 | }
93 | } catch (Exception e) {
94 | // TODO: handle exception
95 | e.printStackTrace();
96 | }
97 | return ResponseEntity.fail("未找到id="+id+"的用户");
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/src/main/java/com/wang/demo/dao/UserMapper.java:
--------------------------------------------------------------------------------
1 | package com.wang.demo.dao;
2 |
3 | import com.wang.demo.model.User;
4 | import com.wang.mybatis.annotation.Insert;
5 | import com.wang.mybatis.annotation.Mapper;
6 | import com.wang.mybatis.annotation.Param;
7 | import com.wang.mybatis.annotation.Select;
8 |
9 | @Mapper
10 | public interface UserMapper {
11 |
12 | @Select("select * from user where id=#{id}")
13 | public User selectUser(@Param("id") Integer id);
14 |
15 | @Insert("insert into user(username,password,timestamp) values(#{username},#{password},#{timestamp})")
16 | public int insertUser(@Param("username") String username,@Param("password") String password,@Param("timestamp") Long timestamp);
17 |
18 | @Select("select * from user where username=#{username}")
19 | public User selectUser(@Param("username") String username);
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/com/wang/demo/interceptor/Interceptor.java:
--------------------------------------------------------------------------------
1 | package com.wang.demo.interceptor;
2 |
3 | import com.wang.spring.annotation.aop.After;
4 | import com.wang.spring.annotation.aop.Around;
5 | import com.wang.spring.annotation.aop.Aspect;
6 | import com.wang.spring.annotation.aop.Before;
7 | import com.wang.spring.annotation.aop.Pointcut;
8 | import com.wang.spring.aop.JoinPoint;
9 |
10 | @Aspect
11 | public class Interceptor {
12 | @Pointcut("com.wang.demo.service.UserService.register")
13 | public void point() {
14 |
15 | }
16 |
17 | @Before(value = "point()",order = 1)
18 | public void beforeService() {
19 | System.out.println("开始调用registerUser,当前时间为:"+System.currentTimeMillis());
20 | }
21 |
22 | @Before(value = "com.wang.demo.service.UserService.loginUser")
23 | public void beforeService2() {
24 | System.out.println("开始调用loginUser,当前时间为:"+System.currentTimeMillis());
25 | }
26 |
27 | @Before(value = "com.wang.demo.service.UserService.isUserLogin")
28 | public void beforeService3() {
29 | System.out.println("开始调用isUserLogin,当前时间为:"+System.currentTimeMillis());
30 | }
31 |
32 | @Around(value = "point()")
33 | public Object aroundService(JoinPoint joinPoint) {
34 | Object result=null;
35 | System.out.println("around调用之前............");
36 | try {
37 | result=joinPoint.proceed();
38 | } catch (Exception e) {
39 | // TODO Auto-generated catch block
40 | e.printStackTrace();
41 | } catch (Throwable e) {
42 | // TODO Auto-generated catch block
43 | e.printStackTrace();
44 | }
45 | System.out.println("around调用之后..........");
46 | return result;
47 | }
48 |
49 | @After("point()")
50 | public void afterService() {
51 | System.out.println("registerUser方法执行结束");
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/main/java/com/wang/demo/model/JedisFake.java:
--------------------------------------------------------------------------------
1 | package com.wang.demo.model;
2 |
3 | import com.wang.spring.annotation.ioc.Component;
4 |
5 | @Component
6 | public class JedisFake{
7 | String host="localhost";
8 | String port="6379";
9 | public JedisFake() {
10 | // TODO Auto-generated constructor stub
11 | }
12 | public JedisFake(String host,String port) {
13 | // TODO Auto-generated constructor stub
14 | this.host=host;
15 | this.port=port;
16 | }
17 | @Override
18 | public String toString() {
19 | return host+":"+port;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/com/wang/demo/model/ResponseEntity.java:
--------------------------------------------------------------------------------
1 | package com.wang.demo.model;
2 |
3 | public class ResponseEntity {
4 | public Integer errorCode=200;
5 | public String msg="";
6 | public Object data=null;
7 |
8 | public ResponseEntity(Integer errorCode,String msg,Object data) {
9 | // TODO Auto-generated constructor stub
10 | this.errorCode=errorCode;
11 | this.msg = msg;
12 | this.data=data;
13 | }
14 |
15 | public static ResponseEntity success(Object data) {
16 | ResponseEntity entity = new ResponseEntity(200,null,data);
17 | return entity;
18 | }
19 | public static ResponseEntity success(Object data,String msg) {
20 | ResponseEntity entity = new ResponseEntity(200,msg,data);
21 | return entity;
22 | }
23 | public static ResponseEntity fail(String msg) {
24 | ResponseEntity entity = new ResponseEntity(500,msg,null);
25 | return entity;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/wang/demo/model/User.java:
--------------------------------------------------------------------------------
1 | package com.wang.demo.model;
2 |
3 | public class User{
4 | private Integer id;
5 | private String username;
6 | private String password;
7 | private Long timestamp;
8 |
9 | public Integer getId() {
10 | return id;
11 | }
12 |
13 | public void setId(Integer id) {
14 | this.id = id;
15 | }
16 |
17 | public String getUserName() {
18 | return username;
19 | }
20 |
21 | public void setUserName(String username) {
22 | this.username = username;
23 | }
24 |
25 | public String getPassword() {
26 | return password;
27 | }
28 |
29 | public void setPassword(String password) {
30 | this.password = password;
31 | }
32 |
33 | public Long getTimeStamp() {
34 | return timestamp;
35 | }
36 |
37 | public void setTimeStamp(Long timestamp) {
38 | this.timestamp = timestamp;
39 | }
40 |
41 | @Override
42 | public String toString() {
43 | return "id="+id+" , name="+username+" , password="+password;
44 | }
45 | }
--------------------------------------------------------------------------------
/src/main/java/com/wang/demo/model/UserRequest.java:
--------------------------------------------------------------------------------
1 | package com.wang.demo.model;
2 |
3 | public class UserRequest {
4 | private String username;
5 |
6 | private String password;
7 |
8 | public String getUserName() {
9 | return username;
10 | }
11 |
12 | public void setUserName(String username) {
13 | this.username = username;
14 | }
15 |
16 | public String getPassword() {
17 | return password;
18 | }
19 |
20 | public void setPassword(String password) {
21 | this.password = password;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/com/wang/demo/service/IUserService.java:
--------------------------------------------------------------------------------
1 | package com.wang.demo.service;
2 | import com.wang.demo.model.UserRequest;
3 | import com.wang.demo.model.User;
4 |
5 | public interface IUserService {
6 | boolean registerUser(UserRequest request);
7 |
8 | User loginUser(UserRequest request);
9 |
10 | boolean isUserLogin(String username);
11 |
12 | boolean logout(String username);
13 |
14 | User findUser(Integer id) throws Exception;
15 |
16 | User findUser1(Integer id1) throws Exception;
17 |
18 | User findUser2(Integer id2);
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/wang/demo/service/UserService.java:
--------------------------------------------------------------------------------
1 | package com.wang.demo.service;
2 |
3 | import com.alibaba.fastjson.JSON;
4 | import com.wang.demo.dao.UserMapper;
5 | import com.wang.demo.model.User;
6 | import com.wang.demo.model.UserRequest;
7 | import com.wang.spring.annotation.aop.Transactional;
8 | import com.wang.spring.annotation.ioc.Autowired;
9 | import com.wang.spring.annotation.ioc.Service;
10 | import com.wang.spring.annotation.ioc.Value;
11 | import com.wang.spring.constants.PropagationLevelConstant;
12 |
13 | import redis.clients.jedis.Jedis;
14 | @Service
15 | public class UserService implements IUserService{
16 |
17 | @Autowired
18 | UserMapper userMapper;
19 |
20 | @Autowired
21 | Jedis jedis;
22 |
23 | @Autowired
24 | public UserService2 userservice2;
25 |
26 | @Override
27 | public boolean registerUser(UserRequest request) {
28 | try{
29 | userMapper.insertUser(request.getUserName(), request.getPassword(), System.currentTimeMillis());
30 | return true;
31 | }catch (Exception e){
32 | e.printStackTrace();
33 | }
34 | return false;
35 | }
36 |
37 | @Override
38 | public User loginUser(UserRequest request) {
39 | User user = userMapper.selectUser(request.getUserName());
40 | if(null==user || !user.getPassword().equals(request.getPassword())) {
41 | return null;
42 | }
43 | String key = "login:"+user.getUserName();
44 | jedis.set(key, JSON.toJSONString(user));
45 | System.out.println(user.getUserName()+" 登录成功");
46 | return user;
47 | }
48 |
49 | @Override
50 | public boolean isUserLogin(String username) {
51 | String key = "login:"+username;
52 | return jedis.exists(key);
53 | }
54 |
55 | @Override
56 | public boolean logout(String username) {
57 | // TODO Auto-generated method stub
58 | String key = "login:"+username;
59 | if(!jedis.exists(key)) {
60 | return false;
61 | }
62 | jedis.del(key);
63 | return true;
64 | }
65 |
66 |
67 | @Override
68 | @Transactional(rollbackFor = {Exception.class})
69 | public User findUser1(Integer id1) throws Exception {
70 | // TODO Auto-generated method stub
71 | return userMapper.selectUser(id1);
72 | }
73 |
74 | @Override
75 | @Transactional
76 | public User findUser2(Integer id2) {
77 | // TODO Auto-generated method stub
78 | return userMapper.selectUser(id2);
79 | }
80 |
81 | @Override
82 | //@Transactional
83 | public User findUser(Integer id) throws Exception {
84 | // TODO Auto-generated method stub
85 | User user1 = findUser1(id);
86 |
87 | User user2 = findUser2(id);
88 | return user1;
89 |
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/main/java/com/wang/demo/service/UserService2.java:
--------------------------------------------------------------------------------
1 | package com.wang.demo.service;
2 |
3 | import com.wang.demo.dao.UserMapper;
4 | import com.wang.spring.annotation.ioc.Autowired;
5 | import com.wang.spring.annotation.ioc.Service;
6 |
7 |
8 | @Service
9 | public class UserService2 {
10 | @Autowired
11 | public UserService userService;
12 |
13 | @Autowired
14 | UserMapper userMapper;
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/com/wang/mybatis/annotation/Delete.java:
--------------------------------------------------------------------------------
1 | package com.wang.mybatis.annotation;
2 |
3 | import static java.lang.annotation.ElementType.METHOD;
4 | import static java.lang.annotation.RetentionPolicy.RUNTIME;
5 |
6 | import java.lang.annotation.Retention;
7 | import java.lang.annotation.Target;
8 |
9 | @Retention(RUNTIME)
10 | @Target(METHOD)
11 | public @interface Delete {
12 |
13 | String value();
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/com/wang/mybatis/annotation/Insert.java:
--------------------------------------------------------------------------------
1 | package com.wang.mybatis.annotation;
2 |
3 | import static java.lang.annotation.ElementType.METHOD;
4 | import static java.lang.annotation.RetentionPolicy.RUNTIME;
5 |
6 | import java.lang.annotation.Retention;
7 | import java.lang.annotation.Target;
8 |
9 | @Retention(RUNTIME)
10 | @Target(METHOD)
11 | public @interface Insert {
12 |
13 | String value();
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/com/wang/mybatis/annotation/Mapper.java:
--------------------------------------------------------------------------------
1 | package com.wang.mybatis.annotation;
2 |
3 | import static java.lang.annotation.ElementType.TYPE;
4 | import static java.lang.annotation.RetentionPolicy.RUNTIME;
5 |
6 | import java.lang.annotation.Retention;
7 | import java.lang.annotation.Target;
8 |
9 | import com.wang.spring.annotation.ioc.Component;
10 |
11 | @Retention(RUNTIME)
12 | @Target(TYPE)
13 | @Component
14 | public @interface Mapper {
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/com/wang/mybatis/annotation/Param.java:
--------------------------------------------------------------------------------
1 | package com.wang.mybatis.annotation;
2 |
3 | import static java.lang.annotation.ElementType.PARAMETER;
4 | import static java.lang.annotation.RetentionPolicy.RUNTIME;
5 |
6 | import java.lang.annotation.Retention;
7 | import java.lang.annotation.Target;
8 |
9 | @Retention(RUNTIME)
10 | @Target(PARAMETER)
11 | public @interface Param {
12 |
13 | String value();
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/com/wang/mybatis/annotation/Select.java:
--------------------------------------------------------------------------------
1 | package com.wang.mybatis.annotation;
2 |
3 | import static java.lang.annotation.ElementType.METHOD;
4 | import static java.lang.annotation.RetentionPolicy.RUNTIME;
5 |
6 | import java.lang.annotation.Retention;
7 | import java.lang.annotation.Target;
8 |
9 | @Retention(RUNTIME)
10 | @Target(METHOD)
11 | public @interface Select {
12 |
13 | String value();
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/com/wang/mybatis/annotation/Update.java:
--------------------------------------------------------------------------------
1 | package com.wang.mybatis.annotation;
2 |
3 | import static java.lang.annotation.ElementType.METHOD;
4 | import static java.lang.annotation.RetentionPolicy.RUNTIME;
5 |
6 | import java.lang.annotation.Retention;
7 | import java.lang.annotation.Target;
8 |
9 | @Retention(RUNTIME)
10 | @Target(METHOD)
11 | public @interface Update {
12 |
13 | String value();
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/com/wang/mybatis/constant/SqlTypeConstant.java:
--------------------------------------------------------------------------------
1 | package com.wang.mybatis.constant;
2 | /**
3 | * SQL语句的类型常量,分别对应增删改查
4 | * @author Administrator
5 | *
6 | */
7 | public class SqlTypeConstant {
8 | public static final Integer SELECT_TYPE = 1;
9 |
10 | public static final Integer UPDATE_TYPE = 2;
11 |
12 | public static final Integer DELETE_TYPE = 3;
13 |
14 | public static final Integer INSERT_TYPE = 4;
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/com/wang/mybatis/core/CGLibMapperProxy.java:
--------------------------------------------------------------------------------
1 | package com.wang.mybatis.core;
2 |
3 | import java.lang.annotation.Annotation;
4 | import java.lang.reflect.Method;
5 | import java.util.List;
6 | import com.wang.mybatis.annotation.Delete;
7 | import com.wang.mybatis.annotation.Insert;
8 | import com.wang.mybatis.annotation.Select;
9 | import com.wang.mybatis.annotation.Update;
10 | import com.wang.mybatis.constant.SqlTypeConstant;
11 | import com.wang.mybatis.executor.Executor;
12 | import com.wang.spring.common.MyProxy;
13 |
14 | import net.sf.cglib.proxy.Enhancer;
15 | import net.sf.cglib.proxy.MethodInterceptor;
16 | import net.sf.cglib.proxy.MethodProxy;
17 |
18 | /**
19 | * 使用CGLib库实现的动态代理,可以对@Mapper注解的接口生成代理对象
20 | * 将@Select,@Update,@Delete,@Insert注解中SQL语句生成实际的代理执行
21 | * @author Administrator
22 | *
23 | */
24 | public class CGLibMapperProxy implements MethodInterceptor,MyProxy{
25 | //执行器
26 | private Executor executor=null;
27 |
28 | public CGLibMapperProxy(Executor executor) {
29 | this.executor = executor;
30 | }
31 | /**
32 | * 对方法进行拦截代理
33 | */
34 | @Override
35 | public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
36 | Object result = null;
37 | if(isIntercept(method)){
38 | // getMethodType
39 | Integer methodType = MapperHelper.getMethodDetails(method).getSqlSource().getExecuteType();
40 | if(methodType == null){
41 | throw new RuntimeException("method is normal sql method");
42 | }
43 | //如果是被@Select注解
44 | if(methodType == SqlTypeConstant.SELECT_TYPE){
45 | List