├── .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 list = executor.select(method,args); 46 | result = list; 47 | //根据情况返回一个对象列表或一个实例对象 48 | if(!MapperHelper.getMethodDetails(method).isHasSet()){ 49 | if(list.size() == 0){ 50 | result = null; 51 | }else { 52 | result = list.get(0); 53 | } 54 | } 55 | }else{ 56 | //如果是被@Update,@Delete,@Insert注解 57 | Integer count = executor.update(method,args); 58 | result = count; 59 | } 60 | } 61 | else if (Object.class.equals(method.getDeclaringClass())) { 62 | result = methodProxy.invokeSuper(object, args); 63 | } 64 | return result; 65 | } 66 | /** 67 | * 获得代理对象 68 | */ 69 | @Override 70 | public Object getProxy(Class cls) { 71 | Enhancer enhancer = new Enhancer(); 72 | enhancer.setSuperclass(cls); 73 | enhancer.setCallback(this); 74 | return enhancer.create(); 75 | } 76 | /** 77 | * 判断方法是否需要被代理 78 | * @param method 79 | * @return 80 | */ 81 | private boolean isIntercept(Method method) { 82 | for(Annotation annotation : method.getAnnotations()) { 83 | if(annotation.annotationType().equals(Select.class) || 84 | annotation.annotationType().equals(Update.class) || 85 | annotation.annotationType().equals(Insert.class) || 86 | annotation.annotationType().equals(Delete.class)) { 87 | return true; 88 | } 89 | } 90 | return false; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/com/wang/mybatis/core/MapperHelper.java: -------------------------------------------------------------------------------- 1 | package com.wang.mybatis.core; 2 | 3 | import java.lang.annotation.Annotation; 4 | import java.lang.reflect.Method; 5 | import java.lang.reflect.Parameter; 6 | import java.lang.reflect.ParameterizedType; 7 | import java.lang.reflect.Type; 8 | import java.util.*; 9 | import java.util.concurrent.ConcurrentHashMap; 10 | import com.wang.mybatis.annotation.Delete; 11 | import com.wang.mybatis.annotation.Insert; 12 | import com.wang.mybatis.annotation.Mapper; 13 | import com.wang.mybatis.annotation.Param; 14 | import com.wang.mybatis.annotation.Select; 15 | import com.wang.mybatis.annotation.Update; 16 | import com.wang.mybatis.constant.SqlTypeConstant; 17 | import com.wang.mybatis.executor.ExecutorFactory; 18 | import com.wang.spring.ioc.BeanDefinition; 19 | import com.wang.spring.ioc.BeanDefinitionRegistry; 20 | import com.wang.spring.ioc.ClassSetHelper; 21 | import com.wang.spring.ioc.GenericBeanDefinition; 22 | /** 23 | * 扫描被@Mapper注解的类,解析方法对应的方法详情类MethodDetails 24 | * @author Administrator * 25 | */ 26 | public class MapperHelper { 27 | //单例对象 28 | private static MapperHelper mapperHelper = null; 29 | //方法详情映射 30 | private static Map cacheMethodDetails = new ConcurrentHashMap<>(); 31 | //被@Mapper注解的类集合 32 | private static Set> mapperClassSet = null; 33 | static { 34 | MapperHelper.init(); 35 | } 36 | private MapperHelper() { 37 | } 38 | /** 39 | * 获得MapperHelper的单例 40 | * @return 41 | */ 42 | public static MapperHelper getInstance() { 43 | synchronized (MapperHelper.class) { 44 | if(mapperHelper==null) { 45 | synchronized (MapperHelper.class) { 46 | mapperHelper = new MapperHelper(); 47 | } 48 | } 49 | } 50 | return mapperHelper; 51 | } 52 | /** 53 | * 获得cacheMethodDetails 54 | * @return 55 | */ 56 | public static Map getCacheMethodDetails(){ 57 | return cacheMethodDetails; 58 | } 59 | /** 60 | * 初始化方法 61 | */ 62 | private static void init(){ 63 | mapperClassSet = ClassSetHelper.getClassSetByAnnotation(Mapper.class); 64 | if(mapperClassSet==null || mapperClassSet.isEmpty()) { 65 | System.out.println("未找到Mapper类"); 66 | return; 67 | } 68 | for(Class nowClazz: mapperClassSet){ 69 | if(!nowClazz.isInterface()){ 70 | continue; 71 | } 72 | Method[] methods = nowClazz.getDeclaredMethods(); 73 | for( Method method : methods){ 74 | //对方法解析,获得详情类 75 | MethodDetails methodDetails = handleParameter(method); 76 | //解析方法注解上的Sql语句 77 | methodDetails.setSqlSource(handleAnnotation(method)); 78 | cacheMethodDetails.put(method,methodDetails); 79 | } 80 | } 81 | //将被@Mapper注解的类注册到BeanDefinition容器中,被设置代理类 82 | if(mapperClassSet!=null && !mapperClassSet.isEmpty()) { 83 | CGLibMapperProxy cgLibMapperProxy = new CGLibMapperProxy(ExecutorFactory.getExecutor()); 84 | for(Class cls:mapperClassSet) { 85 | BeanDefinition beanDefinition=null; 86 | if(BeanDefinitionRegistry.containsBeanDefinition(cls.getName())) { 87 | beanDefinition = BeanDefinitionRegistry.getBeanDefinition(cls.getName()); 88 | } 89 | else { 90 | beanDefinition = new GenericBeanDefinition(); 91 | beanDefinition.setBeanClass(cls); 92 | } 93 | beanDefinition.setIsProxy(true); 94 | beanDefinition.setProxy(cgLibMapperProxy); 95 | BeanDefinitionRegistry.registryBeanDefinition(cls.getName(), beanDefinition); 96 | System.out.println("MapperHelper 注册 "+cls.getName()); 97 | } 98 | } 99 | } 100 | /** 101 | * 获得某个方法的详情类 102 | * @param method 103 | * @return 104 | */ 105 | public static MethodDetails getMethodDetails(Method method) { 106 | if(cacheMethodDetails==null || cacheMethodDetails.isEmpty() || !cacheMethodDetails.containsKey(method)) { 107 | return null; 108 | } 109 | return cacheMethodDetails.get(method); 110 | } 111 | /** 112 | * 由Method对象解析出表示方法详情的MethodDetails对象 113 | * @param method 114 | * @return 115 | */ 116 | private static MethodDetails handleParameter(Method method){ 117 | 118 | MethodDetails methodDetails = new MethodDetails(); 119 | int parameterCount = method.getParameterCount(); 120 | Class[] parameterTypes = method.getParameterTypes(); 121 | List parameterNames = new ArrayList<>(); 122 | Parameter[] params = method.getParameters(); 123 | //设置参数名称 124 | for(Parameter parameter:params){ 125 | parameterNames.add(parameter.getName()); 126 | } 127 | //设置注解中的参数名称 128 | for(int i = 0; i < parameterCount; i++){ 129 | parameterNames.set(i,getParamNameFromAnnotation(method,i,parameterNames.get(i))); 130 | } 131 | //将参数类型和参数名添加到MethodDetails对象中 132 | methodDetails.setParameterTypes(parameterTypes); 133 | methodDetails.setParameterNames(parameterNames); 134 | //获取方法返回类型 135 | Type methodReturnType = method.getGenericReturnType(); 136 | Class methodReturnClass = method.getReturnType(); 137 | if(methodReturnType instanceof ParameterizedType){ 138 | //如果是可参数化的类型,如List,则获取具体参数类型 139 | if(!List.class.equals(methodReturnClass)){ 140 | throw new RuntimeException("now ibatis only support list"); 141 | } 142 | Type type = ((ParameterizedType) methodReturnType).getActualTypeArguments()[0]; 143 | methodDetails.setReturnType((Class) type); 144 | methodDetails.setHasSet(true); 145 | }else { 146 | methodDetails.setReturnType(methodReturnClass); 147 | methodDetails.setHasSet(false); 148 | } 149 | return methodDetails; 150 | } 151 | 152 | /** 153 | * 解析注解中的Sql语句,生成SqlSource对象 154 | * @param method 155 | * @return 156 | */ 157 | private static SqlSource handleAnnotation(Method method){ 158 | SqlSource sqlSource = null; 159 | String sql = null; 160 | Annotation[] annotations = method.getDeclaredAnnotations(); 161 | for(Annotation annotation : annotations){ 162 | if(Select.class.isInstance(annotation)){ 163 | Select selectAnnotation = (Select)annotation; 164 | sql = selectAnnotation.value(); 165 | sqlSource = new SqlSource(sql); 166 | sqlSource.setExecuteType(SqlTypeConstant.SELECT_TYPE); 167 | break; 168 | }else if(Update.class.isInstance(annotation)){ 169 | Update updateAnnotation = (Update)annotation; 170 | sql = updateAnnotation.value(); 171 | sqlSource = new SqlSource(sql); 172 | sqlSource.setExecuteType(SqlTypeConstant.UPDATE_TYPE); 173 | break; 174 | }else if(Delete.class.isInstance(annotation)){ 175 | Delete deleteAnnotation = (Delete) annotation; 176 | sql = deleteAnnotation.value(); 177 | sqlSource = new SqlSource(sql); 178 | sqlSource.setExecuteType(SqlTypeConstant.DELETE_TYPE); 179 | break; 180 | }else if(Insert.class.isInstance(annotation)){ 181 | Insert insertAnnotation = (Insert) annotation; 182 | sql = insertAnnotation.value(); 183 | sqlSource = new SqlSource(sql); 184 | sqlSource.setExecuteType(SqlTypeConstant.INSERT_TYPE); 185 | break; 186 | } 187 | } 188 | if(sqlSource == null){ 189 | throw new RuntimeException("method annotation not null"); 190 | } 191 | return sqlSource; 192 | } 193 | 194 | /** 195 | * 获取指定method的第i个参数的Param参数命名 196 | * @param method 197 | * @param i 198 | * @param paramName 199 | * @return 200 | */ 201 | private static String getParamNameFromAnnotation(Method method, int i, String paramName) { 202 | final Object[] paramAnnos = method.getParameterAnnotations()[i]; 203 | for (Object paramAnno : paramAnnos) { 204 | if (paramAnno instanceof Param) { 205 | paramName = ((Param) paramAnno).value(); 206 | } 207 | } 208 | return paramName; 209 | } 210 | } 211 | -------------------------------------------------------------------------------- /src/main/java/com/wang/mybatis/core/MethodDetails.java: -------------------------------------------------------------------------------- 1 | package com.wang.mybatis.core; 2 | 3 | import java.util.List; 4 | 5 | public class MethodDetails{ 6 | //方法返回类型 7 | private Class returnType; 8 | //是否返回集合 9 | private boolean HasSet; 10 | //参数类型 11 | private Class[] parameterTypes; 12 | //参数名称 13 | private List parameterNames; 14 | //解析得到的Sql包装对象 15 | private SqlSource sqlSource; 16 | 17 | public Class getReturnType() { 18 | return returnType; 19 | } 20 | 21 | public void setReturnType(Class returnType) { 22 | this.returnType = returnType; 23 | } 24 | 25 | public boolean isHasSet() { 26 | return HasSet; 27 | } 28 | 29 | public void setHasSet(boolean hasSet) { 30 | HasSet = hasSet; 31 | } 32 | 33 | public Class[] getParameterTypes() { 34 | return parameterTypes; 35 | } 36 | 37 | public void setParameterTypes(Class[] parameterTypes) { 38 | this.parameterTypes = parameterTypes; 39 | } 40 | 41 | public List getParameterNames() { 42 | return parameterNames; 43 | } 44 | 45 | public void setParameterNames(List parameterNames) { 46 | this.parameterNames = parameterNames; 47 | } 48 | 49 | public SqlSource getSqlSource() { 50 | return sqlSource; 51 | } 52 | 53 | public void setSqlSource(SqlSource sqlSource) { 54 | this.sqlSource = sqlSource; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/com/wang/mybatis/core/SqlResultCache.java: -------------------------------------------------------------------------------- 1 | package com.wang.mybatis.core; 2 | 3 | import java.util.Map; 4 | import java.util.concurrent.ConcurrentHashMap; 5 | 6 | public class SqlResultCache{ 7 | //Sql语句的执行缓存 8 | private static Map map = new ConcurrentHashMap<>(); 9 | 10 | public void putCache(String key, Object val) { 11 | map.put(key,val); 12 | } 13 | 14 | public Object getCache(String key) { 15 | return map.get(key); 16 | } 17 | 18 | public void cleanCache() { 19 | map.clear(); 20 | } 21 | 22 | public int getSize() { 23 | return map.size(); 24 | } 25 | 26 | public void removeCache(String key) { 27 | map.remove(key); 28 | } 29 | } -------------------------------------------------------------------------------- /src/main/java/com/wang/mybatis/core/SqlSource.java: -------------------------------------------------------------------------------- 1 | package com.wang.mybatis.core; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * @example select * from users where id = ${id} and name = #{name} 8 | * -> sql = select * from users where id = ? and name = ? 9 | * -> params = {id,name} 10 | * -> paramInjectTypes = {0,1} 11 | **/ 12 | public class SqlSource { 13 | //sql语句,待输入字段替换成? 14 | private String sql; 15 | //待输入字段 16 | private List params = new ArrayList<>(); 17 | //注入的类型,0表示拼接,1表示动态注入 18 | private List paramInjectTypes = new ArrayList<>(); 19 | //Sql语句的类型,select update insert delete等 20 | private Integer executeType; 21 | 22 | public SqlSource(String sql){ 23 | this.sql = sqlInject(sql); 24 | } 25 | /** 26 | * 解析Sql语句,将#{ }及${ }参数替换为?,并获得参数名与注入方式列表 27 | * @param sql 28 | * @return 29 | */ 30 | private String sqlInject(String sql){ 31 | 32 | String labelPrefix1 = "${"; 33 | String labelPrefix2 = "#{"; 34 | String labelSuffix = "}"; 35 | while ((sql.indexOf(labelPrefix1) > 0 || sql.indexOf(labelPrefix2) > 0) && sql.indexOf(labelSuffix) > 0){ 36 | Integer labelPrefix1Index = sql.indexOf(labelPrefix1); 37 | Integer labelPrefix2Index = sql.indexOf(labelPrefix2); 38 | String sqlParamName; 39 | Integer injectType; 40 | if(labelPrefix1Index>0 && labelPrefix2Index<=0) { 41 | sqlParamName = sql.substring(labelPrefix1Index,sql.indexOf(labelSuffix)+1); 42 | injectType = 0; 43 | } 44 | else if (labelPrefix2Index>0 && labelPrefix1Index<=0) { 45 | sqlParamName = sql.substring(labelPrefix2Index,sql.indexOf(labelSuffix)+1); 46 | injectType = 1; 47 | } 48 | else if(labelPrefix1Index>0 && labelPrefix2Index>0 && labelPrefix1Index0 && labelPrefix2Index>0 && labelPrefix1Index>labelPrefix2Index){ 53 | sqlParamName = sql.substring(labelPrefix2Index,sql.indexOf(labelSuffix)+1); 54 | injectType = 1; 55 | } 56 | else { 57 | continue; 58 | } 59 | sql = sql.replace(sqlParamName,"?"); 60 | if(injectType==0) { 61 | params.add(sqlParamName.replace("${","").replace("}","")); 62 | paramInjectTypes.add(0); 63 | } 64 | else { 65 | params.add(sqlParamName.replace("#{","").replace("}","")); 66 | paramInjectTypes.add(1); 67 | } 68 | 69 | } 70 | return sql; 71 | } 72 | 73 | public String getSql() { 74 | return sql; 75 | } 76 | 77 | public void setSql(String sql) { 78 | this.sql = sql; 79 | } 80 | 81 | public List getParam() { 82 | return params; 83 | } 84 | 85 | public void setParam(List params) { 86 | this.params = params; 87 | } 88 | 89 | public List getParamInjectType() { 90 | return paramInjectTypes; 91 | } 92 | 93 | public void setParamInjectType(List paramInjectTypes) { 94 | this.paramInjectTypes = paramInjectTypes; 95 | } 96 | 97 | 98 | public Integer getExecuteType() { 99 | return executeType; 100 | } 101 | 102 | public void setExecuteType(Integer executeType) { 103 | this.executeType = executeType; 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/main/java/com/wang/mybatis/datasource/DataSource.java: -------------------------------------------------------------------------------- 1 | package com.wang.mybatis.datasource; 2 | 3 | import java.sql.Connection; 4 | import java.sql.SQLException; 5 | /** 6 | * 数据源接口 7 | * @author Administrator 8 | * 9 | */ 10 | public interface DataSource { 11 | //加载驱动 12 | void loadDriverClass(String driverClassName); 13 | //获得默认连接 14 | Connection getConnection() throws SQLException; 15 | //释放连接 16 | void removeConnection(Connection connection) throws SQLException; 17 | //根据参数获得连接 18 | Connection getConnection(String url,String username, String password) throws SQLException; 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/wang/mybatis/datasource/NormalDataSource.java: -------------------------------------------------------------------------------- 1 | package com.wang.mybatis.datasource; 2 | 3 | import java.sql.Connection; 4 | import java.sql.DriverManager; 5 | import java.sql.SQLException; 6 | /** 7 | * 普通的数据源派生类,每次都会获取到一个新的连接 8 | * @author Administrator 9 | * 10 | */ 11 | public class NormalDataSource implements DataSource{ 12 | //驱动类 13 | private String driverClassName; 14 | //数据源url 15 | private String url; 16 | //账号 17 | private String userName; 18 | //密码 19 | private String passWord; 20 | 21 | public NormalDataSource(String driverClassName, String url, String userName, String passWord) { 22 | this.driverClassName = driverClassName; 23 | this.url = url; 24 | this.userName = userName; 25 | this.passWord = passWord; 26 | loadDriverClass(driverClassName); 27 | } 28 | 29 | @Override 30 | public void loadDriverClass(String driverClassName) { 31 | try { 32 | Class.forName(driverClassName); 33 | } catch (ClassNotFoundException e) { 34 | // TODO Auto-generated catch block 35 | e.printStackTrace(); 36 | } 37 | } 38 | 39 | @Override 40 | public Connection getConnection(String url,String username, String password) throws SQLException { 41 | return DriverManager.getConnection(url,username,password); 42 | } 43 | 44 | @Override 45 | public Connection getConnection() throws SQLException { 46 | return getConnection(this.url, this.userName, this.passWord); 47 | } 48 | 49 | @Override 50 | public void removeConnection(Connection connection) throws SQLException{ 51 | if(connection!=null) { 52 | connection.close(); 53 | connection = null; 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/com/wang/mybatis/datasource/PoolDataSource.java: -------------------------------------------------------------------------------- 1 | package com.wang.mybatis.datasource; 2 | 3 | import java.sql.Connection; 4 | import java.sql.DriverManager; 5 | import java.sql.SQLException; 6 | import java.util.concurrent.LinkedBlockingQueue; 7 | import java.util.concurrent.TimeUnit; 8 | import java.util.concurrent.atomic.AtomicInteger; 9 | 10 | import com.wang.spring.utils.ConfigUtil; 11 | 12 | public class PoolDataSource implements DataSource{ 13 | //数据源连接信息 14 | private String driverClassName; 15 | private String url; 16 | private String userName; 17 | private String passWord; 18 | 19 | //空闲连接池 20 | private LinkedBlockingQueue idleConnectPool = new LinkedBlockingQueue<>(); 21 | //活跃连接池 22 | private LinkedBlockingQueue busyConnectPool = new LinkedBlockingQueue<>(); 23 | //活跃连接数 24 | private AtomicInteger activeSize = new AtomicInteger(0); 25 | //最大连接数 26 | private Integer maxSize=10; 27 | private Long waitTimeMill = 100L; 28 | 29 | public PoolDataSource(String driverClassName, String url, String userName, String passWord,Integer maxSize,Long waitTimeMill) { 30 | // TODO Auto-generated constructor stub 31 | loadDriverClass(driverClassName); 32 | this.driverClassName = driverClassName; 33 | this.url = url; 34 | this.userName = userName; 35 | this.passWord = passWord; 36 | this.maxSize = maxSize; 37 | this.waitTimeMill = waitTimeMill; 38 | } 39 | @Override 40 | public void loadDriverClass(String driverClassName) { 41 | try { 42 | Class.forName(driverClassName); 43 | } catch (ClassNotFoundException e) { 44 | e.printStackTrace(); 45 | } 46 | } 47 | @Override 48 | public Connection getConnection() throws SQLException { 49 | return getConnection(this.url,this.userName,this.passWord); 50 | } 51 | 52 | @Override 53 | public Connection getConnection(String url,String username, String password) throws SQLException { 54 | //从idle池中取出一个连接 55 | Connection connection = idleConnectPool.poll(); 56 | if (connection != null) { 57 | //如果有连接,则放入busy池中 58 | busyConnectPool.offer(connection); 59 | return connection; 60 | } 61 | if (activeSize.get() < maxSize) { 62 | //通过 activeSize.incrementAndGet() <= maxSize 这个判断 63 | if (activeSize.incrementAndGet() <= maxSize) { 64 | connection = DriverManager.getConnection(url,username,password);// 创建新连接 65 | busyConnectPool.offer(connection); 66 | return connection; 67 | } 68 | } 69 | //如果空闲池中连接数达到maxSize, 则阻塞等待归还连接 70 | try { 71 | //阻塞获取连接,如果指定时间内内有其他连接释放 72 | connection = idleConnectPool.poll(waitTimeMill, TimeUnit.MILLISECONDS); 73 | if (connection == null) { 74 | System.out.println("等待超时"); 75 | throw new RuntimeException("等待连接超时"); 76 | } 77 | } catch (InterruptedException e) { 78 | e.printStackTrace(); 79 | } 80 | return connection; 81 | } 82 | 83 | @Override 84 | public void removeConnection(Connection connection) throws SQLException { 85 | if(connection!=null) { 86 | //如果连接未关闭,则连接从活跃池中取出,放到空闲池,如果连接已关闭,则移除连接 87 | if(!connection.isClosed()) { 88 | busyConnectPool.remove(connection); 89 | idleConnectPool.offer(connection); 90 | } 91 | else { 92 | busyConnectPool.remove(connection); 93 | idleConnectPool.remove(connection); 94 | connection = null; 95 | } 96 | } 97 | } 98 | 99 | 100 | 101 | } 102 | -------------------------------------------------------------------------------- /src/main/java/com/wang/mybatis/executor/Executor.java: -------------------------------------------------------------------------------- 1 | package com.wang.mybatis.executor; 2 | 3 | import java.lang.reflect.Method; 4 | import java.sql.SQLException; 5 | import java.util.List; 6 | 7 | import com.wang.mybatis.transaction.TransactionStatus; 8 | 9 | /** 10 | * 执行器接口 11 | * @author Administrator 12 | * 13 | */ 14 | public interface Executor { 15 | //执行select语句 16 | List select(Method method,Object[] args) throws Exception; 17 | //执行update,delete,insert语句 18 | int update(Method method,Object[] args)throws SQLException; 19 | //提交事务 20 | void commit(TransactionStatus status) throws SQLException; 21 | //回滚事务 22 | void rollback() throws SQLException; 23 | //释放连接 24 | void close() throws SQLException; 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/wang/mybatis/executor/ExecutorFactory.java: -------------------------------------------------------------------------------- 1 | package com.wang.mybatis.executor; 2 | 3 | /** 4 | * 执行器工厂 5 | * @author Administrator 6 | * 7 | */ 8 | public class ExecutorFactory { 9 | public static Executor getExecutor(){ 10 | Executor executor = new SimpleExecutor(false, false); 11 | return executor; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/wang/mybatis/executor/SimpleExecutor.java: -------------------------------------------------------------------------------- 1 | package com.wang.mybatis.executor; 2 | 3 | import java.lang.reflect.Method; 4 | import java.sql.ResultSet; 5 | import java.sql.SQLException; 6 | import java.util.List; 7 | import com.mysql.jdbc.Connection; 8 | import com.mysql.jdbc.PreparedStatement; 9 | import com.wang.mybatis.core.MapperHelper; 10 | import com.wang.mybatis.core.SqlResultCache; 11 | import com.wang.mybatis.handler.PreparedStatementHandler; 12 | import com.wang.mybatis.handler.ResultSetHandler; 13 | import com.wang.mybatis.transaction.TransactionFactory; 14 | import com.wang.mybatis.transaction.TransactionManager; 15 | import com.wang.mybatis.transaction.TransactionStatus; 16 | 17 | /** 18 | * 简单执行器 19 | * @author Administrator 20 | * 21 | */ 22 | public class SimpleExecutor implements Executor{ 23 | 24 | public TransactionManager transactionManager; 25 | 26 | public SqlResultCache sqlResultCache; 27 | 28 | public SimpleExecutor(boolean openTransaction,boolean openCache){ 29 | if(openCache){ 30 | this.sqlResultCache = new SqlResultCache(); 31 | } 32 | if(openTransaction){ 33 | this.transactionManager = TransactionFactory.newTransaction(Connection.TRANSACTION_REPEATABLE_READ,false); 34 | }else { 35 | this.transactionManager = TransactionFactory.newTransaction(); 36 | } 37 | } 38 | /** 39 | * 执行selct语句 40 | */ 41 | @Override 42 | public List select(Method method,Object[] args) throws Exception{ 43 | String cacheKey = generateCacheKey(method,args); 44 | //如果有缓存,则直接返回 45 | if(sqlResultCache != null && sqlResultCache.getCache(cacheKey) != null){ 46 | System.out.println("this is cache"); 47 | return (List)sqlResultCache.getCache(cacheKey); 48 | } 49 | //生成PreparedStatement对象,注入参数,并执行查询 50 | PreparedStatementHandler preparedStatementHandler = new PreparedStatementHandler(transactionManager,method,args); 51 | PreparedStatement preparedStatement = (PreparedStatement) preparedStatementHandler.generateStatement(); 52 | ResultSet resultSet = null; 53 | preparedStatement.executeQuery(); 54 | resultSet = preparedStatement.getResultSet(); 55 | //对结果集resultSet进行解析,映射为实例对象 56 | Class returnClass = MapperHelper.getMethodDetails(method).getReturnType(); 57 | if(returnClass == null || void.class.equals(returnClass)){ 58 | preparedStatement.close(); 59 | preparedStatementHandler.closeConnection(); 60 | return null; 61 | }else { 62 | ResultSetHandler resultSetHandler = new ResultSetHandler(returnClass,resultSet); 63 | List res = resultSetHandler.handle(); 64 | if(sqlResultCache != null){ 65 | sqlResultCache.putCache(cacheKey,res); 66 | } 67 | preparedStatement.close(); 68 | resultSet.close(); 69 | preparedStatementHandler.closeConnection(); 70 | return res; 71 | } 72 | } 73 | /** 74 | * 执行update,insert,delete等sql语句 75 | */ 76 | @Override 77 | public int update(Method method,Object[] args)throws SQLException{ 78 | PreparedStatementHandler preparedStatementHandler = null; 79 | PreparedStatement preparedStatement = null; 80 | Integer count = 0; 81 | if(sqlResultCache != null){ 82 | sqlResultCache.cleanCache(); 83 | } 84 | try{ 85 | preparedStatementHandler = new PreparedStatementHandler(transactionManager,method,args); 86 | preparedStatement = (PreparedStatement) preparedStatementHandler.generateStatement(); 87 | count = preparedStatement.executeUpdate(); 88 | }finally { 89 | if(preparedStatement != null){ 90 | preparedStatement.close(); 91 | } 92 | preparedStatementHandler.closeConnection(); 93 | } 94 | return count; 95 | } 96 | 97 | @Override 98 | public void commit(TransactionStatus status) throws SQLException { 99 | transactionManager.commit(status); 100 | } 101 | 102 | @Override 103 | public void rollback() throws SQLException { 104 | transactionManager.rollback(); 105 | } 106 | 107 | @Override 108 | public void close() throws SQLException { 109 | transactionManager.close(); 110 | } 111 | /** 112 | * 生成缓存sql执行结果的key 113 | * @param method 114 | * @param args 115 | * @return 116 | */ 117 | private String generateCacheKey(Method method, Object args[]){ 118 | StringBuilder cacheKey = new StringBuilder(method.getDeclaringClass().getName() + method.getName()); 119 | for(Object o:args){ 120 | cacheKey.append(o.toString()); 121 | } 122 | return cacheKey.toString(); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/main/java/com/wang/mybatis/handler/PreparedStatementHandler.java: -------------------------------------------------------------------------------- 1 | package com.wang.mybatis.handler; 2 | 3 | import java.lang.reflect.Method; 4 | import java.sql.Connection; 5 | import java.sql.PreparedStatement; 6 | import java.sql.SQLException; 7 | import java.util.List; 8 | 9 | import com.wang.mybatis.core.MapperHelper; 10 | import com.wang.mybatis.core.MethodDetails; 11 | import com.wang.mybatis.core.SqlSource; 12 | import com.wang.mybatis.transaction.TransactionManager; 13 | 14 | 15 | public class PreparedStatementHandler { 16 | private Method method; 17 | 18 | private TransactionManager transactionManager; 19 | 20 | private Connection connection; 21 | 22 | private Object[] args; 23 | 24 | public PreparedStatementHandler( TransactionManager transactionManager,Method method, Object[] args)throws SQLException { 25 | this.method = method; 26 | this.transactionManager = transactionManager; 27 | this.args = args; 28 | this.connection = transactionManager.getConnection(); 29 | } 30 | /** 31 | * 对method注解的sql语句进行解析,注入参数,获得PreparedStatement对象 32 | * @return 33 | * @throws SQLException 34 | */ 35 | public PreparedStatement generateStatement() throws SQLException{ 36 | MethodDetails methodDetails = MapperHelper.getMethodDetails(method); 37 | SqlSource sqlSource = methodDetails.getSqlSource(); 38 | Class[] clazzes = methodDetails.getParameterTypes(); 39 | List paramNames = methodDetails.getParameterNames(); 40 | List params = sqlSource.getParam(); 41 | List paramInjectTypes = sqlSource.getParamInjectType(); 42 | String sql = sqlSource.getSql(); 43 | //先对${ }参数进行字符串替换 44 | String parsedSql = parseSql(sql, clazzes, paramNames, params, paramInjectTypes, args); 45 | PreparedStatement preparedStatement = connection.prepareStatement(parsedSql); 46 | //再注入#{ }参数 47 | preparedStatement = typeInject(preparedStatement,clazzes,paramNames,params,paramInjectTypes,args); 48 | return preparedStatement; 49 | } 50 | /** 51 | * 对${ }参数进行字符串替换 52 | * @param sql 53 | * @param clazzes 54 | * @param paramNames 55 | * @param params 56 | * @param paramInjectTypes 57 | * @param args 58 | * @return 59 | */ 60 | private String parseSql(String sql,Class[] clazzes,List paramNames,List params,List paramInjectTypes,Object[] args) { 61 | StringBuilder sqlBuilder = new StringBuilder(sql); 62 | Integer index = sqlBuilder.indexOf("?"); 63 | Integer i = 0; 64 | while (index>0 && i type = clazzes[paramIndex]; 73 | String injectValue = ""; 74 | if(String.class.equals(type)) { 75 | injectValue = "'"+(String) arg + "'"; 76 | } 77 | else if (Integer.class.equals(type)) { 78 | injectValue = Integer.toString((Integer) arg); 79 | } 80 | else if (Float.class.equals(type)) { 81 | injectValue = Float.toString((Float) arg); 82 | } 83 | else if (Double.class.equals(type)) { 84 | injectValue = Double.toString((Double) arg); 85 | } 86 | else if (Long.class.equals(type)) { 87 | injectValue = Long.toString((Long) arg); 88 | } 89 | else if (Short.class.equals(type)) { 90 | injectValue = Short.toString((Short) arg); 91 | } 92 | sqlBuilder.replace(index, index+1, injectValue); 93 | index = sqlBuilder.indexOf("?"); 94 | i++; 95 | } 96 | return sqlBuilder.toString(); 97 | 98 | } 99 | 100 | /** 101 | *preparedStatement构建,注入#{ }参数 102 | * @Param preparedStatement 待构建的preparedStatement 103 | * @Param clazzes 该方法中参数类型数组 104 | * @Param paramNames 该方法中参数名称列表,若有@Param注解,则为此注解的值,默认为类名首字母小写 105 | * @Param params 待注入的参数名,如user.name或普通类型如name 106 | * @Param args 真实参数值 107 | **/ 108 | private PreparedStatement typeInject(PreparedStatement preparedStatement,Class[] clazzes,List paramNames,List params,List paramInjectTypes,Object[] args)throws SQLException{ 109 | for(int i = 0; i < paramNames.size(); i++){ 110 | String paramName = paramNames.get(i); 111 | Class type = clazzes[i]; 112 | int injectIndex = params.indexOf(paramName); 113 | if(paramInjectTypes.get(injectIndex)==0) { 114 | continue; 115 | } 116 | if(String.class.equals(type)){ 117 | //此处是判断sql中是否有待注入的名称({name})和方法内输入对象名(name)相同,若相同,则直接注入 118 | if(injectIndex >= 0){ 119 | preparedStatement.setString(injectIndex+1,(String)args[i]); 120 | } 121 | }else if(Integer.class.equals(type) || int.class.equals(type)){ 122 | if(injectIndex >= 0){ 123 | preparedStatement.setInt(injectIndex+1,(Integer)args[i]); 124 | } 125 | }else if(Float.class.equals(type) || float.class.equals(type)){ 126 | if(injectIndex >= 0){ 127 | preparedStatement.setFloat(injectIndex+1,(Float)args[i]); 128 | } 129 | } 130 | else if(Double.class.equals(type) || double.class.equals(type)){ 131 | if(injectIndex >= 0){ 132 | preparedStatement.setDouble(injectIndex+1,(Double)args[i]); 133 | } 134 | } 135 | else if(Long.class.equals(type) || long.class.equals(type)){ 136 | if(injectIndex >= 0){ 137 | preparedStatement.setLong(injectIndex+1,(Long)args[i]); 138 | } 139 | } 140 | } 141 | return preparedStatement; 142 | } 143 | /** 144 | * 关闭连接 145 | * @throws SQLException 146 | */ 147 | public void closeConnection() throws SQLException{ 148 | transactionManager.close(); 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /src/main/java/com/wang/mybatis/handler/ResultSetHandler.java: -------------------------------------------------------------------------------- 1 | package com.wang.mybatis.handler; 2 | 3 | import java.lang.reflect.Constructor; 4 | import java.lang.reflect.Field; 5 | import java.lang.reflect.Type; 6 | import java.math.BigDecimal; 7 | import java.sql.Date; 8 | import java.sql.ResultSet; 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | import com.mysql.jdbc.Blob; 13 | /** 14 | * 对结果集进行解析,完成对象关系映射 15 | * @author Administrator 16 | * 17 | */ 18 | public class ResultSetHandler { 19 | 20 | //转换的目标类型 21 | Class typeReturn; 22 | 23 | //待转换的ResultSet 24 | ResultSet resultSet; 25 | 26 | Boolean hasSet; 27 | 28 | public ResultSetHandler(Class typeReturn,ResultSet resultSet){ 29 | this.resultSet = resultSet; 30 | this.typeReturn = typeReturn; 31 | } 32 | /** 33 | * 将结果集resultSet映射为一个对象列表 34 | * @param 35 | * @return 36 | * @throws Exception 37 | */ 38 | public List handle() throws Exception{ 39 | List res = new ArrayList<>(); 40 | while (resultSet.next()){ 41 | /** 若返回是基础数据类型 */ 42 | if(String.class.equals(typeReturn)){ 43 | String val = resultSet.getString(1); 44 | if(val != null){ 45 | res.add((T)val); 46 | } 47 | } 48 | else if(Integer.class.equals(typeReturn) || int.class.equals(typeReturn)){ 49 | Integer val = resultSet.getInt(1); 50 | if(val != null){ 51 | res.add((T)val); 52 | } 53 | } 54 | else if(Float.class.equals(typeReturn) || float.class.equals(typeReturn)){ 55 | Float val = resultSet.getFloat(1); 56 | if(val != null){ 57 | res.add((T)val); 58 | } 59 | 60 | } 61 | else if(Double.class.equals(typeReturn) || double.class.equals(typeReturn)){ 62 | Double val = resultSet.getDouble(1); 63 | if(val != null){ 64 | res.add((T)val); 65 | } 66 | } 67 | else { 68 | Object val = generateObjFromResultSet(resultSet, typeReturn); 69 | if(val != null){ 70 | res.add((T)val); 71 | } 72 | } 73 | } 74 | return res; 75 | } 76 | /** 77 | * 生成具体对象,并对属性进行填充 78 | * @param resultSet 79 | * @param clazz 80 | * @return 81 | * @throws Exception 82 | */ 83 | private Object generateObjFromResultSet(ResultSet resultSet,Class clazz) throws Exception{ 84 | Constructor[] constructors = clazz.getConstructors(); 85 | Constructor usedConstructor = null; 86 | for(Constructor constructor:constructors){ 87 | if(constructor.getParameterCount() == 0){ 88 | usedConstructor = constructor; 89 | break; 90 | } 91 | } 92 | if(constructors == null) { 93 | throw new RuntimeException(typeReturn + " is not empty constructor"); 94 | } 95 | Object object = usedConstructor.newInstance(); 96 | Field[] fields = clazz.getDeclaredFields(); 97 | for (Field field : fields) { 98 | field.setAccessible(true); 99 | String fname = field.getName(); 100 | Type type = field.getGenericType(); 101 | if (type.equals(String.class)) { 102 | String column = resultSet.getString(fname); 103 | field.set(object, column); 104 | } 105 | else if (type.equals(Integer.class)) { 106 | Integer column = resultSet.getInt(fname); 107 | field.set(object, column); 108 | } 109 | else if (type.equals(Long.class)) { 110 | Long column = resultSet.getLong(fname); 111 | field.set(object, column); 112 | } 113 | else if (type.equals(Float.class)) { 114 | Float column = resultSet.getFloat(fname); 115 | field.set(object, column); 116 | } 117 | else if (type.equals(Double.class)) { 118 | Double column = resultSet.getDouble(fname); 119 | field.set(object, column); 120 | } 121 | else if (type.equals(BigDecimal.class)) { 122 | BigDecimal column = resultSet.getBigDecimal(fname); 123 | field.set(object, column); 124 | } 125 | else if (type.equals(Blob.class)) { 126 | Blob column = (Blob) resultSet.getBlob(fname); 127 | field.set(object, column); 128 | } 129 | else if (type.equals(Boolean.class)) { 130 | Boolean column = resultSet.getBoolean(fname); 131 | field.set(object, column); 132 | } 133 | else if (type.equals(Date.class)) { 134 | Date column = resultSet.getDate(fname); 135 | field.set(object, column); 136 | } 137 | else if (type.equals(byte[].class)) { 138 | byte[] column = resultSet.getBytes(fname); 139 | field.set(object, column); 140 | } 141 | } 142 | return object; 143 | } 144 | } -------------------------------------------------------------------------------- /src/main/java/com/wang/mybatis/transaction/SimpleTransactionManager.java: -------------------------------------------------------------------------------- 1 | package com.wang.mybatis.transaction; 2 | 3 | import java.sql.Connection; 4 | import java.sql.SQLException; 5 | import java.util.Stack; 6 | 7 | import com.wang.mybatis.datasource.DataSource; 8 | import com.wang.spring.constants.PropagationLevelConstant; 9 | 10 | public class SimpleTransactionManager implements TransactionManager{ 11 | 12 | //ThreadLocal对象保证每个线程对应唯一的数据库连接 13 | private ThreadLocal connectionThreadLocal = new ThreadLocal<>(); 14 | //上级事务连接缓存,使用栈可以保证多级事务的缓存 15 | private ThreadLocal> delayThreadLocal = new ThreadLocal<>(); 16 | //数据源 17 | private DataSource dataSource; 18 | //事务隔离级别,默认为可重复读 19 | private Integer level = Connection.TRANSACTION_REPEATABLE_READ; 20 | //是否自动提交 21 | private Boolean autoCommit = true; 22 | 23 | public SimpleTransactionManager(DataSource dataSource){ 24 | this(dataSource,null,null); 25 | } 26 | 27 | public SimpleTransactionManager(DataSource dataSource, Integer level, Boolean autoCommmit) { 28 | this.dataSource = dataSource; 29 | if(level != null){ 30 | this.level = level; 31 | } 32 | if(autoCommmit != null){ 33 | this.autoCommit = autoCommmit; 34 | } 35 | } 36 | /** 37 | * 获得连接对象,先从TreadLocal中获取,如果没有则获取一个新的连接 38 | */ 39 | @Override 40 | public Connection getConnection() throws SQLException{ 41 | Connection connection = connectionThreadLocal.get(); 42 | if(connection!=null && !connection.isClosed()){ 43 | return connection; 44 | } 45 | else { 46 | Connection tempConnection = dataSource.getConnection(); 47 | tempConnection.setAutoCommit(autoCommit); 48 | tempConnection.setTransactionIsolation(level); 49 | connectionThreadLocal.set(tempConnection); 50 | return tempConnection; 51 | } 52 | } 53 | /** 54 | * 当前事务是否存在,如果当前的Connection为非自动提交,说明存在 55 | */ 56 | public boolean isTransactionPresent() { 57 | Connection connection = connectionThreadLocal.get(); 58 | try { 59 | if(connection!=null && !connection.isClosed() && !connection.getAutoCommit()) { 60 | return true; 61 | } 62 | } catch (SQLException e) { 63 | // TODO Auto-generated catch block 64 | e.printStackTrace(); 65 | } 66 | return false; 67 | } 68 | 69 | /** 70 | * 开始事务,根据事务传播行为进行设置 71 | */ 72 | @Override 73 | public void beginTransaction(TransactionStatus status) throws SQLException { 74 | //PROPAGATION_REQUIRED:如果当前存在事务,则加入该事务,如果当前不存在事务,则创建一个新的事务。 75 | if(status.propagationLevel==PropagationLevelConstant.PROPAGATION_REQUIRED) { 76 | if(!status.isTrans) { 77 | doCreateTransaction(status.isolationLevel); 78 | } 79 | } 80 | //PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前不存在事务,则以非事务的方式继续运行。 81 | else if(status.propagationLevel==PropagationLevelConstant.PROPAGATION_SUPPORTS) { 82 | if(!status.isTrans) { 83 | //不需要创建事务,直接获取自动提交的连接,以非事务方式运行 84 | } 85 | } 86 | //PROPAGATION_MANDATORY:如果当前存在事务,则加入该事务;如果当前不存在事务,则抛出异常。 87 | else if (status.propagationLevel == PropagationLevelConstant.PROPAGATION_MANDATORY) { 88 | if(!status.isTrans) { 89 | throw new RuntimeException("事务传播方式为PROPAGATION_MANDATORY,但当前不存在事务"); 90 | } 91 | } 92 | //PROPAGATION_REQUIRES_NEW:重新创建一个新的事务,如果当前存在事务,延缓当前的事务。 93 | else if (status.propagationLevel == PropagationLevelConstant.PROPAGATION_REQUIRES_NEW) { 94 | if(status.isTrans) { 95 | //将当前事务保存在线程本地的栈中,暂缓执行 96 | if(delayThreadLocal.get()==null) { 97 | Stack stack = new Stack<>(); 98 | delayThreadLocal.set(stack); 99 | } 100 | Stack stack = delayThreadLocal.get(); 101 | stack.push(connectionThreadLocal.get()); 102 | delayThreadLocal.set(stack); 103 | connectionThreadLocal.remove(); 104 | } 105 | //新建一个新的事务 106 | doCreateTransaction(status.isolationLevel); 107 | } 108 | //PROPAGATION_NOT_SUPPORTED:以非事务的方式运行,如果当前存在事务,暂停当前的事务。 109 | else if (status.propagationLevel == PropagationLevelConstant.PROPAGATION_NOT_SUPPORTED) { 110 | if(status.isTrans) { 111 | //将当前事务保存在线程本地的栈中,暂缓执行 112 | if(delayThreadLocal.get()==null) { 113 | Stack stack = new Stack<>(); 114 | delayThreadLocal.set(stack); 115 | } 116 | Stack stack = delayThreadLocal.get(); 117 | stack.push(connectionThreadLocal.get()); 118 | delayThreadLocal.set(stack); 119 | //移除后会获取自动提交的连接 120 | connectionThreadLocal.remove(); 121 | } 122 | } 123 | //PROPAGATION_NEVER:以非事务的方式运行,如果当前存在事务,则抛出异常。 124 | else if (status.propagationLevel == PropagationLevelConstant.PROPAGATION_NEVER) { 125 | if(status.isTrans) { 126 | throw new RuntimeException("事务传播方式为PROPAGATION_NEVER,但当前存在事务"); 127 | } 128 | } 129 | //PROPAGATION_NESTED:如果没有,就新建一个事务;如果有,就在当前事务中嵌套其他事务。 130 | else if (status.propagationLevel == PropagationLevelConstant.PROPAGATION_NESTED) { 131 | if(!status.isTrans) { 132 | doCreateTransaction(status.isolationLevel); 133 | } 134 | } 135 | 136 | } 137 | /** 138 | * 新建一个事务。获取一个新的连接,设置位非自动提交,并存放在connectionThreadLocal中 139 | * @param level 140 | * @throws SQLException 141 | */ 142 | private void doCreateTransaction(Integer level) throws SQLException { 143 | Connection tempConnection = dataSource.getConnection(); 144 | tempConnection.setAutoCommit(false); 145 | if(level!=null) { 146 | tempConnection.setTransactionIsolation(level); 147 | } 148 | else { 149 | tempConnection.setTransactionIsolation(this.level); 150 | } 151 | connectionThreadLocal.set(tempConnection); 152 | } 153 | 154 | 155 | /** 156 | * 提交事务 157 | */ 158 | @Override 159 | public void commit(TransactionStatus status) throws SQLException{ 160 | //如果当前不存在上级事务,则提交事务 161 | if(!status.isTrans) { 162 | Connection connection = connectionThreadLocal.get(); 163 | if(connection != null && !connection.isClosed() && !connection.getAutoCommit()){ 164 | connection.commit(); 165 | } 166 | } 167 | //如果当前存在上级事务,且传播行为为PROPAGATION_REQUIRES_NEW或PROPAGATION_NESTED,也进行自动提交 168 | else if (status.isTrans && status.propagationLevel == PropagationLevelConstant.PROPAGATION_REQUIRES_NEW) { 169 | Connection connection = connectionThreadLocal.get(); 170 | if(connection != null && !connection.isClosed() && !connection.getAutoCommit()){ 171 | connection.commit(); 172 | } 173 | } 174 | else if (status.isTrans && status.propagationLevel == PropagationLevelConstant.PROPAGATION_NESTED) { 175 | Connection connection = connectionThreadLocal.get(); 176 | if(connection != null && !connection.isClosed() && !connection.getAutoCommit()){ 177 | connection.commit(); 178 | } 179 | } 180 | 181 | } 182 | /** 183 | * 回滚事务 184 | */ 185 | @Override 186 | public void rollback() throws SQLException{ 187 | //如果为非自动提交,则回滚事务 188 | Connection connection = connectionThreadLocal.get(); 189 | if(connection != null && !connection.isClosed() && !connection.getAutoCommit()){ 190 | connection.rollback(); 191 | } 192 | } 193 | /** 194 | * 普通的关闭链接,如果是自动提交才自动关闭连接 195 | */ 196 | @Override 197 | public void close() throws SQLException{ 198 | Connection connection = connectionThreadLocal.get(); 199 | //放回连接池 200 | if(connection != null && !connection.isClosed() && connection.getAutoCommit()){ 201 | dataSource.removeConnection(connection); 202 | //连接设为null 203 | connectionThreadLocal.remove(); 204 | } 205 | } 206 | 207 | /** 208 | * 关闭事务,恢复连接未自动提交和默认隔离级别,然后关闭连接,关闭链接前,若设置了自动提交为false,则必须进行回滚操作 209 | */ 210 | @Override 211 | public void closeTransaction(TransactionStatus status) throws SQLException{ 212 | Connection connection = connectionThreadLocal.get(); 213 | //如果当前不存在上级事务,且连接未非自动提交,则关闭事务 214 | if(!status.isTrans && connection != null && !connection.isClosed() && !connection.getAutoCommit()){ 215 | connection.rollback(); 216 | connection.setAutoCommit(autoCommit); 217 | connection.setTransactionIsolation(level); 218 | //放回连接池 219 | dataSource.removeConnection(connection); 220 | //清除线程本地变量 221 | connectionThreadLocal.remove(); 222 | } 223 | //如果当前存在上级事务,且传播行为为PROPAGATION_REQUIRES_NEW,则关闭事务,并且将上级事务连接恢复到connectionThreadLocal中 224 | else if (status.isTrans && status.propagationLevel == PropagationLevelConstant.PROPAGATION_REQUIRES_NEW) { 225 | connection.rollback(); 226 | connection.setAutoCommit(autoCommit); 227 | connection.setTransactionIsolation(level); 228 | dataSource.removeConnection(connection); 229 | connectionThreadLocal.remove(); 230 | //恢复上级事务连接 231 | connectionThreadLocal.set(delayThreadLocal.get().pop()); 232 | } 233 | //如果当前存在上级事务,且传播行为为PROPAGATION_NOT_SUPPORTED,则直接将上级事务连接恢复到connectionThreadLocal中 234 | else if (status.isTrans && status.propagationLevel == PropagationLevelConstant.PROPAGATION_NOT_SUPPORTED) { 235 | connectionThreadLocal.set(delayThreadLocal.get().pop()); 236 | } 237 | } 238 | /** 239 | * 设置事务隔离级别 240 | */ 241 | @Override 242 | public void setLevel(Integer level) { 243 | // TODO Auto-generated method stub 244 | this.level = level; 245 | } 246 | /** 247 | * 设置是否自动提交 248 | */ 249 | @Override 250 | public void setAutoCommit(Boolean autoCommit) { 251 | // TODO Auto-generated method stub 252 | this.autoCommit = autoCommit; 253 | } 254 | /** 255 | * 获得事务id,由于一个事务对应唯一一个连接,因此返回的是连接名 256 | */ 257 | @Override 258 | public String getTransactionId() { 259 | // TODO Auto-generated method stub 260 | Connection connection = connectionThreadLocal.get(); 261 | String transactionId = null; 262 | try { 263 | if(connection != null && !connection.isClosed() && !connection.getAutoCommit()) { 264 | transactionId = connection.toString(); 265 | } 266 | } catch (SQLException e) { 267 | // TODO: handle exception 268 | e.printStackTrace(); 269 | } 270 | 271 | return transactionId; 272 | } 273 | } -------------------------------------------------------------------------------- /src/main/java/com/wang/mybatis/transaction/TransactionFactory.java: -------------------------------------------------------------------------------- 1 | package com.wang.mybatis.transaction; 2 | 3 | import com.wang.mybatis.datasource.DataSource; 4 | import com.wang.mybatis.datasource.NormalDataSource; 5 | import com.wang.mybatis.datasource.PoolDataSource; 6 | import com.wang.spring.utils.ConfigUtil; 7 | 8 | /** 9 | * TransactionManager工厂类 10 | * @author Administrator 11 | * 12 | */ 13 | public class TransactionFactory { 14 | private static volatile TransactionManager transaction = null; 15 | /** 16 | * 生成一个TransactionManager实例,并且是单例的 17 | * @param level 18 | * @param autoCommmit 19 | * @return 20 | */ 21 | public static TransactionManager newTransaction(Integer level, Boolean autoCommmit){ 22 | if(transaction==null) { 23 | synchronized (TransactionManager.class) { 24 | if(transaction==null){ 25 | DataSource dataSource = null; 26 | //根据配置决定是否使用数据库连接池 27 | if(ConfigUtil.isDataSourcePool()) { 28 | dataSource =new PoolDataSource(ConfigUtil.getJdbcDriver(), ConfigUtil.getJdbcUrl(), ConfigUtil.getJdbcUsername(), ConfigUtil.getJdbcPassword(), 29 | ConfigUtil.getDataSourcePoolMaxSize(),ConfigUtil.getDataSourcePoolWaitTimeMill()); 30 | } 31 | else { 32 | dataSource = new NormalDataSource(ConfigUtil.getJdbcDriver(), ConfigUtil.getJdbcUrl(), ConfigUtil.getJdbcUsername(), ConfigUtil.getJdbcPassword()); 33 | } 34 | 35 | transaction = new SimpleTransactionManager(dataSource,level,autoCommmit); 36 | return transaction; 37 | } 38 | } 39 | } 40 | return transaction; 41 | } 42 | 43 | public static TransactionManager newTransaction(){ 44 | if(transaction==null) { 45 | synchronized (TransactionManager.class) { 46 | if(transaction==null){ 47 | DataSource dataSource = null; 48 | if(ConfigUtil.isDataSourcePool()) { 49 | dataSource =new PoolDataSource(ConfigUtil.getJdbcDriver(), ConfigUtil.getJdbcUrl(), ConfigUtil.getJdbcUsername(), ConfigUtil.getJdbcPassword(), 50 | ConfigUtil.getDataSourcePoolMaxSize(),ConfigUtil.getDataSourcePoolWaitTimeMill()); 51 | } 52 | else { 53 | dataSource = new NormalDataSource(ConfigUtil.getJdbcDriver(), ConfigUtil.getJdbcUrl(), ConfigUtil.getJdbcUsername(), ConfigUtil.getJdbcPassword()); 54 | } 55 | transaction = new SimpleTransactionManager(dataSource); 56 | return transaction; 57 | } 58 | } 59 | } 60 | return transaction; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/wang/mybatis/transaction/TransactionManager.java: -------------------------------------------------------------------------------- 1 | package com.wang.mybatis.transaction; 2 | 3 | import java.sql.Connection; 4 | import java.sql.SQLException; 5 | 6 | public interface TransactionManager { 7 | //获取链接 8 | Connection getConnection() throws SQLException; 9 | //当前是否存在事务 10 | public boolean isTransactionPresent(); 11 | //开启事务 12 | public void beginTransaction(TransactionStatus status) throws SQLException; 13 | //提交事务 14 | void commit(TransactionStatus status) throws SQLException; 15 | //回滚事务 16 | void rollback() throws SQLException; 17 | //关闭连接 18 | void close() throws SQLException; 19 | //关闭事务 20 | void closeTransaction(TransactionStatus status) throws SQLException; 21 | //设置事务隔离级别 22 | void setLevel(Integer level); 23 | //设置是否自动提交 24 | void setAutoCommit(Boolean autoCommit); 25 | //获取事务id 26 | String getTransactionId(); 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/wang/mybatis/transaction/TransactionStatus.java: -------------------------------------------------------------------------------- 1 | package com.wang.mybatis.transaction; 2 | 3 | public class TransactionStatus { 4 | //是否需要开启事务 5 | public Boolean isNeed; 6 | //当前是否存在事务 7 | public Boolean isTrans; 8 | //事务隔离级别 9 | public Integer isolationLevel; 10 | //事务传播级别 11 | public Integer propagationLevel; 12 | //回滚异常类型 13 | public Class[] rollbackFor; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/annotation/aop/After.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.annotation.aop; 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 After { 12 | String value() default ""; 13 | int order() default -1; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/annotation/aop/AfterReturning.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.annotation.aop; 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 AfterReturning { 12 | String value() default ""; 13 | int order() default -1; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/annotation/aop/AfterThrowing.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.annotation.aop; 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 AfterThrowing { 12 | String value() default ""; 13 | int order() default -1; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/annotation/aop/Around.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.annotation.aop; 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 Around { 12 | String value() default ""; 13 | int order() default -1; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/annotation/aop/Aspect.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.annotation.aop; 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 | @Retention(RUNTIME) 10 | @Target(TYPE) 11 | public @interface Aspect { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/annotation/aop/Before.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.annotation.aop; 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 Before { 12 | String value() default ""; 13 | int order() default -1; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/annotation/aop/Pointcut.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.annotation.aop; 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 Pointcut { 12 | String value() default ""; 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/annotation/aop/Transactional.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.annotation.aop; 2 | 3 | import static java.lang.annotation.ElementType.METHOD; 4 | import static java.lang.annotation.ElementType.TYPE; 5 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 6 | 7 | import java.lang.annotation.Retention; 8 | import java.lang.annotation.Target; 9 | import java.sql.Connection; 10 | 11 | import com.wang.spring.constants.IsolationLevelConstant; 12 | import com.wang.spring.constants.PropagationLevelConstant; 13 | 14 | @Retention(RUNTIME) 15 | @Target({ TYPE, METHOD }) 16 | public @interface Transactional { 17 | int Isolation() default IsolationLevelConstant.TRANSACTION_REPEATABLE_READ; 18 | 19 | int Propagation() default PropagationLevelConstant.PROPAGATION_REQUIRED; 20 | 21 | Class[] rollbackFor() default {Error.class,RuntimeException.class}; 22 | 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/annotation/ioc/Autowired.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.annotation.ioc; 2 | 3 | import static java.lang.annotation.ElementType.FIELD; 4 | import static java.lang.annotation.ElementType.LOCAL_VARIABLE; 5 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 6 | 7 | import java.lang.annotation.Documented; 8 | import java.lang.annotation.Retention; 9 | import java.lang.annotation.Target; 10 | 11 | @Documented 12 | @Retention(RUNTIME) 13 | @Target({ FIELD, LOCAL_VARIABLE }) 14 | public @interface Autowired { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/annotation/ioc/Bean.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.annotation.ioc; 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 Bean { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/annotation/ioc/Component.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.annotation.ioc; 2 | 3 | import static java.lang.annotation.ElementType.TYPE; 4 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 5 | 6 | import java.lang.annotation.Documented; 7 | import java.lang.annotation.Retention; 8 | import java.lang.annotation.Target; 9 | 10 | @Documented 11 | @Retention(RUNTIME) 12 | @Target(TYPE) 13 | public @interface Component { 14 | String value() default ""; 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/annotation/ioc/Configuration.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.annotation.ioc; 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 | @Retention(RUNTIME) 10 | @Target(TYPE) 11 | @Component 12 | public @interface Configuration { 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/annotation/ioc/Qualifier.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.annotation.ioc; 2 | 3 | import static java.lang.annotation.ElementType.FIELD; 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(FIELD) 11 | public @interface Qualifier { 12 | String value() default ""; 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/annotation/ioc/Resource.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.annotation.ioc; 2 | 3 | import static java.lang.annotation.ElementType.FIELD; 4 | import static java.lang.annotation.ElementType.TYPE; 5 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 6 | 7 | import java.lang.annotation.Retention; 8 | import java.lang.annotation.Target; 9 | 10 | @Retention(RUNTIME) 11 | @Target({ TYPE, FIELD }) 12 | public @interface Resource { 13 | String name() default ""; 14 | Class type() default java.lang.Object.class; 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/annotation/ioc/Service.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.annotation.ioc; 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 | @Retention(RUNTIME) 10 | @Target(TYPE) 11 | @Component 12 | public @interface Service { 13 | String value() default ""; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/annotation/ioc/Value.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.annotation.ioc; 2 | 3 | import static java.lang.annotation.ElementType.FIELD; 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(FIELD) 11 | public @interface Value { 12 | String value() default ""; 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/annotation/mvc/Controller.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.annotation.mvc; 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 Controller { 15 | String value() default ""; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/annotation/mvc/PathVariable.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.annotation.mvc; 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 PathVariable { 12 | String value() default ""; 13 | 14 | String defaultValue() default ""; 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/annotation/mvc/RequestBody.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.annotation.mvc; 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 RequestBody { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/annotation/mvc/RequestMapping.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.annotation.mvc; 2 | 3 | import static java.lang.annotation.ElementType.METHOD; 4 | import static java.lang.annotation.ElementType.TYPE; 5 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 6 | import java.lang.annotation.Retention; 7 | import java.lang.annotation.Target; 8 | import com.wang.spring.constants.RequestMethod; 9 | 10 | @Retention(RUNTIME) 11 | @Target({ TYPE, METHOD }) 12 | public @interface RequestMapping { 13 | String value() default ""; 14 | 15 | RequestMethod method() default RequestMethod.GET; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/annotation/mvc/RequestParam.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.annotation.mvc; 2 | 3 | import static java.lang.annotation.ElementType.PARAMETER; 4 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RUNTIME) 9 | @Target(PARAMETER) 10 | public @interface RequestParam { 11 | String value() default ""; 12 | 13 | String defaultValue() default ""; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/annotation/mvc/ResponseBody.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.annotation.mvc; 2 | 3 | import static java.lang.annotation.ElementType.METHOD; 4 | import static java.lang.annotation.ElementType.TYPE; 5 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 6 | 7 | import java.lang.annotation.Retention; 8 | import java.lang.annotation.Target; 9 | 10 | @Retention(RUNTIME) 11 | @Target({ TYPE, METHOD }) 12 | public @interface ResponseBody { 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/aop/AOPHelper.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.aop; 2 | 3 | import java.lang.reflect.Method; 4 | import java.util.ArrayList; 5 | import java.util.Collections; 6 | import java.util.Comparator; 7 | import java.util.HashMap; 8 | import java.util.List; 9 | import java.util.Map; 10 | import java.util.Set; 11 | import java.util.concurrent.ConcurrentHashMap; 12 | import org.apache.commons.collections4.map.HashedMap; 13 | 14 | import com.wang.spring.annotation.aop.After; 15 | import com.wang.spring.annotation.aop.AfterReturning; 16 | import com.wang.spring.annotation.aop.AfterThrowing; 17 | import com.wang.spring.annotation.aop.Around; 18 | import com.wang.spring.annotation.aop.Aspect; 19 | import com.wang.spring.annotation.aop.Before; 20 | import com.wang.spring.annotation.aop.Pointcut; 21 | import com.wang.spring.constants.AdviceTypeConstant; 22 | import com.wang.spring.ioc.BeanDefinition; 23 | import com.wang.spring.ioc.BeanDefinitionRegistry; 24 | import com.wang.spring.ioc.ClassSetHelper; 25 | import com.wang.spring.ioc.DefaultBeanFactory; 26 | import com.wang.spring.ioc.GenericBeanDefinition; 27 | 28 | public class AOPHelper { 29 | private static volatile AOPHelper aopHelper=null; 30 | //需要代理的目标类和目标方法的映射 31 | private static Map, List> classMethodMap= new ConcurrentHashMap<>(); 32 | //需要代理的目标方法和增强类的映射,value的map的key为通知的类型 33 | private static Map>> methodAdvicesMap = new ConcurrentHashMap<>(); 34 | /** 35 | * 初始化aop助手 36 | */ 37 | static { 38 | try { 39 | AOPHelper.init(); 40 | } catch (Exception e) { 41 | // TODO Auto-generated catch block 42 | e.printStackTrace(); 43 | } 44 | } 45 | private AOPHelper() {} 46 | /** 47 | * 获得AOPHelper的单例 48 | * @return 49 | */ 50 | public static AOPHelper getInstance() { 51 | if(aopHelper==null) { 52 | synchronized (AOPHelper.class) { 53 | if(aopHelper==null) { 54 | aopHelper = new AOPHelper(); 55 | return aopHelper; 56 | } 57 | } 58 | } 59 | return aopHelper; 60 | } 61 | /** 62 | * AOP助手初始化方法,扫描有@Aspect注解的类,获取代理目标和增强的映射 63 | * @throws Exception 64 | */ 65 | public static void init() throws Exception { 66 | Set> aspectClassSet = ClassSetHelper.getClassSetByAnnotation(Aspect.class); 67 | for(Class aspectClass : aspectClassSet) { 68 | Map pointcuts = new HashedMap<>(); 69 | Object aspect = aspectClass.getDeclaredConstructor().newInstance(); 70 | for(Method method:aspectClass.getMethods()) { 71 | if(method.isAnnotationPresent(Pointcut.class)) { 72 | String pointcutName = method.getName(); 73 | String pointcut = method.getAnnotation(Pointcut.class).value(); 74 | if(pointcut!=null && !pointcut.equals("")) { 75 | pointcuts.put(pointcutName, pointcut); 76 | } 77 | } 78 | } 79 | for(Method method:aspectClass.getMethods()) { 80 | injectMethodAdvices(aspect, method, pointcuts); 81 | } 82 | } 83 | //对增强类根据注解的order进行排序 84 | for(Method method:methodAdvicesMap.keySet()) { 85 | for(String key:methodAdvicesMap.get(method).keySet()) { 86 | Collections.sort(methodAdvicesMap.get(method).get(key), new Comparator() { 87 | @Override 88 | public int compare(Advice o1, Advice o2) { 89 | // TODO Auto-generated method stub 90 | if(o1.getOrder()==o2.getOrder()) { 91 | return 0; 92 | } 93 | else if (o1.getOrder()>o2.getOrder()) { 94 | return 1; 95 | } 96 | else { 97 | return -1; 98 | } 99 | } 100 | }); 101 | } 102 | } 103 | //重新注册需要增强的类,注入代理类 104 | try { 105 | CGLibProxy cgLibProxy = new CGLibProxy(methodAdvicesMap); 106 | for(Class cls:classMethodMap.keySet()) { 107 | BeanDefinition beanDefinition=null; 108 | if(BeanDefinitionRegistry.containsBeanDefinition(cls.getName())) { 109 | beanDefinition = BeanDefinitionRegistry.getBeanDefinition(cls.getName()); 110 | } 111 | else { 112 | beanDefinition = new GenericBeanDefinition(); 113 | beanDefinition.setBeanClass(cls); 114 | } 115 | beanDefinition.setIsProxy(true); 116 | beanDefinition.setProxy(cgLibProxy); 117 | BeanDefinitionRegistry.registryBeanDefinition(cls.getName(), beanDefinition); 118 | System.out.println("AOPHelper 注册 "+cls.getName()); 119 | } 120 | //DefaultBeanFactory.getInstance().refresh(); 121 | } catch (Exception e) { 122 | // TODO Auto-generated catch block 123 | e.printStackTrace(); 124 | } 125 | } 126 | /** 127 | * 获取相应的映射 128 | * @return 129 | */ 130 | public static Map, List> getClassMethodMap() { 131 | return classMethodMap; 132 | } 133 | public static Map>> getMethodAdvicesMap() { 134 | return methodAdvicesMap; 135 | } 136 | 137 | /** 138 | * 为目标类和方法找到相应的增强列表(Advice) 139 | * @param aspect 140 | * @param method 141 | * @param pointcuts 142 | * @throws Exception 143 | */ 144 | private static void injectMethodAdvices(Object aspect,Method method,Map pointcuts) throws Exception { 145 | String pointValue=null; 146 | String pointType = null; 147 | Integer order = -1; 148 | if(method.isAnnotationPresent(Before.class)) { 149 | pointValue = (method.getAnnotation(Before.class)).value(); 150 | order = (method.getAnnotation(Before.class)).order(); 151 | pointType = AdviceTypeConstant.BEFORE; 152 | } 153 | else if(method.isAnnotationPresent(After.class)) { 154 | pointValue = (method.getAnnotation(After.class)).value(); 155 | order = (method.getAnnotation(After.class)).order(); 156 | pointType = AdviceTypeConstant.AFTER; 157 | } 158 | else if(method.isAnnotationPresent(Around.class)) { 159 | pointValue = (method.getAnnotation(Around.class)).value(); 160 | order = (method.getAnnotation(Around.class)).order(); 161 | pointType = AdviceTypeConstant.AROUND; 162 | } 163 | else if(method.isAnnotationPresent(AfterReturning.class)) { 164 | pointValue = (method.getAnnotation(AfterReturning.class)).value(); 165 | order = (method.getAnnotation(AfterReturning.class)).order(); 166 | pointType = AdviceTypeConstant.AFTERRETURNING; 167 | } 168 | else if(method.isAnnotationPresent(AfterThrowing.class)) { 169 | pointValue = (method.getAnnotation(AfterThrowing.class)).value(); 170 | order = (method.getAnnotation(AfterThrowing.class)).order(); 171 | pointType = AdviceTypeConstant.AFTERTHROWING; 172 | } 173 | else { 174 | //System.out.println(method.getName()+" 不是增强"); 175 | return; 176 | } 177 | pointValue = parsePointValue(pointcuts, pointValue); 178 | 179 | Map classAndMethod = getClassAndMethod(pointValue); 180 | try { 181 | Class targetClass = Class.forName(classAndMethod.get("class")); 182 | if(!classMethodMap.containsKey(targetClass)) { 183 | classMethodMap.put(targetClass,new ArrayList()); 184 | } 185 | for(Method method2:targetClass.getMethods()) { 186 | if(classAndMethod.get("method").equals("*") || classAndMethod.get("method").equals(method2.getName())) { 187 | classMethodMap.get(targetClass).add(method2); 188 | Advice advice = new Advice(aspect, method,order); 189 | if(!methodAdvicesMap.containsKey(method2)) { 190 | methodAdvicesMap.put(method2, new HashedMap>()); 191 | } 192 | if(!methodAdvicesMap.get(method2).containsKey(pointType)) { 193 | methodAdvicesMap.get(method2).put(pointType, new ArrayList()); 194 | } 195 | methodAdvicesMap.get(method2).get(pointType).add(advice); 196 | } 197 | } 198 | } catch (Exception e) { 199 | // TODO: handle exception 200 | e.printStackTrace(); 201 | } 202 | } 203 | 204 | /** 205 | * 获得切点的值,可能直接在通知上定义,也可能在pointcut定义 206 | * @param pointcuts 207 | * @param pointValue 208 | * @return 209 | * @throws Exception 210 | */ 211 | private static String parsePointValue(Map pointcuts,String pointValue) throws Exception { 212 | if(pointValue==null || pointValue.equals("")) { 213 | return null; 214 | } 215 | String result = null; 216 | if(pointValue.endsWith("()")) { 217 | String pointcutName = pointValue.replace("()", ""); 218 | if(!pointcuts.containsKey(pointcutName)) { 219 | throw new Exception(pointValue+" 未定义"); 220 | } 221 | result = pointcuts.get(pointcutName); 222 | } 223 | else { 224 | result = pointValue; 225 | } 226 | return result; 227 | } 228 | /** 229 | * 解析切点全限量名,获得代理的目标类和方法 230 | * @param value 231 | * @return 232 | */ 233 | private static Map getClassAndMethod(String value) { 234 | Map map = new HashMap(); 235 | String[] split = value.split("\\."); 236 | if (split.length == 0) { 237 | throw new RuntimeException("全限量名解析异常"); 238 | } 239 | StringBuilder stringBuilder = new StringBuilder(); 240 | for (int i = 0; i < split.length - 1; i++) { 241 | if (i == split.length - 2) { 242 | stringBuilder.append(split[i]); 243 | } else { 244 | stringBuilder.append(split[i] + "."); 245 | } 246 | } 247 | map.put("class", stringBuilder.toString()); 248 | map.put("method", split[split.length - 1]); 249 | return map; 250 | } 251 | } 252 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/aop/Advice.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.aop; 2 | 3 | import java.lang.reflect.Method; 4 | /** 5 | * 增强类 6 | * @author Administrator 7 | * 8 | */ 9 | public class Advice { 10 | //切面对象 11 | private Object aspect; 12 | //增强方法 13 | private Method adviceMethod; 14 | //级别,一个方法有多个增强时根据级别排序 15 | private Integer order; 16 | private String throwName; 17 | public Advice(Object aspect, Method adviceMethod,Integer order) { 18 | this.aspect = aspect; 19 | this.adviceMethod = adviceMethod; 20 | this.order = order; 21 | } 22 | 23 | public Object getAspect() { 24 | return aspect; 25 | } 26 | public void setAspect(Object aspect) { 27 | this.aspect=aspect; 28 | } 29 | 30 | public Method getAdviceMethod() { 31 | return adviceMethod; 32 | } 33 | public void setAdviceMethod(Method adviceMethod) { 34 | this.adviceMethod=adviceMethod; 35 | } 36 | 37 | public String getThrowName() { 38 | return throwName; 39 | } 40 | public void setThrowName(String throwName) { 41 | this.throwName=throwName; 42 | } 43 | 44 | public Integer getOrder() { 45 | return order; 46 | } 47 | public void setOrder(Integer order) { 48 | this.order=order; 49 | } 50 | } -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/aop/CGLibProxy.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.aop; 2 | 3 | import java.lang.reflect.Method; 4 | import java.sql.SQLException; 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | import com.wang.mybatis.transaction.TransactionFactory; 9 | import com.wang.mybatis.transaction.TransactionManager; 10 | import com.wang.mybatis.transaction.TransactionStatus; 11 | import com.wang.spring.annotation.aop.Transactional; 12 | import com.wang.spring.common.MyProxy; 13 | import com.wang.spring.constants.AdviceTypeConstant; 14 | 15 | import net.sf.cglib.proxy.Enhancer; 16 | import net.sf.cglib.proxy.MethodInterceptor; 17 | import net.sf.cglib.proxy.MethodProxy; 18 | /** 19 | * 使用CGLib实现的代理类,对目标进行增强 20 | * @author Administrator 21 | * 22 | */ 23 | public class CGLibProxy implements MethodInterceptor,MyProxy{ 24 | //目标代理方法和增强列表的映射 25 | Map>> methodAdvicesMap=null; 26 | //事务管理器 27 | TransactionManager transactionManager = TransactionFactory.newTransaction(); 28 | 29 | public CGLibProxy(Map>> methodAdvicesMap) { 30 | // TODO Auto-generated constructor stub 31 | this.methodAdvicesMap=methodAdvicesMap; 32 | } 33 | /** 34 | * 通过CGLib库生成代理类 35 | * @param cls 36 | * @return 37 | */ 38 | @Override 39 | public Object getProxy(Class cls) { 40 | Enhancer enhancer = new Enhancer(); 41 | enhancer.setSuperclass(cls); 42 | enhancer.setCallback(this); 43 | return enhancer.create(); 44 | } 45 | /** 46 | * 拦截目标代理方法,对目标方法进行增强 47 | */ 48 | @Override 49 | public Object intercept(Object object, Method method, Object[] arg2, MethodProxy methodProxy) throws Throwable { 50 | Object result=null; 51 | TransactionStatus status = geTransactionStatus(object, method); 52 | status.isTrans = transactionManager.isTransactionPresent(); 53 | //判断是否增强 54 | Map> advices = methodAdvicesMap.get(method); 55 | try { 56 | //前置增强 57 | invokeAdvice(method,advices,AdviceTypeConstant.BEFORE); 58 | //环绕增强 59 | System.out.println("当前事务是否存在:"+status.isTrans); 60 | if(isAdviceNeed(method) && advices!=null && advices.containsKey(AdviceTypeConstant.AROUND)) { 61 | List aroundAdvices = advices.get(AdviceTypeConstant.AROUND); 62 | if(aroundAdvices!=null && !aroundAdvices.isEmpty()) { 63 | Advice advice = aroundAdvices.get(0); 64 | JoinPoint joinPoint = new JoinPoint(object, methodProxy, arg2); 65 | Method adviceMethod = advice.getAdviceMethod(); 66 | Object aspect = advice.getAspect(); 67 | try { 68 | //开启事务 69 | beginTransaction(status); 70 | //执行方法 71 | result=adviceMethod.invoke(aspect,joinPoint); 72 | //提交事务 73 | commitTransaction(status); 74 | } catch (Throwable e) { 75 | e.printStackTrace(); 76 | //回滚事务 77 | for(Class th:status.rollbackFor) { 78 | if(th.isAssignableFrom(e.getClass())) { 79 | rollbackTransaction(status); 80 | } 81 | } 82 | 83 | } 84 | finally { 85 | //释放事务 86 | closeTransaction(status); 87 | } 88 | 89 | } 90 | else { 91 | try { 92 | //开启事务 93 | beginTransaction(status); 94 | result= methodProxy.invokeSuper(object, arg2); 95 | commitTransaction(status); 96 | } catch (Throwable e) { 97 | e.printStackTrace(); 98 | //回滚事务 99 | for(Class th:status.rollbackFor) { 100 | if(th.isAssignableFrom(e.getClass())) { 101 | rollbackTransaction(status); 102 | } 103 | } 104 | } 105 | finally { 106 | closeTransaction(status); 107 | } 108 | 109 | } 110 | } 111 | else { 112 | try { 113 | //开启事务 114 | beginTransaction(status); 115 | result= methodProxy.invokeSuper(object, arg2); 116 | commitTransaction(status); 117 | } catch (Throwable e) { 118 | e.printStackTrace(); 119 | //回滚事务 120 | for(Class th:status.rollbackFor) { 121 | if(th.isAssignableFrom(e.getClass())) { 122 | rollbackTransaction(status); 123 | } 124 | } 125 | } 126 | finally { 127 | closeTransaction(status); 128 | } 129 | } 130 | //后置增强 131 | invokeAdvice(method,advices, AdviceTypeConstant.AFTER); 132 | } 133 | catch (Exception e) { 134 | // TODO: handle exception 135 | e.printStackTrace(); 136 | //异常增强 137 | invokeAdvice(method,advices, AdviceTypeConstant.AFTERTHROWING); 138 | } 139 | finally { 140 | //返回前增强 141 | invokeAdvice(method,advices, AdviceTypeConstant.AFTERRETURNING); 142 | } 143 | return result; 144 | } 145 | //执行通知增强 146 | private void invokeAdvice(Method method,Map> advices,String type) throws Throwable { 147 | if(isAdviceNeed(method) && advices!=null && advices.containsKey(type)) { 148 | List adviceList=advices.get(type); 149 | if(adviceList!=null && !adviceList.isEmpty()) { 150 | for(Advice advice:adviceList) { 151 | Method adviceMethod = advice.getAdviceMethod(); 152 | Object aspect = advice.getAspect(); 153 | adviceMethod.invoke(aspect); 154 | } 155 | } 156 | } 157 | 158 | } 159 | /** 160 | * 判断是否增强 161 | * @param method 162 | * @return 163 | */ 164 | private boolean isAdviceNeed(Method method) { 165 | return methodAdvicesMap.containsKey(method); 166 | } 167 | /** 168 | * 获得TransactionStatus对象 169 | * @param object 170 | * @param method 171 | * @return 172 | */ 173 | private TransactionStatus geTransactionStatus(Object object,Method method) { 174 | TransactionStatus status = new TransactionStatus(); 175 | status.isNeed = false; 176 | if(transactionManager!=null && (object.getClass().isAnnotationPresent(Transactional.class) || method.isAnnotationPresent(Transactional.class))) { 177 | status.isNeed = true; 178 | if(object.getClass().isAnnotationPresent(Transactional.class)) { 179 | Transactional transactional = object.getClass().getAnnotation(Transactional.class); 180 | status.isolationLevel = transactional.Isolation(); 181 | status.propagationLevel = transactional.Propagation(); 182 | status.rollbackFor = transactional.rollbackFor(); 183 | } 184 | if(method.isAnnotationPresent(Transactional.class)){ 185 | Transactional transactional = method.getAnnotation(Transactional.class); 186 | status.isolationLevel = transactional.Isolation(); 187 | status.propagationLevel = transactional.Propagation(); 188 | status.rollbackFor = transactional.rollbackFor(); 189 | } 190 | } 191 | return status; 192 | } 193 | /** 194 | * 判断是否需要事务管理 195 | * @param status 196 | * @return 197 | */ 198 | private boolean isTrasactionNeed(TransactionStatus status) { 199 | return status.isNeed; 200 | } 201 | /** 202 | * 开启事务 203 | * @param status 204 | * @throws SQLException 205 | */ 206 | private void beginTransaction(TransactionStatus status) throws SQLException { 207 | if(isTrasactionNeed(status)) { 208 | transactionManager.beginTransaction(status); 209 | System.out.println("开启事务,事务Id="+transactionManager.getTransactionId()); 210 | } 211 | } 212 | /** 213 | * 提交事务 214 | * @param status 215 | * @throws SQLException 216 | */ 217 | private void commitTransaction(TransactionStatus status) throws SQLException { 218 | if(isTrasactionNeed(status)) { 219 | transactionManager.commit(status); 220 | System.out.println("提交事务,事务Id="+transactionManager.getTransactionId()); 221 | } 222 | } 223 | /** 224 | * 回滚事务 225 | * @param status 226 | * @throws SQLException 227 | */ 228 | private void rollbackTransaction(TransactionStatus status) throws SQLException { 229 | if(isTrasactionNeed(status)) { 230 | transactionManager.rollback(); 231 | System.out.println("回滚事务,事务Id="+transactionManager.getTransactionId()); 232 | } 233 | } 234 | /** 235 | * 关闭事务 236 | * @param status 237 | * @throws SQLException 238 | */ 239 | private void closeTransaction(TransactionStatus status) throws SQLException { 240 | if(isTrasactionNeed(status)) { 241 | System.out.println("关闭事务,事务Id="+transactionManager.getTransactionId()); 242 | transactionManager.closeTransaction(status); 243 | } 244 | } 245 | } 246 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/aop/JoinPoint.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.aop; 2 | 3 | import java.lang.reflect.Method; 4 | import net.sf.cglib.proxy.MethodProxy; 5 | /** 6 | * 连接点类 7 | * @author Administrator 8 | * 9 | */ 10 | public class JoinPoint { 11 | private Object target=null; 12 | private Method method=null; 13 | //目标方法的代理 14 | private MethodProxy methodProxy=null; 15 | private Object[] args=null; 16 | public JoinPoint(Object target, Method method,Object[] args) { 17 | this.target = target; 18 | this.method = method; 19 | this.args = args; 20 | } 21 | 22 | public JoinPoint(Object target, Method method) { 23 | this.target = target; 24 | this.method = method; 25 | } 26 | 27 | public JoinPoint(Object object, MethodProxy methodProxy, Object[] args) { 28 | // TODO Auto-generated constructor stub 29 | this.target = object; 30 | this.methodProxy = methodProxy; 31 | this.args = args; 32 | } 33 | 34 | public JoinPoint(Object object, MethodProxy methodProxy) { 35 | // TODO Auto-generated constructor stub 36 | this.target = object; 37 | this.methodProxy = methodProxy; 38 | } 39 | /** 40 | * 执行无参的连接点方法 41 | * @return 42 | * @throws Throwable 43 | */ 44 | public Object proceed() throws Throwable{ 45 | Object result; 46 | if(methodProxy!=null) { 47 | result=methodProxy.invokeSuper(target, this.args); 48 | } 49 | else { 50 | if(this.args==null) { 51 | result=method.invoke(target); 52 | } 53 | else { 54 | result=method.invoke(target, this.args); 55 | } 56 | } 57 | 58 | return result; 59 | } 60 | /** 61 | * 执行带参的连接点方法 62 | * @param args 63 | * @return 64 | * @throws Throwable 65 | */ 66 | public Object proceed(Object[] args) throws Throwable{ 67 | if(methodProxy!=null) { 68 | return methodProxy.invokeSuper(target, args); 69 | } 70 | else { 71 | return method.invoke(target, args); 72 | } 73 | } 74 | 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/common/MyProxy.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.common; 2 | /** 3 | * 代理接口 4 | * @author Administrator 5 | * 6 | */ 7 | public interface MyProxy { 8 | public Object getProxy(Class cls); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/constants/AdviceTypeConstant.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.constants; 2 | /** 3 | * 通知类型常量 4 | * @author Administrator 5 | * 6 | */ 7 | public class AdviceTypeConstant { 8 | public static final String BEFORE = "before"; 9 | public static final String AROUND = "around"; 10 | public static final String AFTER = "after"; 11 | public static final String AFTERTHROWING = "afterThrowing"; 12 | public static final String AFTERRETURNING = "afterReturning"; 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/constants/BeanScope.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.constants; 2 | /** 3 | * Bean作用域常量 4 | * @author Administrator 5 | * 6 | */ 7 | public enum BeanScope { 8 | SINGLETON, 9 | PROTOTYPE 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/constants/ConfigConstant.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.constants; 2 | /** 3 | * 配置参数名常量 4 | * @author Administrator 5 | * 6 | */ 7 | public class ConfigConstant { 8 | //配置文件的名称 9 | public static final String CONFIG_FILE = "application.properties"; 10 | 11 | //数据源 12 | public static final String JDBC_DRIVER = "myspring.datasource.jdbc.driver"; 13 | public static final String JDBC_URL = "myspring.datasource.jdbc.url"; 14 | public static final String JDBC_USERNAME = "myspring.datasource.jdbc.username"; 15 | public static final String JDBC_PASSWORD = "myspring.datasource.jdbc.password"; 16 | 17 | //数据库连接池 18 | public static final String POOL_USEPOOL ="myspring.datasource.pool.usePool"; 19 | public static final String POOL_MAXSIZE ="myspring.datasource.pool.maxSize"; 20 | public static final String POOL_WAITTIMEMILL ="myspring.datasource.pool.waitTimeMill"; 21 | //java源码地址 22 | public static final String APP_BASE_PACKAGE = "myspring.app.base_package"; 23 | //jsp页面路径 24 | public static final String APP_JSP_PATH = "myspring.app.jsp_path"; 25 | //静态资源路径 26 | public static final String APP_ASSET_PATH = "myspring.app.asset_path"; 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/constants/IsolationLevelConstant.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.constants; 2 | 3 | public class IsolationLevelConstant { 4 | 5 | public static final int TRANSACTION_NONE = 0; 6 | 7 | public static final int TRANSACTION_READ_UNCOMMITTED = 1; 8 | 9 | public static final int TRANSACTION_READ_COMMITTED = 2; 10 | 11 | public static final int TRANSACTION_REPEATABLE_READ = 4; 12 | 13 | public static final int TRANSACTION_SERIALIZABLE = 8; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/constants/PropagationLevelConstant.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.constants; 2 | 3 | public class PropagationLevelConstant { 4 | 5 | public static final int PROPAGATION_REQUIRED = 0; 6 | 7 | public static final int PROPAGATION_SUPPORTS = 1; 8 | 9 | public static final int PROPAGATION_MANDATORY = 2; 10 | 11 | public static final int PROPAGATION_REQUIRES_NEW = 3; 12 | 13 | public static final int PROPAGATION_NOT_SUPPORTED = 4; 14 | 15 | public static final int PROPAGATION_NEVER = 5; 16 | 17 | public static final int PROPAGATION_NESTED = 6; 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/constants/RequestMethod.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.constants; 2 | /** 3 | * 请求方法常量 4 | * @author Administrator 5 | * 6 | */ 7 | public enum RequestMethod { 8 | GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/ioc/BeanDefinition.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.ioc; 2 | 3 | import com.wang.spring.common.MyProxy; 4 | import com.wang.spring.constants.BeanScope; 5 | /** 6 | * Bean的定义类 7 | * @author Administrator 8 | * 9 | */ 10 | public interface BeanDefinition { 11 | //获得类对象 12 | Class getBeanClass(); 13 | //设置类对象 14 | void setBeanClass(Class cls); 15 | //获得作用域 16 | BeanScope getScope(); 17 | //是否单例 18 | boolean isSingleton(); 19 | //是否原型 20 | boolean isPrototype(); 21 | //是否需要代理 22 | boolean getIsProxy(); 23 | //设置是否需要代理 24 | void setIsProxy(boolean isProxy); 25 | //获得代理类 26 | MyProxy getProxy(); 27 | //设置代理类 28 | void setProxy(MyProxy myProxy); 29 | //获得初始化方法名 30 | String getInitMethodName(); 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/ioc/BeanDefinitionRegistry.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.ioc; 2 | 3 | import java.util.Map; 4 | import java.util.Objects; 5 | import java.util.concurrent.ConcurrentHashMap; 6 | /** 7 | * 将bean的定义信息BeanDefinition注册到BeanDefinition容器中 8 | * @author Administrator 9 | * 10 | */ 11 | public class BeanDefinitionRegistry{ 12 | 13 | //BeanDefinition容器 14 | private static Map beanDefinitionMap = new ConcurrentHashMap<>(); 15 | 16 | /** 17 | * 注册BeanDefinition 18 | */ 19 | public static void registryBeanDefinition(String beanName, BeanDefinition beanDefinition) { 20 | // TODO Auto-generated method stub 21 | Objects.requireNonNull(beanName, "beanName 不能为空"); 22 | Objects.requireNonNull(beanDefinition, "beanDefinition 不能为空"); 23 | beanDefinitionMap.put(beanName, beanDefinition); 24 | } 25 | /** 26 | * 根据类名className获取BeanDefinition 27 | */ 28 | public static BeanDefinition getBeanDefinition(String className) { 29 | // TODO Auto-generated method stub 30 | return beanDefinitionMap.get(className); 31 | } 32 | /** 33 | * BeanDefinition是否存在 34 | */ 35 | public static boolean containsBeanDefinition(String className) { 36 | // TODO Auto-generated method stub 37 | return beanDefinitionMap.containsKey(className); 38 | } 39 | /** 40 | * 获得BeanDefinition容器 41 | * @return 42 | */ 43 | public static Map getBeanDefinitionMap() { 44 | return beanDefinitionMap; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/ioc/BeanFactory.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.ioc; 2 | 3 | import com.wang.spring.constants.BeanScope; 4 | /** 5 | * Bean工厂接口 6 | * @author Administrator 7 | * 8 | */ 9 | public interface BeanFactory { 10 | //根据类名获得bean 11 | Object getBean(String beanName,BeanScope beanScope); 12 | 13 | Object getBean(String name); 14 | //根据类对象获得bean 15 | Object getBean(Class cls,BeanScope beanScope); 16 | 17 | Object getBean(Class cls); 18 | //设置bean 19 | void setBean(String name, Object obj); 20 | 21 | void setBean(Class cls, Object obj); 22 | //刷新Bean工厂 23 | void refresh()throws Exception; 24 | //Bean工厂是否为空 25 | boolean isEmpty(); 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/ioc/ClassSetHelper.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.ioc; 2 | 3 | import java.lang.annotation.Annotation; 4 | import java.lang.annotation.Documented; 5 | import java.lang.annotation.Inherited; 6 | import java.lang.annotation.Retention; 7 | import java.lang.annotation.Target; 8 | import java.util.HashSet; 9 | import java.util.Properties; 10 | import java.util.Set; 11 | 12 | import javax.annotation.Generated; 13 | import javax.annotation.PostConstruct; 14 | import javax.annotation.PreDestroy; 15 | import javax.annotation.Resource; 16 | import javax.annotation.Resources; 17 | 18 | import com.wang.spring.annotation.ioc.Component; 19 | import com.wang.spring.annotation.ioc.Service; 20 | import com.wang.spring.annotation.mvc.Controller; 21 | import com.wang.spring.constants.ConfigConstant; 22 | import com.wang.spring.utils.ClassUtil; 23 | import com.wang.spring.utils.PropsUtil; 24 | /** 25 | * 类集合助手,可扫描配置文件中的包路径,获得指定类型或被指定注解的类对象集合 26 | * @author Administrator 27 | * 28 | */ 29 | public class ClassSetHelper { 30 | private static Set> CLASS_SET; 31 | static { 32 | Properties props = PropsUtil.loadProps("application.properties"); 33 | String basePackName = PropsUtil.getString(props, ConfigConstant.APP_BASE_PACKAGE); 34 | CLASS_SET = ClassUtil.getClassSet(basePackName); 35 | } 36 | /** 37 | * 获得所有类对象集合 38 | * @return 39 | */ 40 | public static Set> getClassSet() { 41 | return CLASS_SET; 42 | } 43 | /** 44 | * 获得被Component注解的类对象集合 45 | * @return 46 | */ 47 | public static Set> getComponentClassSet(){ 48 | Set> classSet = new HashSet>(); 49 | for (Class clz : CLASS_SET) { 50 | if (clz.isAnnotationPresent(Component.class)){ 51 | classSet.add(clz); 52 | } 53 | } 54 | return classSet; 55 | } 56 | /** 57 | * 获得被Service注解的类对象集合 58 | * @return 59 | */ 60 | public static Set> getServiceClassSet(){ 61 | Set> classSet = new HashSet>(); 62 | for (Class clz : CLASS_SET) { 63 | if (clz.isAnnotationPresent(Service.class)){ 64 | classSet.add(clz); 65 | } 66 | } 67 | return classSet; 68 | } 69 | /** 70 | * 获得被Controller注解的类对象集合 71 | * @return 72 | */ 73 | public static Set> getControllerClassSet(){ 74 | Set> classSet = new HashSet>(); 75 | for (Class cls : CLASS_SET) { 76 | if (cls.isAnnotationPresent(Controller.class)) { 77 | classSet.add(cls); 78 | } 79 | } 80 | return classSet; 81 | } 82 | /** 83 | * 获得被Component,Service,Controller注解的类对象集合 84 | * @return 85 | */ 86 | public static Set> getBeanClassSet() { 87 | Set> beanClassSet = new HashSet>(); 88 | beanClassSet.addAll(getServiceClassSet()); 89 | beanClassSet.addAll(getControllerClassSet()); 90 | beanClassSet.addAll(getComponentClassSet()); 91 | return beanClassSet; 92 | } 93 | 94 | public static Set> getInheritedComponentClassSet() { 95 | return getClassSetByInheritedAnnotation(Component.class); 96 | } 97 | 98 | /** 99 | * 通过超类获取实现类的集合 100 | */ 101 | public static Set> getClassSetBySuper(Class superClass) { 102 | Set> classSet = new HashSet>(); 103 | for (Class cls : CLASS_SET) { 104 | //isAssignableFrom() 表示superClass是cls的超类 105 | if (superClass.isAssignableFrom(cls) && !superClass.equals(cls)) { 106 | classSet.add(cls); 107 | } 108 | } 109 | return classSet; 110 | } 111 | 112 | /** 113 | * 获取基础包名下直接带有某注解的所有类 114 | */ 115 | public static Set> getClassSetByAnnotation(Class present){ 116 | Set> classSet = new HashSet>(); 117 | for (Class cls : CLASS_SET) { 118 | if(cls.isAnnotationPresent(present)){ 119 | classSet.add(cls); 120 | } 121 | } 122 | return classSet; 123 | } 124 | 125 | /** 126 | * 获取基础包名下直接或间接带有某注解的所有类 127 | */ 128 | public static Set> getClassSetByInheritedAnnotation(Class present){ 129 | Set> classSet = new HashSet>(); 130 | for (Class cls : CLASS_SET) { 131 | if(isAnnoPresent(cls,present)){ 132 | classSet.add(cls); 133 | } 134 | } 135 | return classSet; 136 | } 137 | 138 | /** 139 | * 判断classz上是否有注解类annoClass,包括直接的和间接的注解 140 | * @param classz 141 | * @param annoClass 142 | */ 143 | private static boolean isAnnoPresent(Class classz,Class annoClass) { 144 | Annotation[] annotations = (Annotation[]) classz.getAnnotations(); 145 | for (Annotation annotation : annotations) { 146 | if ( annotation.annotationType() != Deprecated.class && 147 | annotation.annotationType() != SuppressWarnings.class && 148 | annotation.annotationType() != Override.class && 149 | annotation.annotationType() != PostConstruct.class && 150 | annotation.annotationType() != PreDestroy.class && 151 | annotation.annotationType()!= Resource.class && 152 | annotation.annotationType() != Resources.class && 153 | annotation.annotationType() != Generated.class && 154 | annotation.annotationType() != Target.class && 155 | annotation.annotationType() != Retention.class && 156 | annotation.annotationType() != Documented.class && 157 | annotation.annotationType() != Inherited.class) { 158 | if (annotation.annotationType() ==annoClass){ 159 | return true; 160 | }else{ 161 | return isAnnoPresent(annotation.annotationType(),annoClass); 162 | } 163 | } 164 | } 165 | return false; 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/ioc/DefaultBeanFactory.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.ioc; 2 | import java.lang.reflect.Field; 3 | import java.lang.reflect.Method; 4 | import java.util.HashSet; 5 | import java.util.Map; 6 | import java.util.Objects; 7 | import java.util.Set; 8 | import java.util.concurrent.ConcurrentHashMap; 9 | import javax.annotation.Resource; 10 | import com.wang.spring.annotation.ioc.Autowired; 11 | import com.wang.spring.annotation.ioc.Bean; 12 | import com.wang.spring.annotation.ioc.Component; 13 | import com.wang.spring.annotation.ioc.Configuration; 14 | import com.wang.spring.annotation.ioc.Qualifier; 15 | import com.wang.spring.annotation.ioc.Service; 16 | import com.wang.spring.annotation.ioc.Value; 17 | import com.wang.spring.annotation.mvc.Controller; 18 | import com.wang.spring.common.MyProxy; 19 | import com.wang.spring.constants.BeanScope; 20 | import com.wang.spring.utils.ConfigUtil; 21 | 22 | public class DefaultBeanFactory implements BeanFactory{ 23 | //bean工厂单例 24 | private static volatile DefaultBeanFactory instance = null; 25 | //一级缓存Bean容器,IOC容器,直接从此处获取Bean 26 | private static Map singletonObjects = new ConcurrentHashMap<>(); 27 | //二级缓存,为了将完全地Bean和半成品的Bean分离,避免读取到不完整的Bean 28 | private static Map earlySingletonObjects=new ConcurrentHashMap<>(); 29 | //三级缓存,值为一个对象工厂,可以返回实例对象 30 | private static Map singletonFactories=new ConcurrentHashMap<>(); 31 | //是否在创建中 32 | private static Set singletonsCurrennlyInCreation=new HashSet<>(); 33 | //Bean的注册信息BeanDefinition容器 34 | private static Map beanDefinitionMap = BeanDefinitionRegistry.getBeanDefinitionMap(); 35 | /** 36 | * 初始化Bean 37 | */ 38 | static { 39 | Set> beanClassSet = ClassSetHelper.getBeanClassSet();//ClassSetHelper.getInheritedComponentClassSet(); // 40 | if(beanClassSet!=null && !beanClassSet.isEmpty()) { 41 | try { 42 | for(Class beanClass : beanClassSet) { 43 | GenericBeanDefinition genericBeanDefinition = new GenericBeanDefinition(); 44 | genericBeanDefinition.setBeanClass(beanClass); 45 | BeanDefinitionRegistry.registryBeanDefinition(beanClass.getName(), genericBeanDefinition); 46 | } 47 | //注册配置的bean 48 | getInstance().initConfigBean(); 49 | //注册其他所有的bean 50 | } catch (Exception e) { 51 | e.printStackTrace(); 52 | } 53 | } 54 | } 55 | 56 | private DefaultBeanFactory() { 57 | // TODO Auto-generated constructor stub 58 | } 59 | /** 60 | * 获取单例Bean工厂 61 | * @return 62 | */ 63 | public static DefaultBeanFactory getInstance() { 64 | if(null==instance) { 65 | synchronized (DefaultBeanFactory.class){ 66 | if(null==instance) { 67 | instance=new DefaultBeanFactory(); 68 | return instance; 69 | } 70 | } 71 | } 72 | return instance; 73 | } 74 | public static Map getBeanMap() { 75 | return singletonObjects; 76 | } 77 | 78 | /** 79 | * 根据类的全限定名获取bean 80 | */ 81 | @Override 82 | public Object getBean(String beanName) { 83 | // TODO Auto-generated method stub 84 | Object bean = null; 85 | try { 86 | bean=doGetBean(beanName,BeanScope.SINGLETON); 87 | } catch (Exception e) { 88 | // TODO: handle exception 89 | e.printStackTrace(); 90 | } 91 | return bean; 92 | } 93 | @Override 94 | public Object getBean(String beanName,BeanScope beanScope) { 95 | // TODO Auto-generated method stub 96 | Object bean = null; 97 | try { 98 | bean=doGetBean(beanName,beanScope); 99 | } catch (Exception e) { 100 | // TODO: handle exception 101 | e.printStackTrace(); 102 | } 103 | return bean; 104 | } 105 | /** 106 | * 根据类的class对象获取bean 107 | */ 108 | @Override 109 | public Object getBean(Class cls) { 110 | // TODO Auto-generated method stub 111 | Object bean = null; 112 | try { 113 | bean=doGetBean(cls.getName(),BeanScope.SINGLETON); 114 | } catch (Exception e) { 115 | // TODO: handle exception 116 | e.printStackTrace(); 117 | } 118 | return bean; 119 | } 120 | @Override 121 | public Object getBean(Class cls,BeanScope beanScope) { 122 | // TODO Auto-generated method stub 123 | Object bean = null; 124 | try { 125 | bean=doGetBean(cls.getName(),beanScope); 126 | } catch (Exception e) { 127 | // TODO: handle exception 128 | e.printStackTrace(); 129 | } 130 | return bean; 131 | } 132 | 133 | /** 134 | * 设置bean 135 | */ 136 | @Override 137 | public void setBean(String beanName, Object obj) { 138 | // TODO Auto-generated method stub 139 | try { 140 | Objects.requireNonNull(beanName, "beanName 不能为空"); 141 | singletonObjects.put(beanName, obj); 142 | } catch (Exception e) { 143 | // TODO: handle exception 144 | e.printStackTrace(); 145 | } 146 | } 147 | /** 148 | * 设置bean 149 | */ 150 | @Override 151 | public void setBean(Class cls, Object obj) { 152 | // TODO Auto-generated method stub 153 | this.setBean(cls.getName(), obj); 154 | } 155 | /** 156 | * 刷新,重新注入所有的bean 157 | */ 158 | @Override 159 | public void refresh() throws Exception { 160 | // TODO Auto-generated method stub 161 | for(Map.Entry entry: beanDefinitionMap.entrySet()) { 162 | getBean(entry.getKey()); 163 | } 164 | } 165 | /** 166 | * 注入@Configuration中配置bean 167 | * @throws Exception 168 | */ 169 | private void initConfigBean() throws Exception { 170 | Set> configClassSet = ClassSetHelper.getClassSetByAnnotation(Configuration.class); 171 | if(configClassSet==null || configClassSet.isEmpty()) { 172 | return; 173 | } 174 | for(Class configClass : configClassSet) { 175 | //注册Configuration 176 | GenericBeanDefinition genericBeanDefinition = new GenericBeanDefinition(); 177 | genericBeanDefinition.setBeanClass(configClass); 178 | BeanDefinitionRegistry.registryBeanDefinition(configClass.getName(), genericBeanDefinition); 179 | Object configBean = getBean(configClass); 180 | Method[] methods = configClass.getDeclaredMethods(); 181 | for(Method method:methods) { 182 | if(method.isAnnotationPresent(Bean.class)) { 183 | Class returnClass = method.getReturnType(); 184 | Object bean = method.invoke(configBean); 185 | String keyName = returnClass.getName(); 186 | singletonObjects.put(keyName, bean); 187 | System.out.println("成功注入"+configClass.getName()+" 中的 "+returnClass.getName()); 188 | } 189 | 190 | } 191 | singletonObjects.remove(configClass.getName()); 192 | } 193 | } 194 | 195 | /** 196 | * 从beanMap获取bean,如果不存在则实例化一个bean 197 | * @param beanName 198 | * @return 199 | * @throws Exception 200 | */ 201 | private Object doGetBean(String beanName,BeanScope beanScope) throws Exception{ 202 | Objects.requireNonNull(beanName, "beanName 不能为空"); 203 | //获取单例 204 | Object bean = getSingleton(beanName); 205 | if(bean != null) { 206 | return bean; 207 | } 208 | //如果未获取到bean,且bean不在创建中,则置bean的状态为在创建中 209 | if(!singletonsCurrennlyInCreation.contains(beanName)) { 210 | singletonsCurrennlyInCreation.add(beanName); 211 | } 212 | BeanDefinition beanDefinition = beanDefinitionMap.get(beanName); 213 | if(beanDefinition==null) { 214 | throw new Exception("不存在 "+beanName+" 的定义"); 215 | } 216 | Class beanClass = beanDefinition.getBeanClass(); 217 | //找到实现类 218 | beanClass = findImplementClass(beanClass,null); 219 | //判断是否需要代理,若需要则生成代理类 220 | if(beanDefinition.getIsProxy() && beanDefinition.getProxy()!=null) { 221 | MyProxy myProxy = beanDefinition.getProxy(); 222 | bean=myProxy.getProxy(beanClass); 223 | } 224 | else { 225 | bean = beanClass.getDeclaredConstructor().newInstance(); 226 | } 227 | //将实例化后,但未注入属性的bean,放入三级缓存中 228 | final Object temp = bean; 229 | singletonFactories.put(beanName, new ObjectFactory() { 230 | @Override 231 | public Object getObject() { 232 | // TODO Auto-generated method stub 233 | return temp; 234 | } 235 | }); 236 | //反射调用init方法 237 | String initMethodName = beanDefinition.getInitMethodName(); 238 | if(initMethodName!=null) { 239 | Method method = beanClass.getMethod(initMethodName, null); 240 | method.invoke(bean, null); 241 | } 242 | 243 | //注入bean的属性 244 | fieldInject(beanClass, bean, false); 245 | //如果三级缓存存在bean,则拿出放入二级缓存中 246 | if(singletonFactories.containsKey(beanName)) { 247 | ObjectFactory factory = singletonFactories.get(beanName); 248 | earlySingletonObjects.put(beanName, factory.getObject()); 249 | singletonFactories.remove(beanName); 250 | } 251 | //如果二级缓存存在bean,则拿出放入一级缓存中 252 | if(earlySingletonObjects.containsKey(beanName)) { 253 | bean = earlySingletonObjects.get(beanName); 254 | singletonObjects.put(beanName, bean); 255 | earlySingletonObjects.remove(beanName); 256 | } 257 | return bean; 258 | } 259 | /** 260 | * 从缓存中获取单例bean 261 | * @param beanName 262 | * @return 263 | */ 264 | private Object getSingleton(String beanName) { 265 | //如果一级存在bean,则直接返回 266 | Object bean = singletonObjects.get(beanName); 267 | if(bean!=null) { 268 | return bean; 269 | } 270 | //如果一级缓存不存在bean,且bean在创建中,则从二级缓存中拿出半成品bean返回,否则从三级缓存拿出放入二级缓存中 271 | if(singletonsCurrennlyInCreation.contains(beanName)) { 272 | bean = earlySingletonObjects.get(beanName); 273 | if(bean == null) { 274 | ObjectFactory factory = singletonFactories.get(beanName); 275 | if(factory != null) { 276 | bean = factory.getObject(); 277 | earlySingletonObjects.put(beanName, bean); 278 | singletonFactories.remove(beanName); 279 | } 280 | } 281 | } 282 | return bean; 283 | } 284 | /** 285 | * 依赖注入 286 | * @param beanClass 287 | * @param instance 288 | * @param isProxyed 289 | * @throws Exception 290 | */ 291 | private void fieldInject(Class beanClass, Object bean, boolean isProxyed) throws Exception{ 292 | Field[] beanFields = beanClass.getDeclaredFields(); 293 | if (beanFields != null && beanFields.length > 0) { 294 | for (Field beanField : beanFields) { 295 | if(beanField.isAnnotationPresent(Value.class)) { 296 | //注入value值 297 | String key = beanField.getAnnotation(Value.class).value(); 298 | Class type = beanField.getType(); 299 | if(!"".equals(key)) { 300 | Object value=null; 301 | if(type.equals(String.class)) { 302 | value = ConfigUtil.getString(key); 303 | } 304 | else if (type.equals(Integer.class)) { 305 | value = ConfigUtil.getInt(key); 306 | } 307 | else if (type.equals(Float.class)) { 308 | value = ConfigUtil.getFloat(key); 309 | } 310 | else if (type.equals(Boolean.class)) { 311 | value = ConfigUtil.getBoolean(key); 312 | } 313 | else if (type.equals(Long.class)) { 314 | value = ConfigUtil.getLong(key); 315 | } 316 | else if (type.equals(Double.class)) { 317 | value = ConfigUtil.getDouble(key); 318 | } 319 | else { 320 | throw new RuntimeException("不允许的类型"); 321 | } 322 | beanField.setAccessible(true); 323 | beanField.set(bean, value); 324 | } 325 | } 326 | //找Autowired/Resource注解属性 327 | else if (beanField.isAnnotationPresent(Autowired.class) || beanField.isAnnotationPresent(Resource.class)) { 328 | Class beanFieldClass = beanField.getType(); 329 | String qualifier = null; 330 | if(beanField.isAnnotationPresent(Autowired.class)) { 331 | if(beanField.isAnnotationPresent(Qualifier.class)) { 332 | qualifier=beanField.getAnnotation(Qualifier.class).value(); 333 | } 334 | //Service找实现 335 | beanFieldClass = findImplementClass(beanFieldClass,qualifier); 336 | } 337 | else if(beanField.isAnnotationPresent(Resource.class)){ 338 | qualifier = beanField.getAnnotation(Resource.class).name(); 339 | if(qualifier==null || qualifier.equals("")) { 340 | qualifier = beanFieldClass.getSimpleName(); 341 | } 342 | Class tmpClass= findImplementClass(null,qualifier); 343 | if(tmpClass==null || tmpClass.isInterface()) { 344 | Class beanAnnotationType = beanField.getAnnotation(Resource.class).type(); 345 | if(beanAnnotationType!=java.lang.Object.class) { 346 | beanFieldClass = findImplementClass(beanAnnotationType, null); 347 | } 348 | else { 349 | beanFieldClass = findImplementClass(beanFieldClass, null); 350 | } 351 | } 352 | else { 353 | beanFieldClass = tmpClass; 354 | } 355 | } 356 | //根据beanName去找实例(这时是实现类的beanNamCe) 357 | beanField.setAccessible(true); 358 | try { 359 | //反射注入属性实例。 360 | beanField.set(bean,getBean(beanFieldClass.getName()) //第一遍缓存没有b,再getBean。 361 | ); 362 | } catch (IllegalAccessException e) { 363 | e.printStackTrace(); 364 | } 365 | } 366 | } 367 | } 368 | 369 | } 370 | 371 | /** 372 | * 找到实现类 373 | * @param interfaceClass 374 | * @return 375 | */ 376 | private static Class findImplementClass(Class interfaceClass,String name){ 377 | Class implementClass = interfaceClass; 378 | Set> classSet = new HashSet<>(); 379 | for(Class cls : ClassSetHelper.getClassSet()) { 380 | if(interfaceClass!=null && interfaceClass.isAssignableFrom(cls) && !interfaceClass.equals(cls)) { 381 | if(name!=null && !name.equals("")) { 382 | if(isClassAnnotationedName(cls, name)) { 383 | return cls; 384 | } 385 | } 386 | classSet.add(cls); 387 | } 388 | else if(interfaceClass==null) { 389 | if(name!=null && !name.equals("")) { 390 | if(isClassAnnotationedName(cls, name) || (cls.getSimpleName().equals(name) && !cls.isInterface())) { 391 | return cls; 392 | } 393 | } 394 | } 395 | if(classSet!=null && !classSet.isEmpty()) { 396 | implementClass = classSet.iterator().next(); 397 | } 398 | } 399 | return implementClass; 400 | } 401 | private static boolean isClassAnnotationedName(Class cls,String name) { 402 | return (cls.isAnnotationPresent(Component.class) && cls.getAnnotation(Component.class).value().equals(name)) || 403 | (cls.isAnnotationPresent(Service.class) && cls.getAnnotation(Service.class).value().equals(name)) || 404 | (cls.isAnnotationPresent(Controller.class) && cls.getAnnotation(Controller.class).value().equals(name)); 405 | } 406 | /** 407 | * beanMap是否为空 408 | */ 409 | @Override 410 | public boolean isEmpty() { 411 | // TODO Auto-generated method stub 412 | return singletonObjects==null || singletonObjects.isEmpty(); 413 | } 414 | } 415 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/ioc/GenericBeanDefinition.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.ioc; 2 | import java.util.Objects; 3 | 4 | import com.wang.spring.common.MyProxy; 5 | import com.wang.spring.constants.BeanScope; 6 | 7 | public class GenericBeanDefinition implements BeanDefinition{ 8 | 9 | private Class beanClass; 10 | 11 | private BeanScope scope =BeanScope.SINGLETON; 12 | 13 | private String initMethodName; 14 | 15 | private boolean isProxy = false; 16 | 17 | private MyProxy myProxy = null; 18 | 19 | public void setBeanClass(Class beanClass){ 20 | this.beanClass = beanClass; 21 | } 22 | 23 | public void setScope(BeanScope scope) { 24 | this.scope = scope; 25 | } 26 | 27 | public void setInitMethodName(String initMethodName) { 28 | this.initMethodName = initMethodName; 29 | } 30 | 31 | @Override 32 | public Class getBeanClass() { 33 | return beanClass; 34 | } 35 | 36 | @Override 37 | public BeanScope getScope() { 38 | return scope; 39 | } 40 | 41 | @Override 42 | public boolean isSingleton() { 43 | return Objects.equals(scope,BeanScope.SINGLETON); 44 | } 45 | 46 | @Override 47 | public boolean isPrototype() { 48 | return Objects.equals(scope, BeanScope.PROTOTYPE); 49 | } 50 | 51 | @Override 52 | public String getInitMethodName() { 53 | return initMethodName; 54 | } 55 | 56 | @Override 57 | public MyProxy getProxy() { 58 | // TODO Auto-generated method stub 59 | return myProxy; 60 | } 61 | 62 | @Override 63 | public void setProxy(MyProxy myProxy) { 64 | // TODO Auto-generated method stub 65 | this.myProxy = myProxy; 66 | } 67 | 68 | @Override 69 | public boolean getIsProxy() { 70 | // TODO Auto-generated method stub 71 | return isProxy; 72 | } 73 | 74 | @Override 75 | public void setIsProxy(boolean isProxy) { 76 | // TODO Auto-generated method stub 77 | this.isProxy=isProxy; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/ioc/ObjectFactory.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.ioc; 2 | 3 | public interface ObjectFactory { 4 | public Object getObject(); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/mvc/DispatcherServlet.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.mvc; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.lang.annotation.Annotation; 6 | import java.lang.reflect.Method; 7 | import java.util.Arrays; 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | import java.util.Set; 11 | import javax.servlet.ServletConfig; 12 | import javax.servlet.ServletContext; 13 | import javax.servlet.ServletException; 14 | import javax.servlet.ServletRegistration; 15 | import javax.servlet.http.HttpServlet; 16 | import javax.servlet.http.HttpServletRequest; 17 | import javax.servlet.http.HttpServletResponse; 18 | import com.wang.mybatis.core.MapperHelper; 19 | import com.wang.spring.annotation.mvc.PathVariable; 20 | import com.wang.spring.annotation.mvc.RequestMapping; 21 | import com.wang.spring.annotation.mvc.RequestParam; 22 | import com.wang.spring.annotation.mvc.ResponseBody; 23 | import com.wang.spring.aop.AOPHelper; 24 | import com.wang.spring.constants.RequestMethod; 25 | import com.wang.spring.ioc.ClassSetHelper; 26 | import com.wang.spring.ioc.DefaultBeanFactory; 27 | import com.wang.spring.utils.ConfigUtil; 28 | import freemarker.template.Configuration; 29 | import freemarker.template.TemplateExceptionHandler; 30 | 31 | public class DispatcherServlet extends HttpServlet { 32 | //bean工厂 33 | private static DefaultBeanFactory beanFactory=DefaultBeanFactory.getInstance(); 34 | //请求到Handler的映射 35 | private Map handlerMapping = new HashMap<>(); 36 | //Handler到Handler的映射 37 | private Map adapaterMapping = new HashMap<>(); 38 | //FreeMarker配置对象 39 | private Configuration cfg = null; 40 | 41 | @Override 42 | public void init(ServletConfig config) throws ServletException{ 43 | try { 44 | Class.forName(AOPHelper.class.getName()); 45 | Class.forName(MapperHelper.class.getName()); 46 | beanFactory.refresh(); 47 | } catch (ClassNotFoundException e1) { 48 | // TODO Auto-generated catch block 49 | e1.printStackTrace(); 50 | } catch (Exception e) { 51 | // TODO Auto-generated catch block 52 | e.printStackTrace(); 53 | } 54 | //请求解析 55 | initMultipartResolver(); 56 | //多语言、国际化 57 | initLocaleResolver(); 58 | //主题View层的 59 | initThemeResolver(); 60 | //=========== 重要 ========= 61 | try { 62 | //解析url和Method的关联关系 63 | initHandlerMappings(); 64 | System.out.println("initHandlerMappings..."); 65 | //适配器(匹配的过程) 66 | initHandlerAdapters(); 67 | System.out.println("initHandlerAdapters..."); 68 | InitFreemarkerResolver(); 69 | System.out.println("InitFreemarkerResolver..."); 70 | } catch (Exception e) { 71 | // TODO Auto-generated catch block 72 | e.printStackTrace(); 73 | } 74 | } 75 | /** 76 | * Freemarker的初始化配置 77 | * @throws Exception 78 | */ 79 | private void InitFreemarkerResolver() throws Exception { 80 | cfg = new Configuration(Configuration.VERSION_2_3_22); 81 | cfg.setDirectoryForTemplateLoading(new File(this.getClass().getResource("/").getPath()+ConfigUtil.getAppJspPath())); 82 | cfg.setDefaultEncoding("UTF-8"); 83 | cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); 84 | } 85 | /** 86 | * 动态注册处理静态资源的默认Servlet 87 | * @param servletContext 88 | */ 89 | private void registerServlet(ServletContext servletContext) { 90 | ServletRegistration defaultServlet = servletContext.getServletRegistration("default"); 91 | if(defaultServlet==null) { 92 | throw new RuntimeException("无法动态注册处理静态资源的默认Servlet"); 93 | } 94 | defaultServlet.addMapping(this.getClass().getResource("/").getPath()+ConfigUtil.getAppAssetPath() + "*"); 95 | } 96 | 97 | /** 98 | * 解析url和Method的关联关系 99 | * @param context 100 | */ 101 | private void initHandlerMappings() throws Exception{ 102 | if(beanFactory.isEmpty()) { 103 | throw new Exception("ioc容器未初始化"); 104 | } 105 | Set> classSet = ClassSetHelper.getControllerClassSet(); 106 | for(Class clazz:classSet) { 107 | String url = ""; 108 | RequestMethod requestMethod = RequestMethod.GET; 109 | if(clazz.isAnnotationPresent(RequestMapping.class)) { 110 | RequestMapping requestMapping = clazz.getAnnotation(RequestMapping.class); 111 | url = requestMapping.value(); 112 | requestMethod = requestMapping.method(); 113 | } 114 | //扫描Controller下面的所有方法 115 | Method[] methods = clazz.getMethods(); 116 | for (Method method : methods) { 117 | if (!method.isAnnotationPresent(RequestMapping.class)) { 118 | continue; 119 | } 120 | RequestMapping requestMapping = method.getAnnotation(RequestMapping.class); 121 | String url2 = (url + requestMapping.value()).replaceAll("/+", "/"); 122 | requestMethod = requestMapping.method(); 123 | Request req = new Request(requestMethod, url2); 124 | Handler handler = new Handler(beanFactory.getBean(clazz), method); 125 | handlerMapping.put(req, handler); 126 | System.out.println("Mapping: " + url2 + " to :" + method.toString()); 127 | } 128 | } 129 | } 130 | /** 131 | * 适配器(匹配的过程),主要是用来动态匹配我们参数的 132 | * @param context 133 | */ 134 | private void initHandlerAdapters() throws Exception{ 135 | if (handlerMapping.isEmpty()) { 136 | throw new Exception("handlerMapping 未初始化"); 137 | } 138 | //参数类型作为key,参数的索引号作为值 139 | Map paramMapping = null; 140 | for (Map.Entry entry : handlerMapping.entrySet()) { 141 | paramMapping = new HashMap(); 142 | //把这个方法上面所有的参数全部获取到 143 | Request req = entry.getKey(); 144 | Handler handler =entry.getValue(); 145 | Class[] parameterTypes = handler.method.getParameterTypes(); 146 | //有顺序,但是通过反射,没法拿到我们参数名字 147 | //因为每个参数上面是可以加多个数组的,所以是二维数组,第一位表示参数位置,第二位表示注解个数 148 | Annotation[][] pa = handler.method.getParameterAnnotations(); 149 | //匹配自定参数列表 150 | for (int i = 0; i < pa.length; i++) { 151 | Class type = parameterTypes[i]; 152 | if (type == HttpServletRequest.class || type == HttpServletResponse.class) { 153 | paramMapping.put(type.getName(), i); 154 | continue; 155 | } 156 | for (Annotation annotation : pa[i]) { 157 | String paramName; 158 | if (annotation instanceof RequestParam) { 159 | paramName = ((RequestParam) annotation).value(); 160 | if (!"".equals(paramName.trim())) { 161 | paramMapping.put(paramName, i); 162 | } 163 | } 164 | else if (annotation instanceof PathVariable) { 165 | paramName = ((PathVariable) annotation).value(); 166 | if (!"".equals(paramName.trim())) { 167 | paramMapping.put(paramName, i); 168 | } 169 | } 170 | else if(annotation instanceof ResponseBody) { 171 | paramMapping.put("ResponseBody", i); 172 | } 173 | } 174 | } 175 | adapaterMapping.put(handler, new HandlerAdapter(paramMapping)); 176 | } 177 | } 178 | /** 179 | * 处理GET请求 180 | */ 181 | @Override 182 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 183 | this.doPost(req, resp); 184 | } 185 | /** 186 | * 处理POST请求,在这里调用自己写的Controller的方法 187 | */ 188 | @Override 189 | protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 190 | System.out.println("request method is "+req.getMethod()+" url is "+req.getRequestURI()); 191 | try { 192 | doDispatch(req, resp); 193 | } catch (Exception e) { 194 | resp.getWriter().write("500 Exception, Msg :" + Arrays.toString(e.getStackTrace())); 195 | } 196 | } 197 | 198 | private Request createRequest(HttpServletRequest request) { 199 | String url = request.getRequestURI(); 200 | String contextPath = request.getContextPath(); 201 | url = url.replace(contextPath, "").replaceAll("/+", "/"); 202 | Request req = new Request(Enum.valueOf(RequestMethod.class, request.getMethod().toUpperCase()), url); 203 | return req; 204 | } 205 | /** 206 | * 根据请求找到对应的Handler 207 | * @param request 208 | * @return 209 | */ 210 | private Handler getHandler(HttpServletRequest request) { 211 | if (handlerMapping.isEmpty()) { 212 | System.out.println("handlerMapping is empty" ); 213 | return null; 214 | } 215 | Request req = createRequest(request); 216 | System.out.println("getHander,url is "+req.requestPath); 217 | for(Request request2:handlerMapping.keySet()) { 218 | if(request2.equals(req)) { 219 | return handlerMapping.get(request2); 220 | } 221 | } 222 | return null; 223 | } 224 | /** 225 | * 根据Handler找到对应的HandlerAdapter 226 | * @param handler 227 | * @return 228 | */ 229 | private HandlerAdapter getHandlerAdapter(Handler handler) { 230 | if(handler==null || adapaterMapping==null || adapaterMapping.isEmpty()) { 231 | return null; 232 | } 233 | return adapaterMapping.get(handler); 234 | } 235 | 236 | private Map getPathVariableMap(HttpServletRequest request){ 237 | Request req = createRequest(request); 238 | for(Request reqKey:handlerMapping.keySet()) { 239 | if(reqKey.equals(req)) { 240 | return Request.parsePathVariable(reqKey.requestPath, req.requestPath); 241 | } 242 | } 243 | return null; 244 | 245 | } 246 | /** 247 | * 处理请求,执行方法,解析结果 248 | * @param request 249 | * @param response 250 | * @throws Exception 251 | */ 252 | private void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception{ 253 | Handler handler = getHandler(request); 254 | if(handler==null) { 255 | response.getWriter().write("404 Handler Not Found"); 256 | } 257 | HandlerAdapter handlerAdapter = getHandlerAdapter(handler); 258 | //执行HandlerAdapter,解析执行结果 259 | if(null!=handlerAdapter) { 260 | Map pathVariableMap = getPathVariableMap(request); 261 | Object data = handlerAdapter.handle(request, response, handler,pathVariableMap); 262 | if(data instanceof ModelAndView) { 263 | ResultResolverHandler.handlerFreemarkerResult(data,cfg,request,response); 264 | } 265 | else if(isResponseBody(handler)){ 266 | ResultResolverHandler.handleJsonResult(data,response); 267 | } 268 | else { 269 | ResultResolverHandler.handleStringResult(data, response); 270 | } 271 | } 272 | else { 273 | response.getWriter().write("404 HandlerAdapter Not Found"); 274 | } 275 | } 276 | /** 277 | * handler中的方法是否被ResponseBody注解 278 | * @param handler 279 | * @return 280 | */ 281 | private boolean isResponseBody(Handler handler) { 282 | return handler.method.isAnnotationPresent(ResponseBody.class) || handler.controller.getClass().isAnnotationPresent(ResponseBody.class); 283 | } 284 | 285 | /** 286 | * 请求解析 287 | * @param context 288 | */ 289 | private void initMultipartResolver(){} 290 | /** 291 | * 多语言、国际化 292 | * @param context 293 | */ 294 | private void initLocaleResolver(){} 295 | /** 296 | * 主题View层的 297 | * @param context 298 | */ 299 | private void initThemeResolver(){} 300 | } 301 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/mvc/Handler.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.mvc; 2 | 3 | import java.lang.reflect.Method; 4 | import java.util.Objects; 5 | 6 | public class Handler { 7 | protected Object controller; 8 | protected Method method; 9 | 10 | public Handler(Object controller, Method method) { 11 | this.controller = controller; 12 | this.method = method; 13 | } 14 | 15 | @Override 16 | public boolean equals(Object o) { 17 | if (this == o) return true; 18 | if (o == null || getClass() != o.getClass()) return false; 19 | Handler handler = (Handler) o; 20 | return Objects.equals(controller, handler.controller) && 21 | Objects.equals(method, handler.method); 22 | } 23 | 24 | @Override 25 | public int hashCode() { 26 | 27 | return Objects.hash(controller, method); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/mvc/HandlerAdapter.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.mvc; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.lang.reflect.InvocationTargetException; 6 | import java.lang.reflect.Parameter; 7 | import java.util.Arrays; 8 | import java.util.Map; 9 | 10 | import javax.servlet.http.HttpServletRequest; 11 | import javax.servlet.http.HttpServletResponse; 12 | 13 | import com.alibaba.fastjson.JSON; 14 | import com.wang.spring.annotation.mvc.PathVariable; 15 | import com.wang.spring.annotation.mvc.RequestBody; 16 | import com.wang.spring.annotation.mvc.RequestParam; 17 | 18 | 19 | public class HandlerAdapter { 20 | private Map paramMapping; 21 | 22 | public HandlerAdapter(Map paramMapping) { 23 | this.paramMapping = paramMapping; 24 | } 25 | /** 26 | * 主要目的是用反射调用url对应的method 27 | * @param request 28 | * @param response 29 | * @param handler 30 | */ 31 | public Object handle(HttpServletRequest request, HttpServletResponse response, Handler handler,Map pathVariableMap) throws InvocationTargetException, IllegalAccessException { 32 | if(handler.method.getParameterCount()==0) { 33 | return handler.method.invoke(handler.controller); 34 | } 35 | Class[] parameterTypes = handler.method.getParameterTypes(); 36 | Parameter[] parameters = handler.method.getParameters(); 37 | //要想给参数赋值,只能通过索引号来找到具体的某个参数 38 | Object[] paramValues = new Object[parameterTypes.length]; 39 | 40 | String requestName = HttpServletRequest.class.getName(); 41 | if (this.paramMapping.containsKey(requestName)) { 42 | Integer requestIndex = this.paramMapping.get(requestName); 43 | paramValues[requestIndex] = request; 44 | } 45 | String responseName = HttpServletResponse.class.getName(); 46 | if (this.paramMapping.containsKey(responseName)) { 47 | Integer responseIndex = this.paramMapping.get(responseName); 48 | paramValues[responseIndex] = response; 49 | } 50 | //注入消息体的内容 51 | String bodyContent=null; 52 | try { 53 | bodyContent = getBodyContent(request); 54 | } catch (Exception e) { 55 | // TODO Auto-generated catch block 56 | e.printStackTrace(); 57 | } 58 | if(request.getMethod().equals("POST") && bodyContent!=null) { 59 | Integer index=-1; 60 | for(Integer i=0;i=0) { 67 | Object body = JSON.parseObject(bodyContent, parameterTypes[index]); 68 | paramValues[index]=body; 69 | } 70 | } 71 | //解析RequestParam和pathVariable中的参数 72 | Map params = request.getParameterMap(); 73 | for (Map.Entry entry : paramMapping.entrySet()) { 74 | Integer index = entry.getValue(); 75 | if(paramValues[index]!=null) { 76 | continue; 77 | } 78 | if (!params.containsKey(entry.getKey())) { 79 | if(parameters[index].isAnnotationPresent(PathVariable.class)) { 80 | if(pathVariableMap!=null && pathVariableMap.containsKey(entry.getKey())) { 81 | paramValues[index] = caseStringValue(pathVariableMap.get(entry.getKey()), parameterTypes[index]); 82 | } 83 | else { 84 | paramValues[index] = caseStringValue(parameters[index].getAnnotation(PathVariable.class).defaultValue(), parameterTypes[index]); 85 | } 86 | } 87 | else { 88 | String value = parameters[index].isAnnotationPresent(RequestParam.class)?parameters[index].getAnnotation(RequestParam.class).defaultValue():""; 89 | paramValues[index] = value; 90 | } 91 | } 92 | else { 93 | String value = Arrays.toString(params.get(entry.getKey())).replaceAll("\\[|\\]", "") 94 | .replaceAll(",\\s", ","); 95 | paramValues[index] = caseStringValue(value, parameterTypes[index]); 96 | } 97 | } 98 | Object r = handler.method.invoke(handler.controller, paramValues); 99 | return r; 100 | } 101 | /** 102 | * 转换参数类型 103 | * @param value 104 | * @param clazz 105 | * @return 106 | */ 107 | private Object caseStringValue(String value, Class clazz) { 108 | if (clazz == String.class) { 109 | return value; 110 | } else if (clazz == Integer.class) { 111 | return Integer.valueOf(value); 112 | } else if (clazz == int.class) { 113 | return Integer.valueOf(value); 114 | } else { 115 | return null; 116 | } 117 | } 118 | /** 119 | * 获取HttpServletRequest的body中的内容,以字符串的形式返回 120 | * @param request 121 | * @return 122 | * @throws Exception 123 | */ 124 | private String getBodyContent(HttpServletRequest request) throws Exception { 125 | if ( request.getMethod().equals("POST") ) 126 | { 127 | StringBuffer sb = new StringBuffer(); 128 | BufferedReader bufferedReader = null; 129 | String content = ""; 130 | try { 131 | bufferedReader = request.getReader() ; 132 | char[] charBuffer = new char[128]; 133 | int bytesRead; 134 | while ( (bytesRead = bufferedReader.read(charBuffer)) != -1 ) { 135 | sb.append(charBuffer, 0, bytesRead); 136 | } 137 | } catch (IOException ex) { 138 | throw ex; 139 | } finally { 140 | if (bufferedReader != null) { 141 | try { 142 | bufferedReader.close(); 143 | } catch (IOException ex) { 144 | throw ex; 145 | } 146 | } 147 | } 148 | return sb.toString(); 149 | } 150 | return null; 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/mvc/ModelAndView.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.mvc; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | /** 6 | * 视图-模型对象 7 | * @author Administrator 8 | * 9 | */ 10 | public class ModelAndView { 11 | private String view; 12 | 13 | private Map model; 14 | 15 | public ModelAndView(String path) { 16 | this.view = path; 17 | model = new HashMap(); 18 | } 19 | 20 | public ModelAndView(String path,Map model) { 21 | this.view = path; 22 | this.model = model; 23 | } 24 | 25 | public ModelAndView addModel(String key, Object value) { 26 | model.put(key, value); 27 | return this; 28 | } 29 | 30 | public ModelAndView addModel(Map model) { 31 | this.model.putAll(model);; 32 | return this; 33 | } 34 | 35 | public String getPath() { 36 | return view; 37 | } 38 | 39 | public Map getModel() { 40 | return model; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/mvc/Request.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.mvc; 2 | import java.util.Map; 3 | import java.util.Objects; 4 | 5 | import org.apache.commons.collections4.map.HashedMap; 6 | 7 | import com.wang.spring.constants.RequestMethod; 8 | 9 | public class Request { 10 | //请求方法 11 | protected RequestMethod requestMethod; 12 | //请求路径 13 | protected String requestPath; 14 | 15 | public Request(RequestMethod requestMethod, String requestPath){ 16 | this.requestMethod = requestMethod; 17 | this.requestPath = requestPath; 18 | } 19 | //方法名和路径都一样就是同一对象 20 | @Override 21 | public boolean equals(Object obj) { 22 | if(this == obj) return true; 23 | if(obj instanceof Request){ 24 | Request e = (Request) obj; 25 | if(e.requestMethod.equals(this.requestMethod) && pathMatch(e.requestPath, this.requestPath)){ 26 | return true; 27 | } 28 | } 29 | return false; 30 | } 31 | @Override 32 | public int hashCode() { 33 | return Objects.hash(requestMethod,requestPath); 34 | } 35 | @Override 36 | public String toString() { 37 | return requestMethod+":"+requestPath; 38 | } 39 | public static boolean pathMatch(String path1,String path2) { 40 | String[] pathSplit1 = path1.split("/"); 41 | String[] pathSplit2 = path2.split("/"); 42 | if(pathSplit1.length!=pathSplit2.length) { 43 | return false; 44 | } 45 | for(int i=0;i parsePathVariable(String path1,String path2) { 61 | Map pathVariableMap=new HashedMap<>(); 62 | String[] pathSplit1 = path1.split("/"); 63 | String[] pathSplit2 = path2.split("/"); 64 | if(pathSplit1.length!=pathSplit2.length) { 65 | throw new RuntimeException("path1:"+path1+" 与 path2:"+path2+" 长度不匹配"); 66 | } 67 | for(int i=0;i model = view.getModel(); 63 | for (Map.Entry entry : model.entrySet()) { 64 | request.setAttribute(entry.getKey(), entry.getValue()); 65 | } 66 | request.getRequestDispatcher(ConfigUtil.getAppJspPath() + path).forward(request, response); 67 | } 68 | } 69 | } 70 | /** 71 | * 用freemarker解析ModelAndView 72 | * @param data 73 | * @param request 74 | * @param response 75 | * @throws IOException 76 | * @throws ServletException 77 | */ 78 | public static void handlerFreemarkerResult(Object data, Configuration cfg,HttpServletRequest request, HttpServletResponse response) throws Exception, IOException { 79 | if(data==null || !(data instanceof ModelAndView)) { 80 | throw new RuntimeException("无法转换成ModelAndView"); 81 | } 82 | ModelAndView view = (ModelAndView) data; 83 | String path = view.getPath(); 84 | if (StringUtils.isNotEmpty(path)) { 85 | if (path.startsWith("/") || path.endsWith("/")) { //重定向 86 | response.sendRedirect(request.getContextPath() + path); 87 | } else { 88 | Template temp = cfg.getTemplate(path); 89 | response.setContentType("text/html"); 90 | response.setCharacterEncoding("UTF-8"); 91 | PrintWriter writer = response.getWriter(); 92 | temp.process(view.getModel(), writer); 93 | } 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/tomcat/TomcatServer.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.tomcat; 2 | 3 | import org.apache.catalina.Context; 4 | import org.apache.catalina.LifecycleException; 5 | import org.apache.catalina.startup.Tomcat; 6 | import com.wang.spring.ioc.DefaultBeanFactory; 7 | import com.wang.spring.mvc.DispatcherServlet; 8 | 9 | /** 10 | * 内置Tomcat服务器的配置 11 | * @author Administrator 12 | * 13 | */ 14 | public class TomcatServer { 15 | private Tomcat tomcat; 16 | private String[] args; 17 | 18 | public TomcatServer(String[] args) { 19 | this.args = args; 20 | } 21 | 22 | public void startServer() throws LifecycleException{ 23 | 24 | Tomcat tomcat = new Tomcat(); 25 | DefaultBeanFactory beanFactory = DefaultBeanFactory.getInstance(); 26 | if(!beanFactory.isEmpty()) { 27 | System.out.println("beanFactory初始化成功"); 28 | } 29 | //设置绑定的ip及端口号 30 | tomcat.setHostname("localhost"); 31 | tomcat.setPort(8080); 32 | final Context context = tomcat.addContext("/", null); 33 | Tomcat.addServlet(context, "dispatch", new DispatcherServlet()); 34 | context.addServletMapping("/", "dispatch"); 35 | try { 36 | tomcat.init(); 37 | tomcat.start(); 38 | tomcat.getServer().await(); 39 | } catch (LifecycleException e) { 40 | e.printStackTrace(); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/utils/ClassUtil.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.utils; 2 | 3 | import java.io.File; 4 | import java.io.FileFilter; 5 | import java.net.JarURLConnection; 6 | import java.net.URL; 7 | import java.util.Enumeration; 8 | import java.util.HashSet; 9 | import java.util.Set; 10 | import java.util.jar.JarEntry; 11 | import java.util.jar.JarFile; 12 | 13 | public final class ClassUtil { 14 | /** 15 | * 获取类加载器 16 | */ 17 | public static ClassLoader getClassLoader() { 18 | return Thread.currentThread().getContextClassLoader(); 19 | } 20 | 21 | /** 22 | * 加载类 23 | * @param className 类名 24 | * @param isInitialized 是否初始化 25 | * @return 26 | */ 27 | public static Class loadClass(String className, boolean isInitialized) { 28 | Class cls; 29 | try { 30 | cls = Class.forName(className, isInitialized, getClassLoader()); 31 | } catch (ClassNotFoundException e) { 32 | throw new RuntimeException(e); 33 | } 34 | return cls; 35 | } 36 | 37 | /** 38 | * 加载类(默认将初始化类) 39 | */ 40 | public static Class loadClass(String className) { 41 | return loadClass(className, true); 42 | } 43 | 44 | /** 45 | * 获取指定包名下的所有类 46 | */ 47 | public static Set> getClassSet(String packageName) { 48 | Set> classSet = new HashSet>(); 49 | try { 50 | Enumeration urls = getClassLoader().getResources(packageName.replace(".", "/")); 51 | while (urls.hasMoreElements()) { 52 | URL url = urls.nextElement(); 53 | if (url != null) { 54 | String protocol = url.getProtocol(); 55 | if (protocol.equals("file")) { 56 | String packagePath = url.getPath().replaceAll("%20", " "); 57 | addClass(classSet, packagePath, packageName); 58 | } else if (protocol.equals("jar")) { 59 | JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection(); 60 | if (jarURLConnection != null) { 61 | JarFile jarFile = jarURLConnection.getJarFile(); 62 | if (jarFile != null) { 63 | Enumeration jarEntries = jarFile.entries(); 64 | while (jarEntries.hasMoreElements()) { 65 | JarEntry jarEntry = jarEntries.nextElement(); 66 | String jarEntryName = jarEntry.getName(); 67 | if (jarEntryName.endsWith(".class")) { 68 | String className = jarEntryName.substring(0, jarEntryName.lastIndexOf(".")).replaceAll("/", "."); 69 | doAddClass(classSet, className); 70 | } 71 | } 72 | } 73 | } 74 | } 75 | } 76 | } 77 | } catch (Exception e) { 78 | throw new RuntimeException(e); 79 | } 80 | return classSet; 81 | } 82 | /** 83 | * 将指定路径下的类对象添加到集合classSet中 84 | * @param classSet 85 | * @param packagePath 86 | * @param packageName 87 | */ 88 | private static void addClass(Set> classSet, String packagePath, String packageName) { 89 | File[] files = new File(packagePath).listFiles(new FileFilter() { 90 | public boolean accept(File file) { 91 | return (file.isFile() && file.getName().endsWith(".class")) || file.isDirectory(); 92 | } 93 | }); 94 | for (File file : files) { 95 | String fileName = file.getName(); 96 | if (file.isFile()) { 97 | String className = fileName.substring(0, fileName.lastIndexOf(".")); 98 | if (packageName != null && packageName != "") { 99 | className = packageName + "." + className; 100 | } 101 | doAddClass(classSet, className); 102 | } else { 103 | String subPackagePath = fileName; 104 | if (packagePath != null && packagePath != "") { 105 | subPackagePath = packagePath + "/" + subPackagePath; 106 | } 107 | String subPackageName = fileName; 108 | if (packageName != null && packageName != "") { 109 | subPackageName = packageName + "." + subPackageName; 110 | } 111 | addClass(classSet, subPackagePath, subPackageName); 112 | } 113 | } 114 | } 115 | /** 116 | * 加载并添加类对象 117 | * @param classSet 118 | * @param className 119 | */ 120 | private static void doAddClass(Set> classSet, String className) { 121 | Class cls = loadClass(className, false); 122 | classSet.add(cls); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/utils/ConfigUtil.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.utils; 2 | 3 | import java.util.Properties; 4 | 5 | import com.wang.spring.constants.ConfigConstant; 6 | 7 | 8 | public class ConfigUtil { 9 | 10 | /** 11 | * 加载配置文件的属性 12 | */ 13 | private static final Properties CONFIG_PROPS = PropsUtil.loadProps(ConfigConstant.CONFIG_FILE); 14 | 15 | 16 | /** 17 | * 获取 JDBC 驱动 18 | */ 19 | public static String getJdbcDriver() { 20 | return PropsUtil.getString(CONFIG_PROPS, ConfigConstant.JDBC_DRIVER); 21 | } 22 | 23 | /** 24 | * 获取 JDBC URL 25 | */ 26 | public static String getJdbcUrl() { 27 | return PropsUtil.getString(CONFIG_PROPS, ConfigConstant.JDBC_URL); 28 | } 29 | 30 | /** 31 | * 获取 JDBC 用户名 32 | */ 33 | public static String getJdbcUsername() { 34 | return PropsUtil.getString(CONFIG_PROPS, ConfigConstant.JDBC_USERNAME); 35 | } 36 | 37 | /** 38 | * 获取 JDBC 密码 39 | */ 40 | public static String getJdbcPassword() { 41 | return PropsUtil.getString(CONFIG_PROPS, ConfigConstant.JDBC_PASSWORD); 42 | } 43 | 44 | /** 45 | * 是否使用连接池 46 | */ 47 | public static Boolean isDataSourcePool() { 48 | return PropsUtil.getBoolean(CONFIG_PROPS, ConfigConstant.POOL_USEPOOL,false); 49 | } 50 | /** 51 | * 获取连接池最大连接数 52 | */ 53 | public static Integer getDataSourcePoolMaxSize() { 54 | return PropsUtil.getInt(CONFIG_PROPS, ConfigConstant.POOL_MAXSIZE,50); 55 | } 56 | /** 57 | * 获取阻塞等待时间 58 | */ 59 | public static Long getDataSourcePoolWaitTimeMill() { 60 | return PropsUtil.getLong(CONFIG_PROPS, ConfigConstant.POOL_WAITTIMEMILL,10000L); 61 | } 62 | 63 | /** 64 | * 获取应用基础包名 65 | */ 66 | public static String getAppBasePackage() { 67 | return PropsUtil.getString(CONFIG_PROPS, ConfigConstant.APP_BASE_PACKAGE); 68 | } 69 | 70 | /** 71 | * 获取应用 JSP 路径 72 | */ 73 | public static String getAppJspPath() { 74 | return PropsUtil.getString(CONFIG_PROPS, ConfigConstant.APP_JSP_PATH, "/WEB-INF/view/"); 75 | } 76 | 77 | /** 78 | * 获取应用静态资源路径 79 | */ 80 | public static String getAppAssetPath() { 81 | return PropsUtil.getString(CONFIG_PROPS, ConfigConstant.APP_ASSET_PATH, "/asset/"); 82 | } 83 | 84 | /** 85 | * 根据属性名获取 String 类型的属性值 86 | */ 87 | public static String getString(String key) { 88 | return PropsUtil.getString(CONFIG_PROPS, key); 89 | } 90 | 91 | /** 92 | * 根据属性名获取 int 类型的属性值 93 | */ 94 | public static int getInt(String key) { 95 | return PropsUtil.getInt(CONFIG_PROPS, key); 96 | } 97 | 98 | /** 99 | * 根据属性名获取 boolean 类型的属性值 100 | */ 101 | public static boolean getBoolean(String key) { 102 | return PropsUtil.getBoolean(CONFIG_PROPS, key); 103 | } 104 | 105 | /** 106 | * 根据属性名获取 float 类型的属性值 107 | */ 108 | public static Float getFloat(String key) { 109 | return PropsUtil.getFloat(CONFIG_PROPS, key); 110 | } 111 | 112 | /** 113 | * 根据属性名获取 double 类型的属性值 114 | */ 115 | public static Double getDouble(String key) { 116 | return PropsUtil.getDouble(CONFIG_PROPS, key); 117 | } 118 | 119 | /** 120 | * 根据属性名获取 long 类型的属性值 121 | */ 122 | public static Long getLong(String key) { 123 | return PropsUtil.getLong(CONFIG_PROPS, key); 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/utils/PropsUtil.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.utils; 2 | 3 | import java.io.FileNotFoundException; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.util.Properties; 7 | 8 | public final class PropsUtil { 9 | 10 | /** 11 | * 加载属性文件 12 | */ 13 | public static Properties loadProps(String fileName) { 14 | Properties props = null; 15 | InputStream is = null; 16 | try { 17 | is = ClassUtil.getClassLoader().getResourceAsStream(fileName); 18 | if (is == null) { 19 | throw new FileNotFoundException(fileName + " file is not found"); 20 | } 21 | props = new Properties(); 22 | props.load(is); 23 | } catch (IOException e) { 24 | } finally { 25 | if (is != null) { 26 | try { 27 | is.close(); 28 | } catch (IOException e) { 29 | } 30 | } 31 | } 32 | return props; 33 | } 34 | 35 | /** 36 | * 获取 String 类型的属性值(默认值为空字符串) 37 | */ 38 | public static String getString(Properties props, String key) { 39 | return props.getProperty(key); 40 | } 41 | 42 | /** 43 | * 获取 String 类型的属性值(可指定默认值) 44 | */ 45 | public static String getString(Properties props, String key, String defaultValue) { 46 | String value = defaultValue; 47 | if (props.containsKey(key)) { 48 | value = props.getProperty(key); 49 | } 50 | return value; 51 | } 52 | 53 | /** 54 | * 获取 int 类型的属性值(默认值为 0) 55 | */ 56 | public static int getInt(Properties props, String key) { 57 | return Integer.parseInt(props.getProperty(key)); 58 | } 59 | 60 | /** 61 | * 获取 int 类型的属性值(可指定默认值) 62 | */ 63 | public static int getInt(Properties props, String key, int defaultValue) { 64 | int value = defaultValue; 65 | if (props.containsKey(key)) { 66 | value = Integer.parseInt(props.getProperty(key)); 67 | } 68 | return value; 69 | } 70 | 71 | /** 72 | * 获取 boolean 类型属性(默认值为 false) 73 | */ 74 | public static boolean getBoolean(Properties props, String key) { 75 | return Boolean.parseBoolean(props.getProperty(key)); 76 | } 77 | 78 | /** 79 | * 获取 boolean 类型属性(可指定默认值) 80 | */ 81 | public static boolean getBoolean(Properties props, String key, boolean defaultValue) { 82 | boolean value = defaultValue; 83 | if (props.containsKey(key)) { 84 | value = Boolean.parseBoolean(props.getProperty(key)); 85 | } 86 | return value; 87 | } 88 | 89 | /** 90 | * 获取 boolean 类型属性(默认值为 false) 91 | */ 92 | public static Long getLong(Properties props, String key) { 93 | return Long.parseLong(props.getProperty(key)); 94 | } 95 | 96 | /** 97 | * 获取 boolean 类型属性(可指定默认值) 98 | */ 99 | public static Long getLong(Properties props, String key, Long defaultValue) { 100 | Long value = defaultValue; 101 | if (props.containsKey(key)) { 102 | value =Long.parseLong(props.getProperty(key)); 103 | } 104 | return value; 105 | } 106 | 107 | /** 108 | * 获取 float 类型属性 109 | */ 110 | public static Float getFloat(Properties props, String key) { 111 | return Float.parseFloat(props.getProperty(key)); 112 | } 113 | 114 | /** 115 | * 获取 float 类型属性(可指定默认值) 116 | */ 117 | public static Float getFloat(Properties props, String key, Float defaultValue) { 118 | Float value = defaultValue; 119 | if (props.containsKey(key)) { 120 | value =Float.parseFloat(props.getProperty(key)); 121 | } 122 | return value; 123 | } 124 | 125 | /** 126 | * 获取 double 类型属性 127 | */ 128 | public static Double getDouble(Properties props, String key) { 129 | return Double.parseDouble(props.getProperty(key)); 130 | } 131 | 132 | /** 133 | * 获取 Double 类型属性(可指定默认值) 134 | */ 135 | public static Double getDouble(Properties props, String key, Double defaultValue) { 136 | Double value = defaultValue; 137 | if (props.containsKey(key)) { 138 | value =Double.parseDouble(props.getProperty(key)); 139 | } 140 | return value; 141 | } 142 | 143 | } 144 | -------------------------------------------------------------------------------- /src/main/java/com/wang/spring/utils/ReflectionUtil.java: -------------------------------------------------------------------------------- 1 | package com.wang.spring.utils; 2 | 3 | import java.lang.reflect.Field; 4 | import java.lang.reflect.Method; 5 | 6 | public final class ReflectionUtil { 7 | /** 8 | * 创建实例 9 | */ 10 | public static Object newInstance(Class cls) { 11 | Object instance; 12 | try { 13 | instance = cls.getDeclaredConstructor().newInstance(); 14 | } catch (Exception e) { 15 | throw new RuntimeException(e); 16 | } 17 | return instance; 18 | } 19 | 20 | /** 21 | * 创建实例(根据类名) 22 | */ 23 | public static Object newInstance(String className) { 24 | Class cls = ClassUtil.loadClass(className); 25 | return newInstance(cls); 26 | } 27 | 28 | /** 29 | * 调用方法 30 | */ 31 | public static Object invokeMethod(Object obj, Method method, Object... args) { 32 | Object result; 33 | try { 34 | method.setAccessible(true); 35 | result = method.invoke(obj, args); 36 | } catch (Exception e) { 37 | throw new RuntimeException(e); 38 | } 39 | return result; 40 | } 41 | 42 | /** 43 | * 设置成员变量的值 44 | */ 45 | public static void setField(Object obj, Field field, Object value) { 46 | try { 47 | field.setAccessible(true); 48 | field.set(obj, value); 49 | } catch (Exception e) { 50 | throw new RuntimeException(e); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/resources/WEB-INF/view/login_failed.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Failed! 4 | 5 | 6 |

