初学源码之——银行案例手写IOC和AOP

JavaEE实战:影院系统项目源码解析 本文还有配套的精品资源,点击获取 简介:本课程设计提供了一个影院在线预订系统的完整JavaEE项目源码,帮助初学者深入理解并掌握企业级Java开发的核心技术。通过介绍项目中所用的SSM(Spring、Spring MVC、MyBatis)框架、数据库设计、前端技术、安全机制等关键知识点,帮助学生构建一个功能完善的影院预订系统,并掌握如何进行单元测试与集成测试,确保代码质量与... 阅读详情

手写实现lOC和AOP

上一部分我们理解了loC和AOP思想,我们先不考虑Spring是如何实现这两个思想的,此处准备了一个『银行转账」的案例,请分析该案例在代码层次有什么问题?分析之后使用我们已有知识解决这些问题(痛点)。其实这个过程我们就是在一步步分析并手写实现loC和AOP。

第1节银行转账案例界面

Spring源码高级笔记之——银行案例手写IOC和AOP

 

第2节银行转账案例表结构

Spring源码高级笔记之——银行案例手写IOC和AOP

 

第3节银行转账案例代码调用关系

Spring源码高级笔记之——银行案例手写IOC和AOP

 

第4节银行转账案例关键代码

  • TransferServlet
package com.lagou.edu.servlet;
import com.lagou.edu.service.impl.TransferServiceImpl;
import com.lagou.edu.utils.JsonUtils;
import com.lagou.edu.pojo.Result;
import com.lagou.edu.service.TransferService;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author 斗帝
*/
@WebServlet(name="transferServlet",urlPatterns = "/transferServlet")
public class TransferServlet extends HttpServlet {
 // 1. 实例化service层对象
 private TransferService transferService = new TransferServiceImpl();
 @Override
 protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
 doPost(req,resp);
 }
 @Override
 protected void doPost(HttpServletRequest req, HttpServletResponse
resp) throws ServletException, IOException {
 // 设置请求体的字符编码
 req.setCharacterEncoding("UTF-8");
 String fromCardNo = req.getParameter("fromCardNo");
 String toCardNo = req.getParameter("toCardNo");
 String moneyStr = req.getParameter("money");
 int money = Integer.parseInt(moneyStr);
 Result result = new Result();
 try {
 // 2. 调用service层方法
 transferService.transfer(fromCardNo,toCardNo,money);
 result.setStatus("200");
 } catch (Exception e) {
 e.printStackTrace();
 result.setStatus("201");
 result.setMessage(e.toString());
 }
 // 响应
 resp.setContentType("application/json;charset=utf-8");
 resp.getWriter().print(JsonUtils.object2Json(result));
 }
}
  • TransferService接口及实现类
