# Diy-Spring **Repository Path**: bithachi/diy-spring ## Basic Information - **Project Name**: Diy-Spring - **Description**: 手写Spring和SpringMVC框架的学习,并用手写的框架实现一个简单的RBAC系统练手。 - **Primary Language**: Java - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 0 - **Created**: 2021-07-26 - **Last Updated**: 2022-06-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 1. 项目介绍 ## 1.1 项目简介 ​ 最初这个项目的想法是使用原生 Servlet 写一个简单的 RBAC系统, 复习一下 Java Web 相关的知识点, 写着写着, 感觉原生Servlet 写起来有诸多问题, 比如我想使用注解实现事务、权限鉴权、日志记录、实现Controller-Service-Dao分层,我发现原生的 Servlet 不能满足我的需求,于是我开始查阅资料,我发现可以自己试试手写 Spring 相关的功能实现我的需求。 ​ 于是我开始搜索资料,找到了一个入门版本的手写 Spring 视频,跟着视频做,完成了 Bean 容器和IOC 注入的毛胚房版本,写完之后,感觉手写实现相关框架的功能并不是那么的遥不可及,只要好好利用注解和反射等一些基础知识,就可以实现像Spring框架那样的功能,尝到了一点甜头,于是最终决定手写 Spring IOC AOP MVC 的部分核心功能去实现这个练手的 RBAC 小系统,由此这个项目孕育而生。 ​ 本项目只是实现了 Spring 部分核心的功能而已,可以作为学习使用,万万不可用于生产环境之中。 > 演示地址:http://servletrbac.bithachi.cn:8080/ > 账号:bithachi > 密码:123456 > Druid 监控面板:http://servletrbac.bithachi.cn:8080/druid/login.html > 账号:druid > 密码:druid ## 1.2 部分截图 ​ 项目部分截图展示: ![image-20210825165557550](http://image.bithachi.cn/202108251655028.png) ![image-20210825165645967](http://image.bithachi.cn/202108251656125.png) ![image-20210825165734641](http://image.bithachi.cn/202108251657807.png) ![image-20210825165758150](http://image.bithachi.cn/202108251657264.png) ![image-20210825165821814](http://image.bithachi.cn/202108251658948.png) ![image-20210825165853997](http://image.bithachi.cn/202108251658141.png) ![image-20210825165943224](http://image.bithachi.cn/202108251659374.png) ![image-20210827232550399](http://image.bithachi.cn/202108272325466.png) ![image-20210827232524768](http://image.bithachi.cn/202108272325829.png) ## 1.3 示例代码 ### 1.3.1 @Controller类 ```java /** * @author: BitHachi * @email: bithachi@163.com */ @RequestMapping("/user") @Controller public class UserController { private static final Logger LOGGER= LoggerFactory.getLogger(UserController.class); @Autowired private UserService userService; @Autowired private RoleService roleService; @HavePermission("user:list") @RequestMapping(value = "/list",method = HttpMethod.GET) public View list() { return new View("user/list.jsp"); } @HavePermission("user:list") @RequestMapping(value = "/list",method = HttpMethod.POST) public Data list(Param param) { // 获取分页参数 PageInDTO pageInDTO = PageUtil.getPageParam(param); // 获取分页数据 PageDTO pageOutDTO = userService.listUser(pageInDTO); return new Data(pageOutDTO); } @HavePermission("user:add") @RequestMapping(value = "/add",method = HttpMethod.GET) public View add() { return new View("user/add.jsp"); } @HavePermission("user:add") @RequestMapping(value = "/add",method = HttpMethod.POST) public Data add(Param param) { UserInDTO userInDTO = new UserInDTO(); try { BeanUtils.populate(userInDTO,param.getFieldMap()); } catch (Exception e) { LOGGER.error("BeanUtils.copyProperties(dest,orig)转换失败!", e); return new Data(new ResultDTO(StatusEnum.DATA_CONVERSION_ERROR)); } ResultDTO result = userService.add(userInDTO); return new Data(result); } } ``` ### 1.3.2 @Service类 ```java /** * 用户相关服务 * * @author: BitHachi * @email: bithachi@163.com */ @Service public class UserServiceImpl implements UserService { public static final Logger LOGGER = LoggerFactory.getLogger(UserServiceImpl.class); @Autowired private UserDao userDao ; /** * 用户列表 * * @return List */ @Override public PageDTO listUser(PageInDTO pageInDTO) { // 查询数据 List userPOList = userDao.listUser(pageInDTO.getSearchString(), pageInDTO.getOrderField(), pageInDTO.getOrderType(), pageInDTO.getStart(), pageInDTO.getLength()); List userDTOList; try { userDTOList = ColaBeanUtils.copyListProperties(UserDTO::new, userPOList); } catch (Exception e) { LOGGER.error("BeanUtils.copyProperties(dest,orig)转换失败!", e); throw new RuntimeException(e); } // 过滤后的总记录数 int countRecordsFiltered = userDao.countRecordsFiltered(pageInDTO.getSearchString()); // 数据表总记录数 int countRecords = userDao.countRecords(); PageDTO pageOutDTO = new PageDTO(); pageOutDTO.setData(userDTOList); pageOutDTO.setRecordsFiltered(countRecordsFiltered); pageOutDTO.setRecordsTotal(countRecords); pageOutDTO.setDraw(pageInDTO.getDraw()); return pageOutDTO; } } ``` ### 1.3.3 @Dao类 ```java /** * @author: BitHachi * @email: bithachi@163.com */ @Dao public class UserDaoImpl implements UserDao { private static final Logger LOGGER = LoggerFactory.getLogger(UserDaoImpl.class); /** * 表名 */ private final String TABLE_NAME = " user "; /** * 所有字段 */ private final String ALL_FIELD_NAME = " uid,username,name,phone,email "; /** * 根据用户名和密码查询用户 * * @param username 用户名 * @param password 密码 * @return User */ @Override public UserPO getUserByUserNameAndPassword(String username, String password) { String sql = "SELECT" + ALL_FIELD_NAME + "FROM" + TABLE_NAME + " WHERE username=? AND password=?"; UserPO user = DatabaseHelper.queryEntity(UserPO.class, sql, username, password); return user; } } ``` ### 1.3.4 @Aspect切面类 ```java /** * 鉴权处理 * * @author: BitHachi * @email: bithachi@163.com */ @SuppressWarnings("all") @Aspect(pkg = "cn.bithachi.rbac.controller") public class AuthAspect extends AspectProxy { private static final Logger LOGGER = LoggerFactory.getLogger(AuthAspect.class); /** * 开始增强 */ @Override public void begin() { // LOGGER.info("权限的开始增强!"); } /** * 切入点判断 */ @Override public boolean intercept(Method method, Object[] params) throws Throwable { // LOGGER.info("权限的切入点判断!"); // 判断 Method 是否带 RequestMapping 或 HavePermission 注解 if (method.isAnnotationPresent(RequestMapping.class) || method.isAnnotationPresent(HavePermission.class)) { return true; } else { return false; } } /** * 前置增强 */ @Override public boolean before(Method method, Object[] params) throws Throwable { LOGGER.info("权限的前置增强!"); LOGGER.info("是否已经向前端发出response响应: : "+DataContext.getResponse().isCommitted()); /******************** 是否登录 ********************/ // 判断 Method 是否带 RequestMapping 注解 if (method.isAnnotationPresent(RequestMapping.class)) { RequestMapping requestMapping = method.getAnnotation(RequestMapping.class); // Method 请求路径 String methodRequestPath = requestMapping.value(); // 如果不是login,就需要判断session有无会话信息记录user if (!"/login".equals(methodRequestPath)) { Object user = DataContext.Session.get("user"); if (user == null) { HttpServletResponse response = DataContext.getResponse(); response.setContentType("text/html"); response.setCharacterEncoding("UTF-8"); PrintWriter writer = response.getWriter(); writer.write(("")); writer.flush(); writer.close(); LOGGER.info("是否已经向前端发出response响应: : "+DataContext.getResponse().isCommitted()); return false; } } } /******************** 是否有相应的权限访问 ********************/ // 判断 Method 是否带 HavePermission 注解 if (method.isAnnotationPresent(HavePermission.class)) { HavePermission havePermission = method.getAnnotation(HavePermission.class); // 获取权限标识字符串 String permissionFlag = havePermission.value(); // 获取登录之后保存的会话信息里面的权限信息 List listPermissionDTO = DataContext.Session.get("permissions"); // LOGGER.info(permissionFlag); if (listPermissionDTO != null) { for (PermissionDTO permissionDTO : listPermissionDTO) { // LOGGER.info(permissionDTO.getFlag()); // 如果用户拥有的权限列表中有此权限标识,则直接方法返回, 继续执行后面的步骤 if (permissionDTO.getFlag().equals(permissionFlag)) { return true; } } // 否则直接返回相应的响应提示 HttpServletResponse response = DataContext.getResponse(); response.setContentType("text/html"); response.setCharacterEncoding("UTF-8"); PrintWriter writer = response.getWriter(); writer.write(("")); writer.flush(); writer.close(); LOGGER.info("是否已经向前端发出response响应: "+DataContext.getResponse().isCommitted()); return false; } } return true; } /** * 后置增强 */ @Override public void after(Method method, Object[] params, Object result) throws Throwable { LOGGER.info("权限的后置增强!"); } /** * 异常增强 */ @Override public void error(Method method, Object[] params, Throwable e) { // LOGGER.info("权限的异常增强!"); } /** * 最终增强 */ @Override public void end() { // LOGGER.info("权限的最终增强!"); } } ``` ### 1.3.5 自定义JSP标签实现按钮级别显示 ```jsp 添加用户 ``` ```java /** * @author: BitHachi * @email: bithachi@163.com */ public class DiyTag extends TagSupport { private static final Logger LOGGER = LoggerFactory.getLogger(DiyTag.class); private static final long serialVersionUID = -8379410253641841380L; /** * 权限标识: user:add */ private String permissionFlag; public DiyTag() { } /** * doStartTag()方法是遇到标签开始时会执行的方法, * 其合法的返回值是EVAL_BODY_INCLUDE与SKIP_BODY, * 前者表示将显示标签间的文字,后者表示不显示标签间的文字; * * @return * @throws JspException */ @Override public int doStartTag() throws JspException { List listPermissionDTO = DataContext.Session.get("permissions"); try { if (listPermissionDTO != null) { for (PermissionDTO permissionDTO : listPermissionDTO) { if (permissionDTO.getFlag().equals(permissionFlag)) { return EVAL_BODY_INCLUDE; } } } return SKIP_BODY; } catch (Exception e) { throw new RuntimeException("数据加载异常", e); } } public void setPermissionFlag(String permissionFlag) { this.permissionFlag = permissionFlag; } } ``` ### 1.3.6 config.properties ```properties # 扫描包路径 app.base_package=cn.bithachi.rbac # JSP基础路径 app.jsp_path=/WEB-INF/ # 静态资源路径 app.asset_path=/www/ # 数据库配置 jdbc.type=mysql jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://xxx:3306/servlet_rbac jdbc.username=servlet_rbac jdbc.password=xxx #使用过滤器 若不配置 则不会统计SQL执行 druid.filters=stat,slf4j ``` # 2. 项目功能 **项目分为两部分:手写框架和RBAC实现。** ## 2.1 手写框架 - @Controller、@Service、@Dao 标明类,并注入到 Bean 容器中 - @Aspect 表明切面类,实现AOP功能 - @RequestMapping 实现控制器类方法和URI的映射 - @Autowired 标明类的成员变量,进行 Bean 注入 - @Transactional 标明 Service 类的方法,实现注解事务支持 - DataContext 类,使用 ThreadLocal 实现每个 http 请求线程 request 和 response 的封装隔离 - DispatcherServlet 类,完成系统一系列的初始化,接受所有的前端请求,交给相应的控制器类方法处理,对返回的结果 Data 或 View 进行相关处理 - Data 类,对 Congtroller 类返回的数据进行封装,在 DispatcherServlet 类中转成 JSON 给前端 - View类,对 Congtroller 类返回的视图进行封装,在 DispatcherServlet 类中进行重定向或请求转发 - Param 类,对 Congtroller 类的方法参数进行封装,这些被封装的参数来自于前端传过来的 request 域中 ## 2.2 RBAC实现 - 用户可以拥有多个角色,角色可以拥有多个权限。 - 系统左侧菜单,根据用户拥有的权限进行渲染 - 权限分为三级:目录-菜单-按钮 - @HavePermission 标明控制器类方法的调用需要什么权限 - LogAspect 切面类实现登录和操作日志的记录 - AuthAspect 切面类实现对登录和权限的鉴权,未通过验证,将不会执行目标控制类方法,并返回友好提示 - 自定义 JSP 标签 havePermission 实现按钮级别的权限显示 - 使用 Druid 监控面板对执行的 SQL 等数据进行监控 # 3. 项目目录 ```cmd └─cn └─bithachi ├─framework # 手写SPring框架目录 │ │ DataContext.java # 封装每个http的request和response │ │ DispatcherServlet.java # 完成系统一系列的初始化,接受所有的前端请求,交给相应的控制器类方法处理,对返回的结果 Data 或 View 进行相关处理 │ │ InitLoader.java # 负责一系列的系统初始化加载:类扫描、Bean容器、生成AOP代理对象、IOC注入Bean成员变量、URI和控制器类方法的映射 │ │ │ ├─anno # 框架注解 │ │ Aspect.java # 标明切面类 │ │ Autowired.java # 标明需要IOC注入的Bean成员变量 │ │ Controller.java # 标明控制器类 │ │ Dao.java # 标明数据库访问对象类 │ │ RequestMapping.java # 标明控制器类方法的请求URI路径 │ │ Service.java # 标明服务类 │ │ Transactional.java # 标明服务类的某个方法是否需要开启事务 │ │ │ ├─bean # 框架内部需要用到的 Bean 对象 │ │ Data.java # 封装返回给前端的 JSON 数据对象 │ │ FileParam.java # 前端文件参数封装 │ │ FormParam.java # 前端普通字段封装 │ │ Handler.java # 控制器 Class 和控制器 Method 的封装 │ │ Param.java # 封装 FileParam 和 FormParam │ │ Request.java # HTTP请求方法 requestMethod 和 请求路径 requestPath 的封装 │ │ View.java # 视图路径 path 和 模型数据 model 的封装 │ │ │ ├─constant # 框架常量类 │ │ ConfigConstant.java # 相关配置项常量 │ │ HttpMethod.java # HTTP请求方法的枚举: GET, HEAD, POST, PUT │ │ │ ├─exception # 框架异常类 │ │ AuthcException.java │ │ AuthzException.java │ │ UploadException.java │ │ │ ├─helper # 框架助手类 │ │ AopHelper.java # 负责 AOP 代理对象生成 │ │ BeanHelper.java # 负责 Bean 容器的创建 │ │ ClassHelper.java # 负责扫描初始化原始类对象 │ │ ConfigHelper.java # 负责获取配置文件中指定的内容 │ │ ControllerHelper.java # 负责为请求URI设置对应的控制器方法映射 │ │ DatabaseHelper.java # 数据库相关的一些初始化、事务、CRUD │ │ IocHelper.java # 负责@Autowired注解标注的Bean成员变量的注入 │ │ RequestHelper.java # 获取前端请求的参数 │ │ UploadHelper.java # 封装文件上传相关操作 │ │ │ ├─proxy # 代理类 │ │ AspectProxy.java # 抽象模板,代理切面类 │ │ Proxy.java # 代理接口 │ │ ProxyChain.java # 代理链类:targetClass,targetObject,methodProxy,methodParams,proxyList │ │ ProxyFactory.java # 代理工厂类,使用 Cglib 对目标类生成代理链对象 │ │ TransactionProxy.java # 事务代理类,框架默认对添加了 @Transactional 的 service 方法提供事务代理 │ │ │ └─util # 各种工具类 │ ArrayUtil.java # 数组操作工具类 │ CastUtil.java # 数据类型转换工具类 │ ClassUtil.java # 对类操作的工具类,获取类加载器,某个包下所有类集合,加载某个类 │ CodecUtil.java # 编码与解码操作工具类 │ CollectionUtil.java # 集合操作工具类 │ FileUtil.java # 文件操作工具类 │ PropsUtil.java # xxx.properties属性文件操作工具类 │ ReflectionUtil.java # 反射工具类,创建实例对象,调用对象方法,设置对象成员变量的值(Autowired) │ StreamUtil.java # 流操作工具类 │ StringUtil.java # 字符串操作工具类 │ ThreadUtil.java # 返回当前线程方法调用栈工具类 │ └─rbac # 实践手写Spring框架,简单RBAC小系统目录 ├─anno │ HavePermission.java # 标明控制器类方法需要什么权限 │ ├─aop │ AuthAspect.java # 对登录和权限的鉴权,未通过验证将中断代理链的执行,并返回友好提示 │ LogAspect.java # 对登录和操作日志进行记录 │ ├─constant │ StatusEnum.java # 存放各种业务状态码: 200,400 │ ├─controller # 控制器类 │ LogController.java │ PermissionController.java │ RoleController.java │ SystemController.java │ TestController.java │ UserController.java │ ├─dao # 数据库访问对象类 │ │ LogDao.java │ │ PermissionDao.java │ │ RoleDao.java │ │ UserDao.java │ │ │ └─impl │ LogDaoImpl.java │ PermissionDaoImpl.java │ RoleDaoImpl.java │ UserDaoImpl.java │ ├─pojo # 简单的Java对象 │ ├─dto # 数据传输对象 │ │ ├─in # 主要用于接收前端的参数,再作为参数传给 Service 类的方法 │ │ │ AuthInDTO.java │ │ │ PageInDTO.java │ │ │ PermissionInDTO.java │ │ │ RoleInDTO.java │ │ │ UserInDTO.java │ │ │ │ │ └─out # 主要用于 Service 类的方法的返回结果 │ │ LogDTO.java │ │ PageDTO.java │ │ PermissionDTO.java │ │ ResultDTO.java │ │ RoleDTO.java │ │ UserDTO.java │ │ │ ├─entity # 实体类,Dao层复杂数据的返回使用entity │ │ Permission.java │ │ Role.java │ │ User.java │ │ │ ├─po # 持久化类对象,与数据库表字段一一对应 │ │ LogPO.java │ │ PermissionPO.java │ │ RolePO.java │ │ UserPO.java │ │ │ └─vo # 视图对象,主要用于Controller方法返回给前端的数据,本系统中,没有使用 │ ├─page │ │ PageVO.java │ │ │ └─user │ UserVO.java │ ├─service # 服务类 │ │ LogService.java │ │ PermissionService.java │ │ RoleService.java │ │ SystemService.java │ │ UserService.java │ │ │ └─impl │ LogServiceImpl.java │ PermissionServiceImpl.java │ RoleServiceImpl.java │ SystemServiceImpl.java │ UserServiceImpl.java │ ├─tag # 自定义JSP标签的处理类 │ DiyTag.java │ └─util # 工具类 ColaBeanUtils.java # 负责Bean对象的拷贝 OsUtil.java # 获取操作系统相关信息的工具类 PageUtil.java # 封装前端Datatable插件传过来的分页参数工具类 src/main/webapp/www/static/business/js/main.js # 前端业务相关的JS,添加、删除、编辑弹窗的打开等 ``` # 4. 技术选型 ## 4.1 前端 | 名称 | 说明 | 文档地址 | | --------------- | -------------- | --------------------------------------------------------- | | JQuery | JavaScript 库 | https://jquery.cuishifeng.cn/ | | Datatables | jquery表格插件 | http://datatables.club/ | | JQuery Validate | 表单验证 | https://www.runoob.com/jquery/jquery-plugin-validate.html | | layer | 弹出层组件 | https://www.layui.com/doc/modules/layer.html | | zTree | jQuery 树插件 | http://www.treejs.cn/v3/main.php#_zTreeInfo | | treeTable | 树形表格 | https://gitee.com/whvse/treetable-lay | | H-ui | 轻量级前端框架 | http://www.h-ui.net/ | ## 4.2 后端 | 名称 | 说明 | 文档地址 | | ------------------- | -------------------------------------------------- | ------------------------------------------------------------ | | JUnit | 单元测试 | https://junit.org/junit5/docs/current/user-guide/ | | SLF4J | Java中所有日志框架的简单抽象 | http://www.slf4j.org/docs.html | | Servlet | 运行在 Web 服务器或应用服务器上的程序 | https://www.runoob.com/servlet/servlet-intro.html | | EL | 在 JSP 中简化表达式的方法 | http://c.biancheng.net/view/4487.html | | JSP | Java服务器页面 | https://www.w3cschool.cn/jsp/ | | JSTL | JSP 标准标签库 | https://www.w3cschool.cn/jsp/jsp-jstl.html | | Fastjson | 用于Java 对象和JSON的相互转换 | http://www.dba.cn/book/fastjson/ | | druid | 数据库连接池 | http://www.apache-druid.cn/ | | CGLib | 动态生成一个要代理类的子类 | https://www.runoob.com/w3cnote/cglibcode-generation-library-intro.html | | Apache Commons | Apache 常用工具包 | https://commons.apache.org/components.html | | commons-lang | 通用的工具类集,提供了一些java.lang中类的扩展功能 | https://commons.apache.org/proper/commons-lang/ | | commons-collections | 提供一个类包来扩展和增加标准的 Java Collection框架 | https://commons.apache.org/proper/commons-collections/ | | commons-beanutils | 用于操作JAVA bean的工具包 | https://commons.apache.org/beanutils/ | | commons-dbutils | 用于操作数据库的工具包 | https://commons.apache.org/dbutils/ | | commons-fileupload | 处理HTTP文件上传 | https://commons.apache.org/fileupload/ | | commons-codec | 用于摘要运算、编码解码的包。 Base64、MD5、DES等 | https://commons.apache.org/codec/ | | hutool | 一个小而全的Java工具类库 | https://hutool.cn/docs/#/ | | oshi-core | 获取系统信息 | https://blog.csdn.net/qq_41609208/article/details/105856260 | # 5. 环境和工具 ## 5.1 开发工具 | 名称 | 说明 | 官网 | | --------------- | ---------------------------------- | ------------------------------------------------ | | IDEA | Java开发IDE | https://www.jetbrains.com/idea/download | | Navicat Premium | 一套可创建多个连接的数据库管理工具 | https://www.navicat.com.cn/support/online-manual | | SourceTree | 免费Git图形界面工具 | https://www.sourcetreeapp.com/ | ## 5.2 开发环境 | 名称 | 说明 | 官网 | | ------ | ------ | ------------------------------------------------------------ | | JDK | 1.8 | https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html | | Maven | 3.8.1 | http://maven.apache.org/ | | MySQL | 5.7 | https://www.mysql.com/ | | Tomcat | 9.0.52 | https://tomcat.apache.org/download-90.cgi | ## 5.3 部署相关 | 名称 | 说明 | 官网 | | ------ | ------------------------ | -------------------------------------------------- | | Centos | 7.3.1611 | https://www.centos.org/ | | 宝塔 | 简单好用的服务器运维面板 | https://www.bt.cn/ | | 阿里云 | 云服务器 | https://help.aliyun.com/document_detail/58612.html | | Tomcat | 9.x.x | https://tomcat.apache.org/download-90.cgi | | 腾讯云 | 域名 | https://dnspod.cloud.tencent.com/ | ## 5.4 文档相关 | 名称 | 说明 | 官网 | | ------- | -------------------------- | ------------------------- | | Typora | 免费的跨平台Markdown编辑器 | https://www.typora.net/ | | draw.io | 开源流程图工具 | https://app.diagrams.net/ | # 6. 框架解析 ## 6.1 框架初始化 ### 6.1.2 初始化加载流程图 千里之行始于足下,系统最重要的一步就是需要完成框架的初始化,后续系统操作都要依靠框架初始化后的相关信息。 关于系统框架的初始化加载,我目前知道的有两种方式实现: 1. 监听器方式:实现 [ServletContextListener](https://www.liaoxuefeng.com/wiki/1252599548343744/1304266123771937) 接口,并重写 contextInitialized 方法,在 contextInitialized 中编写系统初始化的一系列操作。 2. Servlet的init(x) 方法:众所周知,每一个 Servlet 的 init(x) 将在第一次请求时执行一次,后续请求将不再执行,**笔者手写的框架采用的是这种方式。** 本系统框架初始化加载流程图如下所示: ![系统初始化](http://image.bithachi.cn/202108261818264.png) 系统初始化主要利用类加载机制去实现各种数据的初始化,使用 **Class.forName(className, isInitialized, classLoader)** 方法加载类,加载类的过程中,static修饰的静态成员变量和静态代码块会执行,主要在static代码块中编写初始化加载的相关代码。 ### 6.1.2 一些重要初始化方法 **在整个系统加载的过程中,有以下方法非常重要:** ```java // 使用类加载器的资源查找算法,返回一个 URL 枚举,可用于访问 resName 描述的资源。 // 在扫描包时使用。 public Enumeration getResources(String resName) // 通过使用类加载器的资源查找算法查找 resName 来返回资源上的流。 // 在加载配置文件信息时使用。 // config.properties public InputStream getResourceAsStream (String resName) // 从配置文件中取出某个值。 public String getProperty(String key) // className - 类的完全限定名称 class cn.bithachi.rbac.controller.LogController // initializeBoolean - 指示是否应该初始化该类。 // classLoader - 类加载器 // 在加载类时使用 public static Class forName(String className, boolean initializeBoolean, ClassLoader classLoader) // 通过调用默认(即零参数)构造函数创建类的实例对象。 // 创建Bean容器时使用。 public T newInstance() // isAssignableFrom() 判断 superClass 和 cls 是否相同或 superClass 是否是 cls 的父类/接口 // 在实现AOP时使用 superClass.isAssignableFrom(cls) // 给目标类创建一个代理链对象 // 在实现AOP时使用 Object proxy = ProxyFactory.createProxy(targetClass, proxyList); /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * 输入一个目标类和一组Proxy接口实现类(切面对象), 返回一个代理对象 * * @param targetClass 要被代理的目标类 * @param proxyList 目标类的所有切面对象链表 * @param 目标类的代理对象 * @return */ @SuppressWarnings("unchecked") public static T createProxy(final Class targetClass, final List proxyList) { class MyMethodInterceptor implements MethodInterceptor{ /** * 每次调用代理类的方法都会被方法拦截器intercept()拦截 * 在调用目标方法时,CGLib会回调MethodInterceptor接口的intercept方法拦截,来实现你自己的代理逻辑,类似于JDK中的InvocationHandler接口。 * 每次调用目标方法时都会先创建一个 ProxyChain 对象, 然后调用该对象的 doProxyChain() 方法(一系列的代理业务逻辑),方法执行完后,intercept()再将结果返回出去 * * * @param thisObject 增强对象,this( new MethodInterceptor(){xxx})本身 * @param targetMethod 目标方法 * @param methodParams 方法参数 * @param methodProxy 方法代理,用于调用 super(非拦截方法);可以根据需要多次调用 * @return * @throws Throwable */ @Override public Object intercept(Object thisObject, Method targetMethod, Object[] methodParams, MethodProxy methodProxy) throws Throwable { return new ProxyChain(targetClass, thisObject, targetMethod, methodProxy, methodParams, proxyList).doProxyChain(); } } return (T) Enhancer.create(targetClass, new MyMethodInterceptor()); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // 反射获取类的所有成员变量 // 在IOC使用 public Field[] getDeclaredFields() Field[] beanFields = beanClass.getDeclaredFields(); // 判断对象(类|属性字段|方法)是由有某个注解标注 public boolean isAnnotationPresent(Class annotationClass) cls.isAnnotationPresent(Controller.class) beanField.isAnnotationPresent(Autowired.class); method.isAnnotationPresent(RequestMapping.class) // 将obj对象的field设置值为value public void set(Object obj, Object value) field.set(obj, value) // 返回类的指定注解 public A getAnnotation(Class annotation) RequestMapping requestMapping = controllerClass.getAnnotation(RequestMapping.class); //获取ServletContext对象, 用于注册Servlet ServletContext servletContext = servletConfig.getServletContext(); //1.处理JSP的Servlet ServletRegistration jspServlet = servletContext.getServletRegistration("jsp"); jspServlet.addMapping(ConfigHelper.getAppJspPath() + "*"); //2.处理静态资源的默认Servlet ServletRegistration defaultServlet = servletContext.getServletRegistration("default"); //网站头像 defaultServlet.addMapping("/favicon.ico"); //静态资源 js css ... defaultServlet.addMapping(ConfigHelper.getAppAssetPath() + "*"); ``` ### 6.1.3 初始化后的重要数据 ```java /** * 定义类集合(存放基础包名下的所有广义的Class对象),广义的Class对象有狭义的Class和interface */ private static final Set> CLASS_SET; /** * BEAN_MAP相当于一个Bean 容器, 拥有项目所有bean的实例 * */ private static final Map, Object> BEAN_MAP = new HashMap, Object>(); /** * REQUEST_HANDLER_MAP为 "请求=处理器" 的映射,请求处理器容器 */ private static final Map REQUEST_HANDLER_MAP = new HashMap(); Request: Request{requestMethod='GET', requestPath='/user/list'} Handler: UserController = list() ``` ### 6.1.4 初始化日志 为了方便调试和学习,我在初始化相关代码中写了日志打印,系统的初始化加载日志如下: #### (1)Class类集合 ```cmd [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.DispatcherServlet:40) - ****************** servlet init() start **************************** [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.InitLoader:23) - *************** init() start ****************** [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:27) - *************** 所有Class的Set集合 ********************* [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.aop.LogAspect [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.service.impl.RoleServiceImpl [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.pojo.dto.out.LogDTO [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.controller.SystemController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.pojo.dto.out.PermissionDTO [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - interface cn.bithachi.rbac.util.ColaBeanUtils$ColaBeanUtilsCallBack [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - interface cn.bithachi.rbac.service.PermissionService [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.pojo.dto.in.RoleInDTO [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.pojo.po.PermissionPO [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.service.impl.SystemServiceImpl [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.pojo.dto.in.PageInDTO [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.service.impl.LogServiceImpl [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.constant.StatusEnum [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.controller.RoleController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.controller.LogController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.util.ColaBeanUtils [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.service.impl.PermissionServiceImpl [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.pojo.dto.in.UserInDTO [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - interface cn.bithachi.rbac.dao.RoleDao [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.dao.impl.UserDaoImpl [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.dao.impl.RoleDaoImpl [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.util.PageUtil [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.pojo.dto.in.AuthInDTO [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - interface cn.bithachi.rbac.service.RoleService [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.dao.impl.PermissionDaoImpl [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - interface cn.bithachi.rbac.dao.UserDao [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.pojo.entity.User [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.controller.PermissionController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.pojo.dto.out.PageDTO [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.tag.DiyTag [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.pojo.entity.Role [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.pojo.dto.out.ResultDTO [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.util.OsUtil [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - interface cn.bithachi.rbac.dao.LogDao [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.controller.UserController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.dao.impl.LogDaoImpl [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - interface cn.bithachi.rbac.anno.HavePermission [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.pojo.dto.out.RoleDTO [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - interface cn.bithachi.rbac.service.UserService [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.aop.AuthAspect [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.pojo.entity.Permission [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.pojo.po.UserPO [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.pojo.po.LogPO [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - interface cn.bithachi.rbac.service.LogService [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.pojo.vo.page.PageVO [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - interface cn.bithachi.rbac.service.SystemService [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.pojo.dto.in.PermissionInDTO [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.pojo.po.RolePO [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.pojo.dto.out.UserDTO [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.pojo.vo.user.UserVO [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.controller.TestController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - interface cn.bithachi.rbac.dao.PermissionDao [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ClassHelper:34) - class cn.bithachi.rbac.service.impl.UserServiceImpl ``` #### (2)Bean容器 ```java [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.BeanHelper:35) - *************** [Controller 、 Service 、 Dao 对应的 Class] 和 [Bean实例对象] 的映射: ********************* [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.BeanHelper:37) - Class: class cn.bithachi.rbac.controller.LogController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.BeanHelper:38) - Bean实例对象: cn.bithachi.rbac.controller.LogController@5760900 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.BeanHelper:37) - Class: class cn.bithachi.rbac.service.impl.RoleServiceImpl [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.BeanHelper:38) - Bean实例对象: cn.bithachi.rbac.service.impl.RoleServiceImpl@7c879178 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.BeanHelper:37) - Class: class cn.bithachi.rbac.service.impl.PermissionServiceImpl [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.BeanHelper:38) - Bean实例对象: cn.bithachi.rbac.service.impl.PermissionServiceImpl@758e8c7f [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.BeanHelper:37) - Class: class cn.bithachi.rbac.controller.SystemController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.BeanHelper:38) - Bean实例对象: cn.bithachi.rbac.controller.SystemController@1cab1584 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.BeanHelper:37) - Class: class cn.bithachi.rbac.dao.impl.UserDaoImpl [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.BeanHelper:38) - Bean实例对象: cn.bithachi.rbac.dao.impl.UserDaoImpl@29a02118 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.BeanHelper:37) - Class: class cn.bithachi.rbac.controller.UserController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.BeanHelper:38) - Bean实例对象: cn.bithachi.rbac.controller.UserController@696c7905 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.BeanHelper:37) - Class: class cn.bithachi.rbac.dao.impl.RoleDaoImpl [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.BeanHelper:38) - Bean实例对象: cn.bithachi.rbac.dao.impl.RoleDaoImpl@6880fd23 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.BeanHelper:37) - Class: class cn.bithachi.rbac.dao.impl.LogDaoImpl [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.BeanHelper:38) - Bean实例对象: cn.bithachi.rbac.dao.impl.LogDaoImpl@2cc3d282 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.BeanHelper:37) - Class: class cn.bithachi.rbac.controller.TestController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.BeanHelper:38) - Bean实例对象: cn.bithachi.rbac.controller.TestController@4438ee3 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.BeanHelper:37) - Class: class cn.bithachi.rbac.service.impl.SystemServiceImpl [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.BeanHelper:38) - Bean实例对象: cn.bithachi.rbac.service.impl.SystemServiceImpl@e6d6b3f [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.BeanHelper:37) - Class: class cn.bithachi.rbac.service.impl.LogServiceImpl [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.BeanHelper:38) - Bean实例对象: cn.bithachi.rbac.service.impl.LogServiceImpl@61ebe634 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.BeanHelper:37) - Class: class cn.bithachi.rbac.dao.impl.PermissionDaoImpl [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.BeanHelper:38) - Bean实例对象: cn.bithachi.rbac.dao.impl.PermissionDaoImpl@530e6f49 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.BeanHelper:37) - Class: class cn.bithachi.rbac.controller.PermissionController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.BeanHelper:38) - Bean实例对象: cn.bithachi.rbac.controller.PermissionController@4ba2c75d [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.BeanHelper:37) - Class: class cn.bithachi.rbac.controller.RoleController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.BeanHelper:38) - Bean实例对象: cn.bithachi.rbac.controller.RoleController@2ef37985 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.BeanHelper:37) - Class: class cn.bithachi.rbac.service.impl.UserServiceImpl [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.BeanHelper:38) - Bean实例对象: cn.bithachi.rbac.service.impl.UserServiceImpl@1097f029 ``` #### (3)AOP 创建代理对象过程 ```java [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:33) - *************** 切面类 ---- 目标类(需要被代理的类)集合的映射 ********************* [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:35) - 切面类: class cn.bithachi.rbac.aop.LogAspect [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:36) - 目标类(需要被代理的类): [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:38) - class cn.bithachi.rbac.controller.LogController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:38) - class cn.bithachi.rbac.controller.TestController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:38) - class cn.bithachi.rbac.controller.SystemController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:38) - class cn.bithachi.rbac.controller.PermissionController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:38) - class cn.bithachi.rbac.controller.UserController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:38) - class cn.bithachi.rbac.controller.RoleController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:35) - 切面类: class cn.bithachi.rbac.aop.AuthAspect [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:36) - 目标类(需要被代理的类): [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:38) - class cn.bithachi.rbac.controller.LogController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:38) - class cn.bithachi.rbac.controller.TestController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:38) - class cn.bithachi.rbac.controller.SystemController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:38) - class cn.bithachi.rbac.controller.PermissionController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:38) - class cn.bithachi.rbac.controller.UserController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:38) - class cn.bithachi.rbac.controller.RoleController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:35) - 切面类: class cn.bithachi.framework.proxy.TransactionProxy [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:36) - 目标类(需要被代理的类): [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:38) - class cn.bithachi.rbac.service.impl.RoleServiceImpl [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:38) - class cn.bithachi.rbac.service.impl.PermissionServiceImpl [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:38) - class cn.bithachi.rbac.service.impl.SystemServiceImpl [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:38) - class cn.bithachi.rbac.service.impl.LogServiceImpl [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:38) - class cn.bithachi.rbac.service.impl.UserServiceImpl [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:46) - *************** 目标类(需要被代理的类) -- 切面对象列表的映射 ********************* [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:48) - 目标类(需要被代理的类): class cn.bithachi.rbac.controller.LogController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:49) - 切面对象列表: [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:51) - cn.bithachi.rbac.aop.LogAspect@6d86103f [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:51) - cn.bithachi.rbac.aop.AuthAspect@588c635b [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:48) - 目标类(需要被代理的类): class cn.bithachi.rbac.controller.TestController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:49) - 切面对象列表: [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:51) - cn.bithachi.rbac.aop.LogAspect@7735d6db [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:51) - cn.bithachi.rbac.aop.AuthAspect@5ad11861 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:48) - 目标类(需要被代理的类): class cn.bithachi.rbac.service.impl.RoleServiceImpl [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:49) - 切面对象列表: [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:51) - cn.bithachi.framework.proxy.TransactionProxy@70bfcec [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:48) - 目标类(需要被代理的类): class cn.bithachi.rbac.controller.SystemController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:49) - 切面对象列表: [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:51) - cn.bithachi.rbac.aop.LogAspect@3c26c1ed [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:51) - cn.bithachi.rbac.aop.AuthAspect@657c4bbc [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:48) - 目标类(需要被代理的类): class cn.bithachi.rbac.service.impl.PermissionServiceImpl [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:49) - 切面对象列表: [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:51) - cn.bithachi.framework.proxy.TransactionProxy@37bc5562 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:48) - 目标类(需要被代理的类): class cn.bithachi.rbac.service.impl.SystemServiceImpl [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:49) - 切面对象列表: [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:51) - cn.bithachi.framework.proxy.TransactionProxy@6f8823e5 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:48) - 目标类(需要被代理的类): class cn.bithachi.rbac.service.impl.LogServiceImpl [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:49) - 切面对象列表: [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:51) - cn.bithachi.framework.proxy.TransactionProxy@65abbe50 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:48) - 目标类(需要被代理的类): class cn.bithachi.rbac.controller.PermissionController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:49) - 切面对象列表: [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:51) - cn.bithachi.rbac.aop.LogAspect@628d28f2 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:51) - cn.bithachi.rbac.aop.AuthAspect@374f6684 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:48) - 目标类(需要被代理的类): class cn.bithachi.rbac.controller.UserController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:49) - 切面对象列表: [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:51) - cn.bithachi.rbac.aop.LogAspect@1976fc83 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:51) - cn.bithachi.rbac.aop.AuthAspect@219788c3 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:48) - 目标类(需要被代理的类): class cn.bithachi.rbac.controller.RoleController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:49) - 切面对象列表: [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:51) - cn.bithachi.rbac.aop.LogAspect@2ad6febb [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:51) - cn.bithachi.rbac.aop.AuthAspect@66e1d623 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:48) - 目标类(需要被代理的类): class cn.bithachi.rbac.service.impl.UserServiceImpl [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:49) - 切面对象列表: [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:51) - cn.bithachi.framework.proxy.TransactionProxy@485dbc98 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:56) - *************** 目标类(需要被代理的类) -- 代理链对象的映射 ********************* [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:61) - 目标类(需要被代理的类): class cn.bithachi.rbac.controller.LogController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:65) - 目标类的代理链对象: cn.bithachi.rbac.controller.LogController$$EnhancerByCGLIB$$7d9fa3a@7056ea64 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:61) - 目标类(需要被代理的类): class cn.bithachi.rbac.controller.TestController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:65) - 目标类的代理链对象: cn.bithachi.rbac.controller.TestController$$EnhancerByCGLIB$$502a1236@47625536 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:61) - 目标类(需要被代理的类): class cn.bithachi.rbac.service.impl.RoleServiceImpl [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:65) - 目标类的代理链对象: cn.bithachi.rbac.service.impl.RoleServiceImpl$$EnhancerByCGLIB$$820204e@488244e5 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:61) - 目标类(需要被代理的类): class cn.bithachi.rbac.controller.SystemController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:65) - 目标类的代理链对象: cn.bithachi.rbac.controller.SystemController$$EnhancerByCGLIB$$57a90cd5@1f5664e8 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:61) - 目标类(需要被代理的类): class cn.bithachi.rbac.service.impl.PermissionServiceImpl [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:65) - 目标类的代理链对象: cn.bithachi.rbac.service.impl.PermissionServiceImpl$$EnhancerByCGLIB$$269d02bb@4eb7ab23 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:61) - 目标类(需要被代理的类): class cn.bithachi.rbac.service.impl.SystemServiceImpl [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:65) - 目标类的代理链对象: cn.bithachi.rbac.service.impl.SystemServiceImpl$$EnhancerByCGLIB$$6bb019b@6a31ffd5 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:61) - 目标类(需要被代理的类): class cn.bithachi.rbac.service.impl.LogServiceImpl [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:65) - 目标类的代理链对象: cn.bithachi.rbac.service.impl.LogServiceImpl$$EnhancerByCGLIB$$3d9544f8@6d6b78fd [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:61) - 目标类(需要被代理的类): class cn.bithachi.rbac.controller.PermissionController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:65) - 目标类的代理链对象: cn.bithachi.rbac.controller.PermissionController$$EnhancerByCGLIB$$c425035@11944b6b [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:61) - 目标类(需要被代理的类): class cn.bithachi.rbac.controller.UserController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:65) - 目标类的代理链对象: cn.bithachi.rbac.controller.UserController$$EnhancerByCGLIB$$52f77049@2026237a [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:61) - 目标类(需要被代理的类): class cn.bithachi.rbac.controller.RoleController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:65) - 目标类的代理链对象: cn.bithachi.rbac.controller.RoleController$$EnhancerByCGLIB$$a6fabf82@46c86477 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:61) - 目标类(需要被代理的类): class cn.bithachi.rbac.service.impl.UserServiceImpl [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.AopHelper:65) - 目标类的代理链对象: cn.bithachi.rbac.service.impl.UserServiceImpl$$EnhancerByCGLIB$$dbb98867@397c291 ``` #### (4)@Autowired 依赖注入 ```java [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.IocHelper:32) - ********************* 注入所有的 @Autowired ********************* [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.IocHelper:63) - beanInstance: cn.bithachi.rbac.controller.LogController$$EnhancerByCGLIB$$7d9fa3a@7056ea64 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.IocHelper:64) - beanField: private cn.bithachi.rbac.service.LogService cn.bithachi.rbac.controller.LogController.logService [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.IocHelper:65) - beanFieldInstance: cn.bithachi.rbac.service.impl.LogServiceImpl$$EnhancerByCGLIB$$3d9544f8@6d6b78fd [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.IocHelper:63) - beanInstance: cn.bithachi.rbac.service.impl.RoleServiceImpl$$EnhancerByCGLIB$$820204e@488244e5 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.IocHelper:64) - beanField: private cn.bithachi.rbac.dao.RoleDao cn.bithachi.rbac.service.impl.RoleServiceImpl.roleDao [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.IocHelper:65) - beanFieldInstance: cn.bithachi.rbac.dao.impl.RoleDaoImpl@6880fd23 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.IocHelper:63) - beanInstance: cn.bithachi.rbac.service.impl.PermissionServiceImpl$$EnhancerByCGLIB$$269d02bb@4eb7ab23 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.IocHelper:64) - beanField: private cn.bithachi.rbac.dao.PermissionDao cn.bithachi.rbac.service.impl.PermissionServiceImpl.permissionDao [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.IocHelper:65) - beanFieldInstance: cn.bithachi.rbac.dao.impl.PermissionDaoImpl@530e6f49 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.IocHelper:63) - beanInstance: cn.bithachi.rbac.controller.SystemController$$EnhancerByCGLIB$$57a90cd5@1f5664e8 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.IocHelper:64) - beanField: cn.bithachi.rbac.service.SystemService cn.bithachi.rbac.controller.SystemController.systemService [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.IocHelper:65) - beanFieldInstance: cn.bithachi.rbac.service.impl.SystemServiceImpl$$EnhancerByCGLIB$$6bb019b@6a31ffd5 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.IocHelper:63) - beanInstance: cn.bithachi.rbac.controller.UserController$$EnhancerByCGLIB$$52f77049@2026237a [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.IocHelper:64) - beanField: private cn.bithachi.rbac.service.UserService cn.bithachi.rbac.controller.UserController.userService [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.IocHelper:65) - beanFieldInstance: cn.bithachi.rbac.service.impl.UserServiceImpl$$EnhancerByCGLIB$$dbb98867@397c291 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.IocHelper:63) - beanInstance: cn.bithachi.rbac.controller.UserController$$EnhancerByCGLIB$$52f77049@2026237a [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.IocHelper:64) - beanField: private cn.bithachi.rbac.service.RoleService cn.bithachi.rbac.controller.UserController.roleService [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.IocHelper:65) - beanFieldInstance: cn.bithachi.rbac.service.impl.RoleServiceImpl$$EnhancerByCGLIB$$820204e@488244e5 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.IocHelper:63) - beanInstance: cn.bithachi.rbac.service.impl.SystemServiceImpl$$EnhancerByCGLIB$$6bb019b@6a31ffd5 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.IocHelper:64) - beanField: private cn.bithachi.rbac.dao.UserDao cn.bithachi.rbac.service.impl.SystemServiceImpl.userDao [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.IocHelper:65) - beanFieldInstance: cn.bithachi.rbac.dao.impl.UserDaoImpl@29a02118 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.IocHelper:63) - beanInstance: cn.bithachi.rbac.service.impl.LogServiceImpl$$EnhancerByCGLIB$$3d9544f8@6d6b78fd [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.IocHelper:64) - beanField: private cn.bithachi.rbac.dao.LogDao cn.bithachi.rbac.service.impl.LogServiceImpl.logDao [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.IocHelper:65) - beanFieldInstance: cn.bithachi.rbac.dao.impl.LogDaoImpl@2cc3d282 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.IocHelper:63) - beanInstance: cn.bithachi.rbac.controller.PermissionController$$EnhancerByCGLIB$$c425035@11944b6b [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.IocHelper:64) - beanField: cn.bithachi.rbac.service.PermissionService cn.bithachi.rbac.controller.PermissionController.permissionService [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.IocHelper:65) - beanFieldInstance: cn.bithachi.rbac.service.impl.PermissionServiceImpl$$EnhancerByCGLIB$$269d02bb@4eb7ab23 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.IocHelper:63) - beanInstance: cn.bithachi.rbac.controller.RoleController$$EnhancerByCGLIB$$a6fabf82@46c86477 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.IocHelper:64) - beanField: private cn.bithachi.rbac.service.RoleService cn.bithachi.rbac.controller.RoleController.roleService [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.IocHelper:65) - beanFieldInstance: cn.bithachi.rbac.service.impl.RoleServiceImpl$$EnhancerByCGLIB$$820204e@488244e5 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.IocHelper:63) - beanInstance: cn.bithachi.rbac.service.impl.UserServiceImpl$$EnhancerByCGLIB$$dbb98867@397c291 [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.IocHelper:64) - beanField: private cn.bithachi.rbac.dao.UserDao cn.bithachi.rbac.service.impl.UserServiceImpl.userDao [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.IocHelper:65) - beanFieldInstance: cn.bithachi.rbac.dao.impl.UserDaoImpl@29a02118 ``` #### (5)Request 和 Handler 的映射 ```java [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:31) - ****************** 所有的 Controller 类 ********************* [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:35) - class cn.bithachi.rbac.controller.LogController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:35) - class cn.bithachi.rbac.controller.TestController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:35) - class cn.bithachi.rbac.controller.SystemController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:35) - class cn.bithachi.rbac.controller.PermissionController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:35) - class cn.bithachi.rbac.controller.UserController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:35) - class cn.bithachi.rbac.controller.RoleController [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:73) - Request 和 Handler 对应的的映射: [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:74) - Request: requestMethod + requestPath [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:75) - Handler: controllerClass + controllerMethod ********************************* [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:78) - Request: Request{requestMethod='POST', requestPath='/role/add'} [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:79) - Handler: cn.bithachi.rbac.controller.RoleController ---> add() [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:78) - Request: Request{requestMethod='GET', requestPath='/permission/edit'} [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:79) - Handler: cn.bithachi.rbac.controller.PermissionController ---> editView() [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:78) - Request: Request{requestMethod='POST', requestPath='/role/edit'} [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:79) - Handler: cn.bithachi.rbac.controller.RoleController ---> edit() [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:78) - Request: Request{requestMethod='GET', requestPath='/log/list'} [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:79) - Handler: cn.bithachi.rbac.controller.LogController ---> logView() [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:78) - Request: Request{requestMethod='GET', requestPath='/permission/add'} [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:79) - Handler: cn.bithachi.rbac.controller.PermissionController ---> add() [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:78) - Request: Request{requestMethod='POST', requestPath='/permission/add'} [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:79) - Handler: cn.bithachi.rbac.controller.PermissionController ---> add() [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:78) - Request: Request{requestMethod='GET', requestPath='/login'} [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:79) - Handler: cn.bithachi.rbac.controller.SystemController ---> login() [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:78) - Request: Request{requestMethod='GET', requestPath='/index'} [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:79) - Handler: cn.bithachi.rbac.controller.SystemController ---> index() [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:78) - Request: Request{requestMethod='GET', requestPath='/exit'} [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:79) - Handler: cn.bithachi.rbac.controller.SystemController ---> exit() [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:78) - Request: Request{requestMethod='POST', requestPath='/user/delete'} [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:79) - Handler: cn.bithachi.rbac.controller.UserController ---> delete() [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:78) - Request: Request{requestMethod='POST', requestPath='/log/list'} [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:79) - Handler: cn.bithachi.rbac.controller.LogController ---> log() [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:78) - Request: Request{requestMethod='GET', requestPath='/user/auth'} [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:79) - Handler: cn.bithachi.rbac.controller.UserController ---> authView() [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:78) - Request: Request{requestMethod='GET', requestPath='/welcome'} [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:79) - Handler: cn.bithachi.rbac.controller.SystemController ---> welcome() [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:78) - Request: Request{requestMethod='POST', requestPath='/user/auth'} [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:79) - Handler: cn.bithachi.rbac.controller.UserController ---> auth() [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:78) - Request: Request{requestMethod='POST', requestPath='/user/add'} [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:79) - Handler: cn.bithachi.rbac.controller.UserController ---> add() [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:78) - Request: Request{requestMethod='GET', requestPath='/user/add'} [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:79) - Handler: cn.bithachi.rbac.controller.UserController ---> add() [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:78) - Request: Request{requestMethod='POST', requestPath='/user/list'} [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:79) - Handler: cn.bithachi.rbac.controller.UserController ---> list() [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:78) - Request: Request{requestMethod='GET', requestPath='/permission/listdata'} [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:79) - Handler: cn.bithachi.rbac.controller.PermissionController ---> listdata() [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:78) - Request: Request{requestMethod='POST', requestPath='/permission/delete'} [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:79) - Handler: cn.bithachi.rbac.controller.PermissionController ---> delete() [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:78) - Request: Request{requestMethod='GET', requestPath='/user/list'} [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:79) - Handler: cn.bithachi.rbac.controller.UserController ---> list() [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:78) - Request: Request{requestMethod='POST', requestPath='/role/list'} [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:79) - Handler: cn.bithachi.rbac.controller.RoleController ---> list() [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:78) - Request: Request{requestMethod='GET', requestPath='/role/list'} [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:79) - Handler: cn.bithachi.rbac.controller.RoleController ---> listView() [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:78) - Request: Request{requestMethod='POST', requestPath='/user/edit'} [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:79) - Handler: cn.bithachi.rbac.controller.UserController ---> edit() [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:78) - Request: Request{requestMethod='POST', requestPath='/login'} [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:79) - Handler: cn.bithachi.rbac.controller.SystemController ---> login() [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:78) - Request: Request{requestMethod='POST', requestPath='/permission/edit'} [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:79) - Handler: cn.bithachi.rbac.controller.PermissionController ---> edit() [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:78) - Request: Request{requestMethod='GET', requestPath='/role/add'} [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:79) - Handler: cn.bithachi.rbac.controller.RoleController ---> addView() [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:78) - Request: Request{requestMethod='GET', requestPath='/permission/list'} [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:79) - Handler: cn.bithachi.rbac.controller.PermissionController ---> list() [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:78) - Request: Request{requestMethod='GET', requestPath='/user/edit'} [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:79) - Handler: cn.bithachi.rbac.controller.UserController ---> editView() [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:78) - Request: Request{requestMethod='GET', requestPath='/role/edit'} [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:79) - Handler: cn.bithachi.rbac.controller.RoleController ---> editView() [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:78) - Request: Request{requestMethod='POST', requestPath='/role/delete'} [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.helper.ControllerHelper:79) - Handler: cn.bithachi.rbac.controller.RoleController ---> delete() [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.InitLoader:35) - ****************** init() end ****************** [RMI TCP Connection(3)-127.0.0.1] [INFO ] (cn.bithachi.framework.DispatcherServlet:48) - ************************* servlet init() end ************************** ``` ## 6.2 框架如何处理请求 ### 6.2.1 Tomcat 如何处理请求 首先我们先从全局上看一下Tomcat是如何处理传过来的请求的。当请求到达时,Tomcat 会把请求转发给内部的 Servlet容器 , 内部的 Servlet容器 传递给具体的 Servlet 去执行(这里我只写了一个 DispatcherServlet , 因为在本框架中,只有这一个 Servlet , 它负责接收所有前端请求并返回响应信息给前端),Servlet 执行完毕后,把响应信息给 Tomcat , Tomcat 再包装一下为HTTP响应信息, 返回给前端。 ![](http://image.bithachi.cn/20210827003447.png) ### 6.2.2 DispatcherServlet 处理请求的流程图 在简单复习了 Tomcat 如何处理前端传过来的请求后,接下来看看在框架中, DispatcherServlet 是如何处理前端的请求的。 DispatcherServlet 处理请求的流程图如下所示: ![DispatcherServlet如何处理前端请求](http://image.bithachi.cn/202108271637548.png) ### 6.2.3 服务端处理每一个请求的的日志 ```cmd [http-nio-8082-exec-5] [INFO ] (cn.bithachi.framework.DispatcherServlet:55) - ************************* service start *************************** [http-nio-8082-exec-5] [INFO ] (cn.bithachi.framework.DispatcherServlet:58) - 是否已经向前端发出response响应: : false [http-nio-8082-exec-5] [INFO ] (cn.bithachi.framework.DispatcherServlet:66) - requestMethod: GET [http-nio-8082-exec-5] [INFO ] (cn.bithachi.framework.DispatcherServlet:67) - requestPath: /user/edit [http-nio-8082-exec-5] [INFO ] (cn.bithachi.framework.DispatcherServlet:140) - not file ! [http-nio-8082-exec-5] [INFO ] (cn.bithachi.framework.DispatcherServlet:148) - param: Param{formParamList=[FormParam{fieldName='id', fieldValue=27}], fileParamList=null} [http-nio-8082-exec-5] [INFO ] (cn.bithachi.framework.DispatcherServlet:149) - param is Empty: false [http-nio-8082-exec-5] [INFO ] (cn.bithachi.rbac.aop.LogAspect:74) - 服务器主机名: localhost [http-nio-8082-exec-5] [INFO ] (cn.bithachi.rbac.aop.LogAspect:75) - 服务器端口号: 8082 [http-nio-8082-exec-5] [INFO ] (cn.bithachi.rbac.aop.LogAspect:76) - 客户端请求的协议名和版本: HTTP/1.1 [http-nio-8082-exec-5] [INFO ] (cn.bithachi.rbac.aop.LogAspect:77) - 客户端请求的http方法: GET [http-nio-8082-exec-5] [INFO ] (cn.bithachi.rbac.aop.LogAspect:78) - 客户端请求的资源URI: /mvc/user/edit [http-nio-8082-exec-5] [INFO ] (cn.bithachi.rbac.aop.LogAspect:79) - 请求的控制器类.方法: class cn.bithachi.rbac.controller.UserController.editView(xxx) [http-nio-8082-exec-5] [INFO ] (cn.bithachi.rbac.aop.LogAspect:80) - 客户端请求参数: {"id":["27"]} [http-nio-8082-exec-5] [INFO ] (cn.bithachi.rbac.aop.LogAspect:81) - 客户端URL参数: id=27 [http-nio-8082-exec-5] [INFO ] (cn.bithachi.rbac.aop.LogAspect:82) - 客户端主机名: 0:0:0:0:0:0:0:1 [http-nio-8082-exec-5] [INFO ] (cn.bithachi.rbac.aop.LogAspect:83) - 客户端IP地址: 0:0:0:0:0:0:0:1 [http-nio-8082-exec-5] [INFO ] (cn.bithachi.rbac.aop.LogAspect:84) - 客户端端口: 58167 [http-nio-8082-exec-5] [DEBUG] (druid.sql.Connection:129) - {conn-10002} pool-connect [http-nio-8082-exec-5] [DEBUG] (druid.sql.Statement:134) - {conn-10002, pstmt-20029} created. INSERT INTO log (username,ip,port,http_method,protocol,uri,controller_method,params,result) VALUES (?,?,?,?,?,?,?,?,?) [http-nio-8082-exec-5] [DEBUG] (druid.sql.Statement:134) - {conn-10002, pstmt-20029} Parameters : [bithachi, 0:0:0:0:0:0:0:1, 58167, GET, HTTP/1.1, /mvc/user/edit, class cn.bithachi.rbac.controller.UserController.editView(xxx), {"id":["27"]}, null] [http-nio-8082-exec-5] [DEBUG] (druid.sql.Statement:134) - {conn-10002, pstmt-20029} Types : [VARCHAR, VARCHAR, VARCHAR, VARCHAR, VARCHAR, VARCHAR, VARCHAR, VARCHAR, VARCHAR] [http-nio-8082-exec-5] [DEBUG] (druid.sql.Statement:134) - {conn-10002, pstmt-20029} update executed. effort 1. 30.0822 millis. INSERT INTO log (username,ip,port,http_method,protocol,uri,controller_method,params,result) VALUES (?,?,?,?,?,?,?,?,?) [http-nio-8082-exec-5] [DEBUG] (druid.sql.Statement:134) - {conn-10002, pstmt-20029} closed [http-nio-8082-exec-5] [DEBUG] (druid.sql.Connection:129) - {conn-10002} pool-recycle [http-nio-8082-exec-5] [DEBUG] (druid.sql.Connection:129) - {conn-10002} pool-connect [http-nio-8082-exec-5] [DEBUG] (druid.sql.Statement:134) - {conn-10002, pstmt-20030} created. SELECT LAST_INSERT_ID() [http-nio-8082-exec-5] [DEBUG] (druid.sql.Statement:134) - {conn-10002, pstmt-20030} Parameters : [] [http-nio-8082-exec-5] [DEBUG] (druid.sql.Statement:134) - {conn-10002, pstmt-20030} Types : [] [http-nio-8082-exec-5] [DEBUG] (druid.sql.Statement:134) - {conn-10002, pstmt-20030, rs-50015} query executed. 25.4041 millis. SELECT LAST_INSERT_ID() [http-nio-8082-exec-5] [DEBUG] (druid.sql.ResultSet:139) - {conn-10002, pstmt-20030, rs-50015} open [http-nio-8082-exec-5] [DEBUG] (druid.sql.ResultSet:139) - {conn-10002, pstmt-20030, rs-50015} Header: [LAST_INSERT_ID()] [http-nio-8082-exec-5] [DEBUG] (druid.sql.ResultSet:139) - {conn-10002, pstmt-20030, rs-50015} Result: [85] [http-nio-8082-exec-5] [DEBUG] (druid.sql.ResultSet:139) - {conn-10002, pstmt-20030, rs-50015} closed [http-nio-8082-exec-5] [DEBUG] (druid.sql.Statement:134) - {conn-10002, pstmt-20030} closed [http-nio-8082-exec-5] [DEBUG] (druid.sql.Connection:129) - {conn-10002} pool-recycle [http-nio-8082-exec-5] [INFO ] (cn.bithachi.rbac.aop.AuthAspect:59) - 是否已经向前端发出response响应: : false [http-nio-8082-exec-5] [DEBUG] (druid.sql.Connection:129) - {conn-10002} pool-connect [http-nio-8082-exec-5] [DEBUG] (druid.sql.Statement:134) - {conn-10002, pstmt-20031} created. SELECT uid,username,name,phone,email FROM user WHERE uid=? [http-nio-8082-exec-5] [DEBUG] (druid.sql.Statement:134) - {conn-10002, pstmt-20031} Parameters : [27] [http-nio-8082-exec-5] [DEBUG] (druid.sql.Statement:134) - {conn-10002, pstmt-20031} Types : [BIGINT] [http-nio-8082-exec-5] [DEBUG] (druid.sql.Statement:134) - {conn-10002, pstmt-20031, rs-50016} query executed. 25.8414 millis. SELECT uid,username,name,phone,email FROM user WHERE uid=? [http-nio-8082-exec-5] [DEBUG] (druid.sql.ResultSet:139) - {conn-10002, pstmt-20031, rs-50016} open [http-nio-8082-exec-5] [DEBUG] (druid.sql.ResultSet:139) - {conn-10002, pstmt-20031, rs-50016} Header: [uid, username, name, phone, email] [http-nio-8082-exec-5] [DEBUG] (druid.sql.ResultSet:139) - {conn-10002, pstmt-20031, rs-50016} Result: [27, bithachi, 老王, 176743546, asf26878g@163.com] [http-nio-8082-exec-5] [DEBUG] (druid.sql.ResultSet:139) - {conn-10002, pstmt-20031, rs-50016} closed [http-nio-8082-exec-5] [DEBUG] (druid.sql.Statement:134) - {conn-10002, pstmt-20031} closed [http-nio-8082-exec-5] [DEBUG] (druid.sql.Connection:129) - {conn-10002} pool-recycle [http-nio-8082-exec-5] [INFO ] (cn.bithachi.rbac.aop.LogAspect:134) - 方法执行后, 返回json格式化结果: {"model":{},"path":"user/edit.jsp"} [http-nio-8082-exec-5] [DEBUG] (druid.sql.Connection:129) - {conn-10002} pool-connect [http-nio-8082-exec-5] [DEBUG] (druid.sql.Statement:134) - {conn-10002, pstmt-20032} created. UPDATE log SET result=? WHERE id=? [http-nio-8082-exec-5] [DEBUG] (druid.sql.Statement:134) - {conn-10002, pstmt-20032} Parameters : [{"model":{},"path":"user/edit.jsp"}, 85] [http-nio-8082-exec-5] [DEBUG] (druid.sql.Statement:134) - {conn-10002, pstmt-20032} Types : [VARCHAR, BIGINT] [http-nio-8082-exec-5] [DEBUG] (druid.sql.Statement:134) - {conn-10002, pstmt-20032} update executed. effort 1. 26.2668 millis. UPDATE log SET result=? WHERE id=? [http-nio-8082-exec-5] [DEBUG] (druid.sql.Statement:134) - {conn-10002, pstmt-20032} closed [http-nio-8082-exec-5] [DEBUG] (druid.sql.Connection:129) - {conn-10002} pool-recycle [http-nio-8082-exec-5] [INFO ] (cn.bithachi.framework.DispatcherServlet:175) - 是否已经向前端发出response响应: : false [http-nio-8082-exec-5] [INFO ] (cn.bithachi.framework.DispatcherServlet:183) - 是否已经向前端发出response响应: : false [http-nio-8082-exec-5] [INFO ] (cn.bithachi.framework.DispatcherServlet:189) - 请求转发: /WEB-INF/user/edit.jsp [http-nio-8082-exec-5] [INFO ] (cn.bithachi.framework.DispatcherServlet:80) - *************************** service end **************************** ``` ## 6.3 Aop 相关 ### 6.3.1 Aop是如何实现的? 框架中最难的就是AOP的实现了,AOP核心就是动态代理,笔者这里使用 [CGLIB](https://www.runoob.com/w3cnote/cglibcode-generation-library-intro.html) 做动态代理并配合 [模板模式](https://www.yuque.com/bithachi/study/eg2il8) 和 [责任链模式](http://c.biancheng.net/view/1383.html)来实现AOP。 在AopHelp初始化的过程中,为目标类创建N个代理对象的列表,然后根据N个代理对象的列表,使用自定义的 CGLIB 代理工厂类 ProxyFactory 的 createProxy 方法生成目标类的代理链对象,形成一个代理链 ProxyChain 对象。 当调用目标类对象的方法时,CGLIB会回调 MethodInterceptor 接口的方法 intercept(xxx) 进行拦截, 创建一个 ProxyChain 对象, 并调用该对象的 doProxyChain() 方法,调用 doProxyChain() 方法时: - 如果是控制类的方法调用,会首先递归的执行代理链中每一个AOP代理对象的增强逻辑, 然后根据情况(登录和权限验证),最后再执行目标方法,然后回溯,最终返回执行结果。 - 如果是@Service服务类标注了@Transactional的方法调用,会在方法执行前开启事务,方法执行完后提交事务,如果抛出异常,则会回滚事务,从而完成注解事务的支持。DatabaseHelper 内部使用 ThreadLocal 存储数据库连接,因为ThreadLocal 存储的值是线程隔离的,每一个请求线程都有一个属于自己的数据库连接,而且是全局的,在Dao层中进行数据库操作,操作的始终是一个数据库连接,所以能保证多个数据库操作,比如增加、删除和更新可以以一个事务进行提交。 ### 6.3.2 AOP顶层处理流程图 ![Aop处理流程图](http://image.bithachi.cn/202108292150019.png) ### 6.3.3 一个案例解析控制类方法的Aop处理流程 当在DispatcherServlet调用控制器类的方法 ReflectionUtil.invokeMethod(xxx) 时,我们假设有两个切面代理对象:AuthAspect和LogAspect。AOP处理流程如下图所示: ![Aop案例解析](http://image.bithachi.cn/202108292113782.png) ### 6.3.4 AOP 核心代码 相关的AOP代码实现如下所示: #### (1)ProxyFactory ```java package cn.bithachi.framework.proxy; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; import java.util.List; /** * 代理工厂,负责创建代理对象 * 当调用 ProxyFactory.createProxy(xxx) 方法来创建一个代理对象后, * 每次执行代理方法时都会调用 intercept() 方法, 从而创建一个 ProxyChain 对象, 并调用该对象的 doProxyChain() 方法. * 调用doProxyChain()方法时会首先递归的执行代理链中每一个AOP代理对象的增强逻辑, 然后根据情况(登录和权限验证),最后再执行目标方法 */ public class ProxyFactory { /** * 输入一个目标类和一组Proxy接口实现类(切面对象), 返回一个代理对象 * * @param targetClass 要被代理的目标类 * @param proxyList 目标类的所有切面代理对象列表 * @param 目标类的代理链对象 * @return */ @SuppressWarnings("unchecked") public static T createProxy(final Class targetClass, final List proxyList) { class MyMethodInterceptor implements MethodInterceptor{ /** * 每次调用目标类的方法都会被方法拦截器intercept()拦截 * 在调用目标方法时,CGLib会回调MethodInterceptor接口的intercept方法拦截,来实现你自己的代理逻辑,类似于JDK中的InvocationHandler接口。 * 每次调用目标方法时都会先创建一个 ProxyChain 对象, 然后调用该对象的 doProxyChain() 方法(一系列的代理业务逻辑), * 方法执行完后,intercept()再将结果返回出去。 * * @param thisObject 增强对象,this( new MethodInterceptor(){xxx})本身 * @param targetMethod 目标类方法 * @param methodParams 目标类方法参数 * @param methodProxy 方法代理,用于调用 super(非拦截方法);可以根据需要多次调用 * @return 方法执行后的结果 * @throws Throwable */ @Override public Object intercept(Object thisObject, Method targetMethod, Object[] methodParams, MethodProxy methodProxy) throws Throwable { return new ProxyChain(targetClass, thisObject, targetMethod, methodProxy, methodParams, proxyList).doProxyChain(); } } return (T) Enhancer.create(targetClass, new MyMethodInterceptor()); } } ``` #### (2)ProxyChain ```java package cn.bithachi.framework.proxy; import net.sf.cglib.proxy.MethodProxy; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; /** * 代理链 */ public class ProxyChain { private static final Logger LOGGER = LoggerFactory.getLogger(ProxyChain.class); /** * 目标类 */ private final Class targetClass; /** * 目标对象 */ private final Object targetObject; /** * 目标方法 */ private final Method targetMethod; /** * 目标方法的代理 net.sf.cglib.proxy.MethodProxy */ private final MethodProxy methodProxy; /** * 目标方法参数 */ private final Object[] methodParams; /** * 切面类代理对象列表 */ private List proxyList = new ArrayList<>(); /** * 代理索引,用于执行n个切面类代理对象的业务逻辑方法 doProxy(xxx) */ private int proxyIndex = 0; /** * * @param targetClass 目标类 * @param targetObject 目标对象 * @param targetMethod 目标方法 * @param methodProxy 目标方法的代理 net.sf.cglib.proxy.MethodProxy * @param methodParams 目标方法参数 * @param proxyList 切面类代理对象列表 */ public ProxyChain(Class targetClass, Object targetObject, Method targetMethod, MethodProxy methodProxy, Object[] methodParams, List proxyList) { this.targetClass = targetClass; this.targetObject = targetObject; this.targetMethod = targetMethod; this.methodProxy = methodProxy; this.methodParams = methodParams; this.proxyList = proxyList; } /** * 递归的执行代理链中每一个AOP切面类代理对象的增强逻辑, 然后根据情况(登录和权限验证),最后再执行目标方法。 * */ public Object doProxyChain() throws Throwable { // 方法执行结果 Object methodResult; if (proxyIndex < proxyList.size()) { //执行代理链中所有代理对象的强制增强方法,进行一些鉴权,日志,事务等非业务的逻辑 methodResult = proxyList.get(proxyIndex++).doProxy(this); } else { // 如果AOP代理逻辑都顺利执行,则最终执行目标类对象的方法 methodResult = methodProxy.invokeSuper(targetObject, methodParams); } return methodResult; } public Object[] getMethodParams() { return methodParams; } public Class getTargetClass() { return targetClass; } public Method getTargetMethod() { return targetMethod; } } ``` #### (3)Proxy ```java package cn.bithachi.framework.proxy; /** * 代理接口 */ public interface Proxy { /** * 执行链式代理 * 所谓链式代理, 就是说, 可将多个代理通过一条链子串起来, 一个个地去执行, 执行顺序取决于添加到链上的先后顺序 */ Object doProxy(ProxyChain proxyChain) throws Throwable; } ``` #### (4)AspectProxy ```java package cn.bithachi.framework.proxy; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.lang.reflect.Method; /** * 默认的切面代理 抽象类 */ public abstract class AspectProxy implements Proxy { private static final Logger LOGGER = LoggerFactory.getLogger(AspectProxy.class); @Override public final Object doProxy(ProxyChain proxyChain) throws Throwable { Object result = null; Class cls = proxyChain.getTargetClass(); Method method = proxyChain.getTargetMethod(); Object[] params = proxyChain.getMethodParams(); // 对 toString 和 hashcode 方法进行放行,不进行增强! 因为日志打印,所以要做这一步处理 if (method.getName().equals("toString") || method.getName().equals("hashCode")) { // LOGGER.info("toString ------ hashCode"); result = proxyChain.doProxyChain(); return result; } // 开始增强 begin(); try { // 切入点判断 if (intercept(method, params)) { // 前置增强 boolean isContinue = before(method, params); // 如果前置增强通过,就继续执行,否则直接返回结果,不再执行目标对象方法,也不再执行本切面对象的后续增强逻辑 if (isContinue) { result = proxyChain.doProxyChain(); } else { return null; } // 后置增强 after(method, params,result); } else { result = proxyChain.doProxyChain(); } } catch (Exception e) { LOGGER.error("proxy failure", e); error(method, params, e); throw e; } finally { // 最终增强 end(); } return result; } /** * 开始增强 */ public void begin() { // LOGGER.info("默认的开始增强!"); } /** * 切入点判断 */ public boolean intercept(Method method, Object[] params) throws Throwable { return true; } /** * 前置增强 */ public boolean before(Method method, Object[] params) throws Throwable { // LOGGER.info("默认的前置增强!"); return true; } /** * 后置增强 */ public void after(Method method, Object[] params, Object result) throws Throwable { // LOGGER.info("默认的后置增强!"); } /** * 异常增强 */ public void error(Method method, Object[] params, Throwable e) { // LOGGER.info("默认的异常增强!"); } /** * 最终增强 */ public void end() { // LOGGER.info("默认的最终增强!"); } } ``` ### (5)TransactionProxy ```java /** * 框架默认对添加了 @Transactional 的 service 方法提供事务代理 */ public class TransactionProxy implements Proxy { private static final Logger LOGGER = LoggerFactory.getLogger(TransactionProxy.class); @Override public Object doProxy(ProxyChain thisOroxyChain) throws Throwable { Object result; Method method = thisOroxyChain.getTargetMethod(); // 加了@Transactional注解的方法要做事务处理 if (method.isAnnotationPresent(Transactional.class)) { try { DatabaseHelper.beginTransaction(); LOGGER.debug("begin transaction"); result = thisOroxyChain.doProxyChain(); DatabaseHelper.commitTransaction(); LOGGER.debug("commit transaction"); } catch (Exception e) { DatabaseHelper.rollbackTransaction(); LOGGER.debug("rollback transaction"); throw e; } } else { result = thisOroxyChain.doProxyChain(); } return result; } } ``` ### 6.3.5 AopHelper 切面助手类初始化流程图 AopHelper 利用自定义的 CGLIB 代理工厂生成目标类的代理链对象,并重新设置Bean容器的初始化流程如下图所示: ![AopHelp初始化流程图](http://image.bithachi.cn/202108281128272.png) # 7. 数据库 ![image-20210829222238591](http://image.bithachi.cn/202108292222768.png) # 8. 学习资料 - [ Smart Framework](https://gitee.com/huangyong/smart-framework) - [架构探险――从零开始写Java Web框架](https://book.douban.com/subject/26593466/) - [CSDN-椰子Tyshawn手写Spring框架](https://blog.csdn.net/litianxiang_kaola/category_9284463.html) - [阿里巴巴开发手册](https://developer.aliyun.com/topic/java20) - [Servlet多线程安全问题](https://www.yuque.com/bithachi/study/ab3qgg) - [自定义jsp标签实现按钮权限控制](https://blog.csdn.net/weixin_42184707/article/details/80318171) - [RBAC权限系统分析、设计与实现](https://www.yuque.com/bithachi/study/vt075g) - [树形表格插件](https://gitee.com/whvse/treetable-lay) - 递归实现菜单树: - https://blog.csdn.net/weter_drop/article/details/103601591 - https://blog.csdn.net/LDY1016/article/details/85784001 - https://blog.csdn.net/frankcheng5143/article/details/52958486 - [PO、VO、DTO、BO、POJO、BO/DO、DAO设计](https://www.jianshu.com/p/d9cfd1a85068) - RBAC 参考的一些开源项目: - https://github.com/paifeng/my-rbac - https://github.com/misterchaos/HotelSystem - https://github.com/czwbig/Tmall_JavaEE - [druid servlet 配置 StatViewServlet配置](https://blog.csdn.net/u013160024/article/details/52881020) - [druid 参数配置详解](https://www.cnblogs.com/halberd-lee/p/11304790.html) - [zTree -- jQuery 树插件](http://www.treejs.cn/v3/main.php#_zTreeInfo) # 9. 联系方式 - 邮箱:bithachi@163.com - 博客:[BitHachi - 开源・分享・互助・终身学习](http://blog.bithachi.cn/) - 笔记:[BitHachi - 武功秘籍](http://note.bithachi.cn/)