${user} 未登录!

7 | 8 | -------------------------------------------------------------------------------- /src/main/resources/WEB-INF/view/login_sucess.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Success! 4 | 5 | 6 |

${user} 已经登录成功!

7 | 8 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | #服务端口号 2 | myspring.server.port=8080 3 | #数据库配置 4 | myspring.datasource.jdbc.driver=com.mysql.jdbc.Driver 5 | myspring.datasource.jdbc.url=jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8 6 | #数据库账号 7 | myspring.datasource.jdbc.username=root 8 | #数据库密码 9 | myspring.datasource.jdbc.password="" 10 | #是否使用数据库连接池 11 | myspring.datasource.pool.usePool="" 12 | #连接池容量 13 | myspring.datasource.pool.maxSize=50 14 | #阻塞等待时间 15 | myspring.datasource.pool.waitTimeMill=10000 16 | #扫描包的路径 17 | myspring.app.base_package=com.wang.demo 18 | myspring.app.jsp_path=/WEB-INF/view/ 19 | myspring.app.asset_path=/asset/ 20 | -------------------------------------------------------------------------------- /target/classes/WEB-INF/view/login_failed.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Failed! 4 | 5 | 6 |

${user} 未登录!

7 | 8 | -------------------------------------------------------------------------------- /target/classes/WEB-INF/view/login_sucess.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Success! 4 | 5 | 6 |