package com.lagou.edu.service;
/**
* @author 斗帝
*/
public interface TransferService {
void transfer(String fromCardNo,String toCardNo,int money) throws
Exception;
}package com.lagou.edu.service.impl;
import com.lagou.edu.dao.AccountDao;
import com.lagou.edu.dao.impl.JdbcAccountDaoImpl;
import com.lagou.edu.pojo.Account;
import com.lagou.edu.service.TransferService;
/**
* @author 斗帝
*/
public class TransferServiceImpl implements TransferService {
private AccountDao accountDao = new JdbcAccountDaoImpl();
@Override
public void transfer(String fromCardNo, String toCardNo, int money)
throws Exception {
Account from = accountDao.queryAccountByCardNo(fromCardNo);Account to = accountDao.queryAccountByCardNo(toCardNo);from.setMoney(from.getMoney()-money);to.setMoney(to.getMoney()+money);accountDao.updateAccountByCardNo(from);accountDao.updateAccountByCardNo(to); }
  • AccountDao层接口及基于Jdbc的实现类
package com.lagou.edu.dao;
import com.lagou.edu.pojo.Account;
/**
* @author 斗帝
*/
public interface AccountDao {
 Account queryAccountByCardNo(String cardNo) throws Exception;
 int updateAccountByCardNo(Account account) throws Exception; 
}
  • JdbcAccountDaoImpl(Jdbc技术实现Dao层接口)
package com.lagou.edu.dao.impl;
import com.lagou.edu.pojo.Account;
import com.lagou.edu.dao.AccountDao;
import com.lagou.edu.utils.DruidUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
/**
* @author 斗帝
*/
public class JdbcAccountDaoImpl implements AccountDao {
@Override
public Account queryAccountByCardNo(String cardNo) throws Exception {
//从连接池获取连接
Connection con = DruidUtils.getInstance().getConnection();
String sql = "select * from account where cardNo=?";
PreparedStatement preparedStatement = con.prepareStatement(sql);
preparedStatement.setString(1,cardNo);
ResultSet resultSet = preparedStatement.executeQuery();
Account account = new Account();
while(resultSet.next()) {
account.setCardNo(resultSet.getString("cardNo"));
account.setName(resultSet.getString("name"));
account.setMoney(resultSet.getInt("money"));
 }
resultSet.close();
preparedStatement.close();
con.close();
return account;
 }
@Override
 public int updateAccountByCardNo(Account account) throws Exception {
 //从连接池获取连接
 Connection con = DruidUtils.getInstance().getConnection();
 String sql = "update account set money=? where cardNo=?";
 PreparedStatement preparedStatement = con.prepareStatement(sql);
 preparedStatement.setInt(1,account.getMoney());
 preparedStatement.setString(2,account.getCardNo());
 int i = preparedStatement.executeUpdate();
 preparedStatement.close();
 con.close();
 return i;
 }
}

第5节 银行转账案例代码问题分析

 

Spring源码高级笔记之——银行案例手写IOC和AOP

 

(1)问题一:在上述案例实现中,service 层实现类在使用 dao 层对象时,直接在TransferServiceImpl 中通过 AccountDao accountDao = new JdbcAccountDaoImpl() 获得了 dao层对象,然而一个 new 关键字却将 TransferServiceImpl 和 dao 层具体的一个实现类JdbcAccountDaoImpl 耦合在了一起,如果说技术架构发生一些变动,dao 层的实现要使用其它技术,比如 Mybatis,思考切换起来的成本?每一个 new 的地方都需要修改源代码,重新编译,面向接口开发的意义将大打折扣?

(2)问题二:service 层代码没有竟然还没有进行事务控制 ?!如果转账过程中出现异常,将可能导致数据库数据错乱,后果可能会很严重,尤其在金融业务。

第6节问题解决思路

  • 针对问题—思考:

实例化对象的方式除了new之外,还有什么技术?反射(需要把类的全限定类名配置在xml中)

  • 考虑使用设计模式中的工厂模式解耦合,另外项目中往往有很多对象需要实例化,那就在工厂中使用反射技术实例化对象,工厂模式很合适

Spring源码高级笔记之——银行案例手写IOC和AOP

 

  • 更进一步,代码中能否只声明所需实例的接口类型,不出现 new 也不出现工厂类的字眼,如下图? 能!声明一个变量并提供 set 方法,在反射的时候将所需要的对象注入进去吧

 

Spring源码高级笔记之——银行案例手写IOC和AOP

 

  • 针对问题二思考:

service 层没有添加事务控制,怎么办?没有事务就添加上事务控制,手动控制 JDBC 的Connection 事务,但要注意将Connection和当前线程绑定(即保证一个线程只有一个Connection,这样操作才针对的是同⼀个 Connection,进而控制的是同一个事务)

Spring源码高级笔记之——银行案例手写IOC和AOP

 

第7节 案例代码改造

(1)针对问题一的代码改造

  • beans.xml

 

<?xml version="1.0" encoding="UTF-8" ?>
<beans>
<bean id="transferService"
class="com.lagou.edu.service.impl.TransferServiceImpl">
<property name="AccountDao" ref="accountDao"></property>
</bean>
<bean id="accountDao"
class="com.lagou.edu.dao.impl.JdbcAccountDaoImpl">
</bean>
</beans>
  • 增加 BeanFactory.java

 

package com.lagou.edu.factory;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author 应癫
*/
public class BeanFactory {
 /**
 * 工厂类的两个任务
 * 任务一:加载解析xml,读取xml中的bean信息,通过反射技术实例化bean对象,然后放入
map待用
 * 任务二:提供接口方法根据id从map中获取bean(静态方法)
 */
 private static Map<String,Object> map = new HashMap<>();
 static {
 InputStream resourceAsStream =BeanFactory.class.getClassLoader().getResourceAsStream("beans.xml");
 SAXReader saxReader = new SAXReader();
 try {
 Document document = saxReader.read(resourceAsStream);
 Element rootElement = document.getRootElement();
 List<Element> list = rootElement.selectNodes("//bean");
 // 实例化bean对象
 for (int i = 0; i < list.size(); i++) {
 Element element = list.get(i);
 String id = element.attributeValue("id");
 String clazz = element.attributeValue("class");
 Class<?> aClass = Class.forName(clazz);
 Object o = aClass.newInstance();
 map.put(id,o);
 }
 // 维护bean之间的依赖关系
 List<Element> propertyNodes =
rootElement.selectNodes("//property");
 for (int i = 0; i < propertyNodes.size(); i++) {
 Element element = propertyNodes.get(i);
 // 处理property元素
 String name = element.attributeValue("name");
 String ref = element.attributeValue("ref");
 
 String parentId =
element.getParent().attributeValue("id");
 Object parentObject = map.get(parentId);
 Method[] methods = parentObject.getClass().getMethods();
 for (int j = 0; j < methods.length; j++) {
 Method method = methods[j];
 if(("set" + name).equalsIgnoreCase(method.getName()))
{
 // bean之间的依赖关系(注入bean)
 Object propertyObject = map.get(ref);
 method.invoke(parentObject,propertyObject);
 }
 }
 // 维护依赖关系后重新将bean放⼊map中
 map.put(parentId,parentObject);
 }
 } catch (DocumentException e) {
 e.printStackTrace();
 } catch (ClassNotFoundException e) {
 e.printStackTrace();
 } catch (IllegalAccessException e) {
 e.printStackTrace();
 } catch (InstantiationException e) {
 e.printStackTrace();
 } catch (InvocationTargetException e) {
 e.printStackTrace();
 }
 }
 public static Object getBean(String id) {
 return map.get(id);
 }
}
  • 修改 TransferServlet

Spring源码高级笔记之——银行案例手写IOC和AOP

 

  • 修改 TransferServiceImpl

Spring源码高级笔记之——银行案例手写IOC和AOP

 

(2)针对问题二的改造

 