${user} 已经登录成功!

7 | 8 | -------------------------------------------------------------------------------- /target/classes/application.properties: -------------------------------------------------------------------------------- 1 | #服务端口号 2 | myspring.server.port=8080 3 | #数据库配置 4 | myspring.datasource.jdbc.driver=com.mysql.jdbc.Driver 5 | myspring.datasource.jdbc.url=jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8 6 | #数据库账号 7 | myspring.datasource.jdbc.username=root 8 | #数据库密码 9 | myspring.datasource.jdbc.password="" 10 | #是否使用数据库连接池 11 | myspring.datasource.pool.usePool="" 12 | #连接池容量 13 | myspring.datasource.pool.maxSize=50 14 | #阻塞等待时间 15 | myspring.datasource.pool.waitTimeMill=10000 16 | #扫描包的路径 17 | myspring.app.base_package=com.wang.demo 18 | myspring.app.jsp_path=/WEB-INF/view/ 19 | myspring.app.asset_path=/asset/ 20 | -------------------------------------------------------------------------------- /target/classes/com/wang/demo/Application.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/demo/Application.class -------------------------------------------------------------------------------- /target/classes/com/wang/demo/configuration/JedisConfig.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/demo/configuration/JedisConfig.class -------------------------------------------------------------------------------- /target/classes/com/wang/demo/controller/TestController.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/demo/controller/TestController.class -------------------------------------------------------------------------------- /target/classes/com/wang/demo/dao/UserMapper.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/demo/dao/UserMapper.class -------------------------------------------------------------------------------- /target/classes/com/wang/demo/interceptor/Interceptor.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/demo/interceptor/Interceptor.class -------------------------------------------------------------------------------- /target/classes/com/wang/demo/model/JedisFake.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/demo/model/JedisFake.class -------------------------------------------------------------------------------- /target/classes/com/wang/demo/model/ResponseEntity.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/demo/model/ResponseEntity.class -------------------------------------------------------------------------------- /target/classes/com/wang/demo/model/User.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/demo/model/User.class -------------------------------------------------------------------------------- /target/classes/com/wang/demo/model/UserRequest.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/demo/model/UserRequest.class -------------------------------------------------------------------------------- /target/classes/com/wang/demo/service/IUserService.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/demo/service/IUserService.class -------------------------------------------------------------------------------- /target/classes/com/wang/demo/service/UserService.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/demo/service/UserService.class -------------------------------------------------------------------------------- /target/classes/com/wang/demo/service/UserService2.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/demo/service/UserService2.class -------------------------------------------------------------------------------- /target/classes/com/wang/mybatis/annotation/Delete.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/mybatis/annotation/Delete.class -------------------------------------------------------------------------------- /target/classes/com/wang/mybatis/annotation/Insert.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/mybatis/annotation/Insert.class -------------------------------------------------------------------------------- /target/classes/com/wang/mybatis/annotation/Mapper.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/mybatis/annotation/Mapper.class -------------------------------------------------------------------------------- /target/classes/com/wang/mybatis/annotation/Param.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/mybatis/annotation/Param.class -------------------------------------------------------------------------------- /target/classes/com/wang/mybatis/annotation/Select.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/mybatis/annotation/Select.class -------------------------------------------------------------------------------- /target/classes/com/wang/mybatis/annotation/Update.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/mybatis/annotation/Update.class -------------------------------------------------------------------------------- /target/classes/com/wang/mybatis/constant/SqlTypeConstant.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/mybatis/constant/SqlTypeConstant.class -------------------------------------------------------------------------------- /target/classes/com/wang/mybatis/core/CGLibMapperProxy.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/mybatis/core/CGLibMapperProxy.class -------------------------------------------------------------------------------- /target/classes/com/wang/mybatis/core/MapperHelper.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/mybatis/core/MapperHelper.class -------------------------------------------------------------------------------- /target/classes/com/wang/mybatis/core/MethodDetails.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/mybatis/core/MethodDetails.class -------------------------------------------------------------------------------- /target/classes/com/wang/mybatis/core/SqlResultCache.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/mybatis/core/SqlResultCache.class -------------------------------------------------------------------------------- /target/classes/com/wang/mybatis/core/SqlSource.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/mybatis/core/SqlSource.class -------------------------------------------------------------------------------- /target/classes/com/wang/mybatis/datasource/DataSource.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/mybatis/datasource/DataSource.class -------------------------------------------------------------------------------- /target/classes/com/wang/mybatis/datasource/NormalDataSource.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/mybatis/datasource/NormalDataSource.class -------------------------------------------------------------------------------- /target/classes/com/wang/mybatis/datasource/PoolDataSource.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/mybatis/datasource/PoolDataSource.class -------------------------------------------------------------------------------- /target/classes/com/wang/mybatis/executor/Executor.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/mybatis/executor/Executor.class -------------------------------------------------------------------------------- /target/classes/com/wang/mybatis/executor/ExecutorFactory.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/mybatis/executor/ExecutorFactory.class -------------------------------------------------------------------------------- /target/classes/com/wang/mybatis/executor/SimpleExecutor.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/mybatis/executor/SimpleExecutor.class -------------------------------------------------------------------------------- /target/classes/com/wang/mybatis/handler/PreparedStatementHandler.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/mybatis/handler/PreparedStatementHandler.class -------------------------------------------------------------------------------- /target/classes/com/wang/mybatis/handler/ResultSetHandler.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/mybatis/handler/ResultSetHandler.class -------------------------------------------------------------------------------- /target/classes/com/wang/mybatis/transaction/SimpleTransactionManager.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/mybatis/transaction/SimpleTransactionManager.class -------------------------------------------------------------------------------- /target/classes/com/wang/mybatis/transaction/TransactionFactory.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/mybatis/transaction/TransactionFactory.class -------------------------------------------------------------------------------- /target/classes/com/wang/mybatis/transaction/TransactionManager.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/mybatis/transaction/TransactionManager.class -------------------------------------------------------------------------------- /target/classes/com/wang/mybatis/transaction/TransactionStatus.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/mybatis/transaction/TransactionStatus.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/annotation/aop/After.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/annotation/aop/After.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/annotation/aop/AfterReturning.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/annotation/aop/AfterReturning.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/annotation/aop/AfterThrowing.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/annotation/aop/AfterThrowing.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/annotation/aop/Around.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/annotation/aop/Around.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/annotation/aop/Aspect.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/annotation/aop/Aspect.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/annotation/aop/Before.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/annotation/aop/Before.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/annotation/aop/Pointcut.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/annotation/aop/Pointcut.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/annotation/aop/Transactional.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/annotation/aop/Transactional.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/annotation/ioc/Autowired.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/annotation/ioc/Autowired.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/annotation/ioc/Bean.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/annotation/ioc/Bean.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/annotation/ioc/Component.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/annotation/ioc/Component.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/annotation/ioc/Configuration.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/annotation/ioc/Configuration.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/annotation/ioc/Qualifier.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/annotation/ioc/Qualifier.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/annotation/ioc/Resource.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/annotation/ioc/Resource.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/annotation/ioc/Service.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/annotation/ioc/Service.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/annotation/ioc/Value.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/annotation/ioc/Value.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/annotation/mvc/Controller.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/annotation/mvc/Controller.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/annotation/mvc/PathVariable.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/annotation/mvc/PathVariable.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/annotation/mvc/RequestBody.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/annotation/mvc/RequestBody.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/annotation/mvc/RequestMapping.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/annotation/mvc/RequestMapping.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/annotation/mvc/RequestParam.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/annotation/mvc/RequestParam.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/annotation/mvc/ResponseBody.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/annotation/mvc/ResponseBody.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/aop/AOPHelper$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/aop/AOPHelper$1.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/aop/AOPHelper.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/aop/AOPHelper.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/aop/Advice.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/aop/Advice.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/aop/CGLibProxy.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/aop/CGLibProxy.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/aop/JoinPoint.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/aop/JoinPoint.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/common/MyProxy.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/common/MyProxy.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/constants/AdviceTypeConstant.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/constants/AdviceTypeConstant.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/constants/BeanScope.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/constants/BeanScope.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/constants/ConfigConstant.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/constants/ConfigConstant.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/constants/IsolationLevelConstant.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/constants/IsolationLevelConstant.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/constants/PropagationLevelConstant.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/constants/PropagationLevelConstant.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/constants/RequestMethod.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/constants/RequestMethod.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/ioc/BeanDefinition.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/ioc/BeanDefinition.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/ioc/BeanDefinitionRegistry.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/ioc/BeanDefinitionRegistry.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/ioc/BeanFactory.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/ioc/BeanFactory.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/ioc/ClassSetHelper.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/ioc/ClassSetHelper.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/ioc/DefaultBeanFactory$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/ioc/DefaultBeanFactory$1.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/ioc/DefaultBeanFactory.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/ioc/DefaultBeanFactory.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/ioc/GenericBeanDefinition.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/ioc/GenericBeanDefinition.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/ioc/ObjectFactory.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/ioc/ObjectFactory.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/mvc/DispatcherServlet.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/mvc/DispatcherServlet.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/mvc/Handler.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/mvc/Handler.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/mvc/HandlerAdapter.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/mvc/HandlerAdapter.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/mvc/ModelAndView.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/mvc/ModelAndView.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/mvc/Request.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/mvc/Request.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/mvc/ResultResolverHandler.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/mvc/ResultResolverHandler.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/tomcat/TomcatServer.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/tomcat/TomcatServer.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/utils/ClassUtil$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/utils/ClassUtil$1.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/utils/ClassUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/utils/ClassUtil.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/utils/ConfigUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/utils/ConfigUtil.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/utils/PropsUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/utils/PropsUtil.class -------------------------------------------------------------------------------- /target/classes/com/wang/spring/utils/ReflectionUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wxwer/MySpringImpl/8254bb74f8d2d61bbbabdc2336f891c6ba8f3b97/target/classes/com/wang/spring/utils/ReflectionUtil.class --------------------------------------------------------------------------------