  • 增加 ConnectionUtils
package com.lagou.edu.utils;
import java.sql.Connection;
import java.sql.SQLException;
/**
* @author 斗帝
*/
public class ConnectionUtils {
 /*private ConnectionUtils() {
 }
 private static ConnectionUtils connectionUtils = new
ConnectionUtils();
 public static ConnectionUtils getInstance() {
 return connectionUtils;
 }*/
 private ThreadLocal<Connection> threadLocal = new ThreadLocal<>(); //
存储当前线程的连接
 /**
 * 从当前线程获取连接
 */
 public Connection getCurrentThreadConn() throws SQLException {
 /**
 * 判断当前线程中是否已经绑定连接,如果没有绑定,需要从连接池获取一个连接绑定到
当前线程
 */
 Connection connection = threadLocal.get();
 if(connection == null) {
 // 从连接池拿连接并绑定到线程
 connection = DruidUtils.getInstance().getConnection();
 // 绑定到当前线程
 threadLocal.set(connection);
 }
 return connection;
 }
}
  • 增加 TransactionManager 事务管理器类
package com.lagou.edu.utils;
import java.sql.SQLException;
/**
* @author 斗帝
*/
public class TransactionManager {
 private ConnectionUtils connectionUtils;
 public void setConnectionUtils(ConnectionUtils connectionUtils) {
 this.connectionUtils = connectionUtils;
 } // 开启事务
 public void beginTransaction() throws SQLException {
 connectionUtils.getCurrentThreadConn().setAutoCommit(false);
 }
 // 提交事务
 public void commit() throws SQLException {
 connectionUtils.getCurrentThreadConn().commit();
 }
 // 回滚事务
 public void rollback() throws SQLException {
 connectionUtils.getCurrentThreadConn().rollback();
 }
}
  • 增加 ProxyFactory 代理工厂类

 

package com.lagou.edu.factory;
import com.lagou.edu.utils.TransactionManager;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @author 斗帝
*/
public class ProxyFactory {
 private TransactionManager transactionManager;
 public void setTransactionManager(TransactionManager
transactionManager) {
 this.transactionManager = transactionManager;
 } public Object getProxy(Object target) {
 return Proxy.newProxyInstance(this.getClass().getClassLoader(),
target.getClass().getInterfaces(), new InvocationHandler() {
 @Override
 public Object invoke(Object proxy, Method method, Object[]
args) throws Throwable {
 Object result = null;
 try{
 // 开启事务
 transactionManager.beginTransaction();
 // 调用原有业务逻辑
 result = method.invoke(target,args);
 // 提交事务
 transactionManager.commit();
 }catch(Exception e) {
 e.printStackTrace();
 // 回滚事务
 transactionManager.rollback();
 // 异常向上抛出,便于servlet中捕获
 throw e.getCause();
 }
 return result;
 }
 });
 }
}
  • 修改 beans.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!--跟标签beans,里面配置一个又一个的bean子标签,每一个bean子标签都代表一个类的配置--
><beans>
 <!--id标识对象,class是类的全限定类名-->
 <bean id="accountDao"
class="com.lagou.edu.dao.impl.JdbcAccountDaoImpl">
 <property name="ConnectionUtils" ref="connectionUtils"/>
 </bean>
 <bean id="transferService"
class="com.lagou.edu.service.impl.TransferServiceImpl">
 <!--set+ name 之后锁定到传值的set方法了,通过反射技术可以调用该方法传入对应
的值-->
 <property name="AccountDao" ref="accountDao"></property>
 </bean>
 <!--配置新增的三个Bean-->
 <bean id="connectionUtils"
class="com.lagou.edu.utils.ConnectionUtils"></bean>
 <!--事务管理器-->
 <bean id="transactionManager"
class="com.lagou.edu.utils.TransactionManager">
 <property name="ConnectionUtils" ref="connectionUtils"/>
 </bean>
 <!--代理对象工厂-->
 <bean id="proxyFactory" class="com.lagou.edu.factory.ProxyFactory">
 <property name="TransactionManager" ref="transactionManager"/>
 </bean>
</beans>
  • 修改 JdbcAccountDaoImpl
package com.lagou.edu.dao.impl;
import com.lagou.edu.pojo.Account;
import com.lagou.edu.dao.AccountDao;
import com.lagou.edu.utils.ConnectionUtils;
import com.lagou.edu.utils.DruidUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
/**
* @author 斗帝
*/
public class JdbcAccountDaoImpl implements AccountDao {
 private ConnectionUtils connectionUtils;
 public void setConnectionUtils(ConnectionUtils connectionUtils) {
 this.connectionUtils = connectionUtils;
 } @Override
 public Account queryAccountByCardNo(String cardNo) throws Exception {
 //从连接池获取连接
 // Connection con = DruidUtils.getInstance().getConnection();
 Connection con = connectionUtils.getCurrentThreadConn();
 String sql = "select * from account where cardNo=?";
 PreparedStatement preparedStatement = con.prepareStatement(sql);
 preparedStatement.setString(1,cardNo);
 ResultSet resultSet = preparedStatement.executeQuery();
 Account account = new Account();
 while(resultSet.next()) {
 account.setCardNo(resultSet.getString("cardNo"));
 account.setName(resultSet.getString("name"));
 account.setMoney(resultSet.getInt("money"));
 }
 resultSet.close();
 preparedStatement.close();
 //con.close();
 return account;
 }
 @Override
 public int updateAccountByCardNo(Account account) throws Exception {
 // 从连接池获取连接
 // 改造为:从当前线程当中获取绑定的connection连接
 //Connection con = DruidUtils.getInstance().getConnection();
 Connection con = connectionUtils.getCurrentThreadConn();
 String sql = "update account set money=? where cardNo=?";
 PreparedStatement preparedStatement = con.prepareStatement(sql);
 preparedStatement.setInt(1,account.getMoney());
 preparedStatement.setString(2,account.getCardNo());
 int i = preparedStatement.executeUpdate();
 preparedStatement.close();
 //con.close();
 return i;
 }
}
  • 修改 TransferServlet
package com.lagou.edu.servlet;
import com.lagou.edu.factory.BeanFactory;
import com.lagou.edu.factory.ProxyFactory;
import com.lagou.edu.service.impl.TransferServiceImpl;
import com.lagou.edu.utils.JsonUtils;
import com.lagou.edu.pojo.Result;
import com.lagou.edu.service.TransferService;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author 斗帝
*/
@WebServlet(name="transferServlet",urlPatterns = "/transferServlet")
public class TransferServlet extends HttpServlet {
 // 1. 实例化service层对象
 //private TransferService transferService = new TransferServiceImpl();
 //private TransferService transferService = (TransferService)
BeanFactory.getBean("transferService");
 // 从工厂获取委托对象(委托对象是增强了事务控制的功能)
 // 首先从BeanFactory获取到proxyFactory代理工厂的实例化对象
 private ProxyFactory proxyFactory = (ProxyFactory)
BeanFactory.getBean("proxyFactory");
 private TransferService transferService = (TransferService)
proxyFactory.getJdkProxy(BeanFactory.getBean("transferService")) ;
 @Override
 protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
 doPost(req,resp);
 }
 @Override
 protected void doPost(HttpServletRequest req, HttpServletResponse
resp) throws ServletException, IOException {
 // 设置请求体的字符编码
 req.setCharacterEncoding("UTF-8");
 String fromCardNo = req.getParameter("fromCardNo");
 String toCardNo = req.getParameter("toCardNo");
 String moneyStr = req.getParameter("money");
 int money = Integer.parseInt(moneyStr);
 Result result = new Result();
 try {
 // 2. 调用service层方法
 transferService.transfer(fromCardNo,toCardNo,money);
 result.setStatus("200");
 } catch (Exception e) {
 e.printStackTrace();
 result.setStatus("201");
 result.setMessage(e.toString());
 }
 // 响应
 resp.setContentType("application/json;charset=utf-8");
 resp.getWriter().print(JsonUtils.object2Json(result));
 }
}

好了,银行的案例今天就写到这里,喜欢的朋友可以关注一下小编,此系列文章持续更新中;

看完三件事❤️

如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:

  1. 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。

  2. 关注公众号 『 Java斗帝 』,不定期分享原创知识。

  3. 同时可以期待后续文章ing🚀

html python mysql交互_干货!Python与MySQL数据库的交互实战 安装PyMySQL库如果你想要使用python操作MySQL数据库,就必须先要安装pymysql库,这个库的安装很简单,直接使用pip install pymysql;假如这种方式还是安装不上,就用如下链接找一个合适的安装包,进行安装,这个就不细说了。https://www.lfd.uci.edu/~gohlke/pythonlibs/使用Python连接MySQL数据库1)六个常用的连接参数参数... 阅读详情

相关推荐

EGO-Planner文章解读(一)——论文原理和算法实现

详细解读egoplanner论文和代码

fegxg的博客 3992

首次公开 阿里架构师手写源码阅读笔记,细读只有拜服

Java开发人员都知道,阅读源码是非常好的学习方式,在我们日常工作中或多或少都会接触一些开源代码,比如说最常用的Struts、Hibernate、Spring,这些源码的普及与应用程度远远超过我们的想象,正因为很多人使用,也在推动着源码不断地完善。这些优秀的源码中有着多年积淀下来的精华,这些精华是非常值得我们学习的,不管我们当前是什么水平,通过反复阅读源码,能力都会有所提升,小到对源码所提供的功能上的使用更加熟练,大到使我们的程序设计更加完美优秀。当今网上有哪些好的源码阅读指导资料?不要急,今天为大家整理了

jjc4261的博客 148

SAP SD模块进阶:VA31和VA01底层竟是同一个BAPI?揭秘销售单据创建的统一逻辑

本文深入解析SAP SD模块中VA31和VA01的底层统一架构设计,揭示两者如何通过同一个BAPI `SD_SALESDOCUMENT_CREATE`实现销售单据创建。通过ABAP调试和参数化设计分析,展示了SAP如何利用单据类型(doc_type)等关键字段实现业务逻辑复用,为开发者提供配置化设计的重要启示。

weixin_30561177的博客 245

终于有人把Spring源码用最朴素的语言讲明白了

  Spring,相信每个Java开发都用过,而且是每天都在用,那强大又神秘的IoC,AOP,让我们的开发变得越来越简单,只需要一个注解搞定一切,但是它内部到底是什么样子的呢?跟着我,一起探究Spring源码吧。      写在前面的话:Spring项目距今已有15年左右的历史了,是众多Java大神们的杰作,由于我个人水平有限,时间有限,不保证我说的全部都是正确的,但是我可以保证每一句话都是反复推敲,经过验证,绝没有复制粘贴。当然在这里,也不可能把每个方法都进行深层次的分析,只能把重点集中在重要的方

linjingyg的博客 129

手把手教你理解特斯拉Model 3的域控制器架构:RBCM如何成为“多面手”?

本文深入解析特斯拉Model 3的域控制器架构,重点介绍右车身域控制器(RBCM)如何整合车身电子系统功能。RBCM作为多任务处理中枢,管理空调系统、尾部电气设备和超声波雷达等关键功能,展现了特斯拉在汽车电子架构上的创新设计。文章详细探讨了RBCM的硬件架构、功能版图及信号网络,揭示其如何通过高性能MCU和智能开关技术实现功能集中与效率提升。

weixin_30919429的博客 384

LVGL与STM32的理解(基于正点原子资料)

我们要在lcd_draw_fast_rgb_color里面实现对屏的具体操作(也就是在这里实现自己的代码)。lcd_set_window、lcd_write_ram_prepare、lcd_wr_data这三个函数是本例程LCD屏的控制函数(也就是自己写的函数)。以下是stm32工程的文件目录,GUI_APP也可以忽略(细节参考正点原子例程):这里主要是再次加强一下印象,主要就是把。,里面的lcd_init()与lcd_display_dir是。它们都是LVGL的接口,按照它们的需求,把内容给它们即可。

weixin_39257775的博客 3437

GitHub标星75k,阿里15W字的Spring高级文档(全彩版),太全了

第1节Spring简介第2节Spring发展历程第3节Spring的优势第4节Spring的核心结构第5节Spring框架版本这份Spring文档,可以说填补了大家 Spring学习资源的空白。它通过详细的代码示例和学习路径,帮助开发者从零开始学习Spring,逐步掌握其核心知识点。同时,文档结构清晰,内容系统完整,答疑解惑,这对新手来说意义重大。这份文档的成功也说明,在Java后端技术学习资源匮乏的情况下,开源学习社区对开发者的帮助不容小觑。

知识分享官 780

Windows10 使用Apple Studio Display显示器的设置

AppleStudioDisplay显示器购买花了近1.5wRMB,由于为windows台式机,显卡为NVIDAGTX-1660,而AppleStudioDisplay只有雷电接口,尝试了很多种转接方式,均以失败告终,最终使用贝尔金VR线成功,,附图如下这边也测试过NVIDARTX-2060Super、NVIDAGTX-1650显卡,都是能点亮的,NVIDA1650存在关机重启后黑屏,不稳定现象,2060也存在关机重启后不亮现象,后面发现1660s很稳定。...

爱意随风起,人生不可弃。 1万+

通过一个银行转账的案例,手写实现IOC 和 AOP

通过上一篇面试被问了几百遍的 IoC 和 AOP,还在傻傻搞不清楚?我们了解了 IOC 和 AOP 这两个思想,下面我们先不去考虑Spring是如何实现这两个思想的,先通过一个银行转账的案例,分析一下该案例在代码层面存在什么问题?分析之后使用我们已有的知识来解决这些问题(痛点)。其实这个过程就是在一步步分析并手动实现 IOC 和 AOP 。案例介绍银行转账:账户A向账户B转账(账户A减钱,账户B加钱)。为了简单起见,在前端页面中写死了两个账户。每次只需要输入转账金额,进行转账操作,验证功能即可。案例表结构

m0_63437643的博客 152

AI编码规则:从提示工程到自动化,提升大模型生成代码质量

在软件工程领域,代码质量是保障软件可维护性、安全性和团队协作效率的核心。其背后遵循着从基础语法规范到架构设计原则的一系列工程实践。随着大语言模型(LLM)在代码生成任务中的广泛应用,如何确保AI生成的代码符合这些工程标准,成为一个关键的技术挑战。这涉及到将人类工程师积累的最佳实践,转化为机器可理解、可执行的明确约束。通过系统化的**编码规则**定义与集成,例如构建涵盖安全、风格、架构的多层次规则集,并将其融入**提示工程**或自动化工作流,可以显著引导AI产出更健壮、规范的代码。这种方法的价值在于,它能将模

weixin_42525189的博客 643

apk反编译修改教程系列-----修改apk应用名称 任意修改名称 签名【一】

这个是最最简单的反编译操作了。写这个教程的目的是其中很多粉丝要求出一点入门的教程。当然演示的是使用MT来操作。还有很多类似的软件可以达到目的。例如NP apltool等等或者电脑端也有很多反编译软件修改。对于玩机用户来说。也可以在系统包里直接修改一些app。

小马哥的专栏 7266

GitHub上标星13k的《Java面试突击版》,oppoJava面试题

在这里,由于面试中MySQL问的比较多,因此也就在此以MySQL为例为大家总结分享。但是你要学习的往往不止这一点,还有一些主流框架的使用,Spring源码的学习,Mybatis源码的学习等等都是需要掌握的,我也把这些知识点都整理起来了都整理起来了[外链图片转存中…(img-YzTJj9fj-1709713212722)][外链图片转存中…(img-rt9jujeA-1709713212723)]本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】

m0_60575487的博客 456

6、基因组数据可视化与甲基化分析:从基础操作到深入洞察

本文详细介绍了基因组数据可视化和全基因组DNA甲基化分析的方法和技术,包括基因组查看器(IGV)的基本操作、单核苷酸变异的可视化、DNA甲基化与CpG岛的关联分析、统计建模与显著甲基化区域识别,以及不同细胞系之间的甲基化模式差异分析。通过具体案例展示了如何利用MATLAB进行数据分析和可视化,为基因组研究、疾病机制探索及个性化医疗提供了技术支撑和实践参考。

qsc901234的博客 295

你可以错过其他笔记,但这份Spring 源码笔记你一定不能错过!

Spring简介Spring发展历程Spring的优势Spring的核心结构Spring框架版本。

m0_73311735的博客 189

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

撸完阿里P8手写的Spring源码笔记后,感觉之前读的都是ZZ

Spring让我们可以更快,更轻松,更安全地进行Java编程。Spring对速度,简单性和生产率的关注使其成为世界上最受欢迎的Java框架。

m0_69305074的博客 383

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

厉害!年薪近百万架构师保姆式讲解的这份Spring源码笔记,绝绝子

Spring框架,作为Java开发人员肯定都不陌生。Spring 框架现在已经越来越受欢迎,你可以错过其他框架,但 Spring 一定不能错过!

老男孩的架构路 116

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

干货整理,华为java面试难度

总体来说,如果你想转行从事程序员的工作,Java开发一定可以作为你的第一选择。但是不管你选择什么编程语言,提升自己的硬件实力才是拿高薪的唯一手段。如果你以这份学习路线来学习,你会有一个比较系统化的知识网络,也不至于把知识学习得很零散。我个人是完全不建议刚开始就看《Java编程思想》、《Java核心技术》这些书籍,看完你肯定会放弃学习。建议可以看一些视频来学习,当自己能上手再买这些书看又是非常有收获的事了。看一些视频来学习,当自己能上手再买这些书看又是非常有收获的事了。

D1561691的博客 969

厉害!年薪近百万架构师讲解的这份Spring源码笔记,绝绝子

Spring简介Spring发展历程Spring的优势Spring的核心结构Spring框架版本Spring 是 Java 后端领域最最最重要的技术之一,熟练掌握它对于 Java 程序员至关重要。这份笔记从0开始手把手教你学习 Spring ,循序渐进由浅入深掌握 Spring 的核心与底层,助你成为 Spring 大佬。

javaAnPou的博客 166

厉害,年薪近百万架构师讲解的这份Spring源码笔记,绝绝子

Spring简介Spring发展历程Spring的优势Spring的核心结构Spring框架版本​第二部分核心思想IoCAOP​第三部分手写实现IoC和AOP银行转账案例界面银行转账案例表结构银行转账案例代码调用关系银行转账案例关键代码银行转账案例代码问题分析问题解决思路案例代码改造​第四部分SpringIOC应用SpringIoC基础SpringIOC高级特性​第五部分SpringIOC源码深度剖析SpringIoC容器初始化主体流程https。...

JHIII的博客 246

Spring真的这么难懂吗?还是你没找对方法?

👨‍💻连读同事写的代码都费劲,还读Spring? 咋的,Spring 很难读! 这个与我们码农朝夕相处的 Spring,就像睡在你身边的媳妇,你知道找她要吃、要喝、要零花钱、要买皮肤。但你不知道她的仓库共有多少存粮、也不知道她是买了理财还是存了银行。🍑开个玩笑,接下来我要正经了! 一、为什么Spring难读懂? 为什么 Spring 天天用,但要想去读一读源码,怎么就那么难!因为由Java和J2EE开发领域的专家 Rod Johnson 于 2002 年提出并随后创建的 Spring 框架,随着 JD

wdj_yyds的博客 3907

厉害了!阿里p8架构大神把Spring源码讲的简单易懂又通透!

第1节Spring简介第2节Spring发展历程第3节Spring的优势第4节Spring的核心结构第5节Spring框架版本。

Java_ttcd的博客 357

腾讯内部年薪近百万的架构师讲解的这份Spring源码笔记,看完你还不会Spring?

Spring简介Spring发展历程Spring的优势Spring的核心结构Spring框架版本Spring 是 Java 后端领域最最最重要的技术之一,熟练掌握它对于 Java 程序员至关重要。这份笔记从0开始手把手教你学习 Spring ,循序渐进由浅入深掌握 Spring 的核心与底层,助你成为 Spring 大佬。

the shy 204

基于JavaWeb开发的银行信息管理系统毕业设计

在社会快速发展的影响下,银行继续发展,大大增加了存取款和贷款的数量、多样性、质量等等的要求,使小型银行的管理和运营比过去十年更加困难。依照这一现实为基础,设计一个快捷而又方便的小型银行管理系统是一项十分重要并且有价值的事情。对于传统的在银行管理制模型来说,银行管理系统具有许多不可比拟的优势,首先是快速更新订单信息,其次是大量信息的管理,最后是高度安全,以及使用简单等特性,这使得小型银行管理系统的管理和运营非常方便。现代社会的网络和信息技术不断提高,人们的生活水平达到一个新的水平。

央顺科技官方博客 1561

基于JavaWeb开发的springboot小型银行管理系统

在社会快速发展的影响下,银行继续发展,大大增加了存取款和贷款的数量、多样性、质量等等的要求,使小型银行的管理和运营比过去十年更加困难。依照这一现实为基础,设计一个快捷而又方便的小型银行管理系统是一项十分重要并且有价值的事情。对于传统的在银行管理制模型来说,银行管理系统具有许多不可比拟的优势,首先是快速更新订单信息,其次是大量信息的管理,最后是高度安全,以及使用简单等特性,这使得小型银行管理系统的管理和运营非常方便。现代社会的网络和信息技术不断提高,人们的生活水平达到一个新的水平。

央顺科技官方博客 976
上一篇: 大厂最常问的19道并发编程面试真题(含答案+阿里内部学习资料)
下一篇: 国庆前喜讯,七战字节终获offer,面试全过程分享,纯手肛;
Java斗帝之路
博客等级 码龄7年 2392粉丝 687原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值