分析并手写实现IOC
业务场景
模拟银行转账业务
1. 页面
2. 数据表结构
CREATE TABLE `account` (
`name` varchar(255) DEFAULT NULL,
`cardNo` varchar(255) DEFAULT NULL,
`money` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
3. 表数据
4. 基本代码
TransferServlet.java
@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及实现类
public interface TransferService {
void transfer(String fromCardNo,String toCardNo,int money) throws Exception;
}
public class TransferServiceImpl implements TransferService {
// private AccountDao accountDao = new JdbcAccountDaoImpl();
// private AccountDao accountDao = (AccountDao) BeanFactory.getBean("accountDao");
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
private TransactionManager transactionManager;
public void setTransactionManager(TransactionManager transactionManager) {
this.transactionManager = transactionManager;
}
@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(to);
accountDao.updateAccountByCardNo(from);
}
}
AccountDao及实现类
public interface AccountDao {
Account queryAccountByCardNo(String cardNo) throws Exception;
int updateAccountByCardNo(Account account) throws Exception;
}
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;
}
}
工具类 DruidUtils
public class DruidUtils {
private DruidUtils(){
}
private static DruidDataSource druidDataSource = new DruidDataSource();
static {
druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");
druidDataSource.setUrl("jdbc:mysql://localhost:3306/bank");
druidDataSource.setUsername("root");
druidDataSource.setPassword("root");
}
public static DruidDataSource getInstance() {
return druidDataSource;
}
}
JsonUtils
public class JsonUtils {
private static final ObjectMapper MAPPER = new ObjectMapper();
/**
* 将对象转换成json字符串。
* @param data
* @return
*/
public static String object2Json(Object data) {
try {
String string = MAPPER.writeValueAsString(data);
return string;
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
/**
* 将json结果集转化为对象
*
* @param jsonData json数据
* @param beanType 对象中的object类型
* @return
*/
public static <T> T json2Pojo(String jsonData, Class<T> beanType) {
try {
T t = MAPPER.readValue(jsonData, beanType);
return t;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 将json数据转换成pojo对象list
* @param jsonData
* @param beanType
* @return
*/
public static <T>List<T> json2List(String jsonData, Class<T> beanType) {
JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType);
try {
List<T> list = MAPPER.readValue(jsonData, javaType);
return list;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
实体类 Result
public class Result {
private String status;
private String message;
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
@Override
public String toString() {
return "Result{" +
"status='" + status + '\'' +
", message='" + message + '\'' +
'}';
}
}
Account
public class Account {
private String cardNo;
private String name;
private int money;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
public String getCardNo() { return cardNo; }
public void setCardNo(String cardNo) { this.cardNo = cardNo;}
@Override
public String toString() {
return "Account{" +
"cardNo='" + cardNo + '\'' +
", name='" + name + '\'' +
", money=" + money +
'}';
}
}
5. 代码分析
- 代码调用关系
- 代码分析
6. 问题分析
- 问题一 代码耦合
针对问题一思考: 实例化对象的⽅式除了 new 之外,还有什么技术?
- 反射 (需要把类的全限定类名配置在xml中)
- 使用工厂模式来通过反射生产对象
- 更进一步,代码中能否只需要声明所需实例的接口类型,不出现new关键字,也不出现工厂类的字眼?
解决思路: 1.创建一个放置所有类的全限定名的配置类 beans.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!--根标签beans,里面配置bean子标签,每一个bean子标签都代表一个类的配置-->
<beans>
<bean id="accountDao" class="com.example.dao.impl.JdbcAccountDaoImpl">
</bean>
<bean id="transferService" class="com.example.service.impl.TransferServiceImpl">
</bean>
</beans>
- 注 这里有一个问题 accountDao的bean标签必须放在transferService标签的上边,否则如果先初始化service,调用newInstance()的时候,就会去调用getBean()去获取,此时map中并没有dao的实例。
2.创建配置类,解析并存储所有实例化之后的bean,并提供获取方法
public class BeanFactory {
private static Map<String, Object> map = new HashMap<>();
/**
* 解析配置文件 创建所有的bean
*/
static {
//读取解析beans.xml
InputStream resourceAsStream = BeanFactory.class.getClassLoader().getResourceAsStream("beans.xml");
SAXReader saxReader = new SAXReader();
Document document = null;
try {
document = saxReader.read(resourceAsStream);
} catch (DocumentException e) {
e.printStackTrace();
}
//获取根节点 beans
Element rootElement = document.getRootElement();
//获取所有的bean标签
List<Element> beanLst = rootElement.selectNodes("//bean");
for (Element bean : beanLst) {
//获取每个标签的id和class
String id = bean.attributeValue("id");
String clazz = bean.attributeValue("class");
//反射创建class实例
try {
Class<?> instance = Class.forName(clazz);
//将实例存储在map中
map.put(id, instance.newInstance());
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
}
/**
* 提供getBean方法
*/
public static Object getBean(String id) {
return map.get(id);
}
}
3.修改service中和servlet中的引用 从工厂中获取 servlet
@WebServlet(name="transferServlet",urlPatterns = "/transferServlet")
public class TransferServlet extends HttpServlet {
// 1. 实例化service层对象
// private TransferService transferService = new TransferServiceImpl();
//从BeanFactory中获取bean
private TransferService transferService = (TransferService) BeanFactory.getBean("transferService");
//省略其他代码
....
}
service
public class TransferServiceImpl implements TransferService {
// private AccountDao accountDao = new JdbcAccountDaoImpl();
private AccountDao accountDao = (AccountDao) BeanFactory.getBean("accountDao");
省略其他代码......
}
4.测试代码
插件中运行Tomcat
打开本地的8080 http://localhost:8080
在转账金额处输入数字,点击转出
问题一解决。
思考二:
还有没有更好的办法解决代码耦合: 不在service中向工厂类去获取
解决思路: 1.service中定义private AccountDao accountDao; 并提供setter()
public class TransferServiceImpl implements TransferService {
// private AccountDao accountDao = new JdbcAccountDaoImpl();
// private AccountDao accountDao = (AccountDao) BeanFactory.getBean("accountDao");
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
//省略部分代码
......
}
2.在beans.xml中添加properties标签,标签中配置set方法的方法名,以及需要传递的参数类型
<?xml version="1.0" encoding="UTF-8" ?>
<!--根标签beans,里面配置bean子标签,每一个bean子标签都代表一个类的配置-->
<beans>
<bean id="connectionUtils" class="com.example.utils.ConnectionUtils"></bean>
<bean id="accountDao" class="com.example.dao.impl.JdbcAccountDaoImpl">
</bean>
<bean id="transferService" class="com.example.service.impl.TransferServiceImpl">
<!--name为setter() 去掉set后的名称 ref指向需要传递的参数类型-->
<properties name="AccountDao" ref="accountDao"></properties>
</bean>
</beans>
3.修改xml文件解析 解析所有的properties标签 为属性赋值
public class BeanFactory {
private static Map<String, Object> map = new HashMap<>();
/**
* 解析配置文件 创建所有的bean
*/
static {
//读取解析beans.xml
InputStream resourceAsStream = BeanFactory.class.getClassLoader().getResourceAsStream("beans.xml");
SAXReader saxReader = new SAXReader();
Document document = null;
try {
document = saxReader.read(resourceAsStream);
} catch (DocumentException e) {
e.printStackTrace();
}
//获取根节点 beans
Element rootElement = document.getRootElement();
//获取所有的bean标签
List<Element> beanLst = rootElement.selectNodes("//bean");
for (Element bean : beanLst) {
//获取每个标签的id和class
String id = bean.attributeValue("id");
String clazz = bean.attributeValue("class");
//反射创建class实例
try {
Class<?> instance = Class.forName(clazz);
//将实例存储在map中
map.put(id, instance.newInstance());
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
//获取所有的properties标签 为属性赋值
List<Element> propertiesLst = rootElement.selectNodes("//properties");
for (Element element : propertiesLst) {
//获取name和ref
String name = element.attributeValue("name");
String ref = element.attributeValue("ref");
//获取当前元素的父元素 当前properties所在的bean
Element parentElement = element.getParent();
//获取id
String parentId = parentElement.attributeValue("id");
//获取实例对象
Object parentObj = map.get(parentId);
//获取所有方法
Method[] methods = parentObj.getClass().getMethods();
for (Method method : methods) {
//通过方法名匹配到当前这个属性的setter方法
if (method.getName().equalsIgnoreCase("set" + name)) {
try {
//执行setter方法 将ref指向的对象赋值给属性
method.invoke(parentObj, map.get(ref));
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
}
/**
* 提供getBean方法
*/
public static Object getBean(String id) {
return map.get(id);
}
}
4.测试代码
- 问题二 事务管理
思考:
- 需要添加事务管理,手动控制jdbc的事务,同时要确保所有的执行都使用同一个连接connection
- 使用同一个connection,需要将连接保存在当前线程中
解决思路:
- 创建连接工具类ConnectionUtils
public class ConnectionUtils {
//线程缓存
ThreadLocal<Connection> threadLocal = new ThreadLocal<>();
private static ConnectionUtils connectionUtils = new ConnectionUtils();
//保证工具类单例
public static ConnectionUtils getConnectionUtils() {
return connectionUtils;
}
//获取连接
public Connection getConnection() throws SQLException {
//通过当前线程获取
Connection connection = threadLocal.get();
if (null == connection) {
// 如果为空,从连接池获取连接,并保存到当前线程
connection = DruidUtils.getInstance().getConnection();
threadLocal.set(connection);
}
return connection;
}
}
- 修改dao层 必须关闭con.close() 不然连接关闭后将不再是同一个连接
public class JdbcAccountDaoImpl implements AccountDao {
@Override
public Account queryAccountByCardNo(String cardNo) throws Exception {
//从连接池获取连接
// Connection con = DruidUtils.getInstance().getConnection();
Connection con = ConnectionUtils.getConnectionUtils().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连接
// Connection con = DruidUtils.getInstance().getConnection();
Connection con = ConnectionUtils.getConnectionUtils().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;
}
}
- 修改service
@Override
public void transfer(String fromCardNo, String toCardNo, int money) throws Exception {
try {
//取消事务自动提交
ConnectionUtils.getConnectionUtils().getConnection().setAutoCommit(false);
Account from = accountDao.queryAccountByCardNo(fromCardNo);
Account to = accountDao.queryAccountByCardNo(toCardNo);
from.setMoney(from.getMoney()-money);
to.setMoney(to.getMoney()+money);
accountDao.updateAccountByCardNo(to);
//测试异常
int i = 1/0;
accountDao.updateAccountByCardNo(from);
//手动commit
ConnectionUtils.getConnectionUtils().getConnection().commit();
} catch (Exception e) {
e.printStackTrace();
//有异常回滚事务
ConnectionUtils.getConnectionUtils().getConnection().rollback();
}
}
- 进一步改造: 将设置自动提交、提交、回滚封装工具类
/**
* 事务管理器类:负责手动事务的开启、提交、回滚
*/
public class TransactionManager {
private static TransactionManager transactionManager = new TransactionManager();
public static TransactionManager getTransactionManager() {
return transactionManager;
}
public void setAutoCommit() throws SQLException {
ConnectionUtils.getConnectionUtils().getConnection().setAutoCommit(false);
}
public void commit() throws SQLException {
ConnectionUtils.getConnectionUtils().getConnection().commit();
}
public void rollback() throws SQLException {
ConnectionUtils.getConnectionUtils().getConnection().rollback();
}
}
@Override
public void transfer(String fromCardNo, String toCardNo, int money) throws Exception {
try {
// //取消事务自动提交
// ConnectionUtils.getConnectionUtils().getConnection().setAutoCommit(false);
TransactionManager.getTransactionManager().setAutoCommit();
Account from = accountDao.queryAccountByCardNo(fromCardNo);
Account to = accountDao.queryAccountByCardNo(toCardNo);
from.setMoney(from.getMoney()-money);
to.setMoney(to.getMoney()+money);
accountDao.updateAccountByCardNo(to);
int i = 1/0;
accountDao.updateAccountByCardNo(from);
//手动commit
// ConnectionUtils.getConnectionUtils().getConnection().commit();
TransactionManager.getTransactionManager().commit();
} catch (Exception e) {
e.printStackTrace();
//有异常回滚事务
// ConnectionUtils.getConnectionUtils().getConnection().rollback();
TransactionManager.getTransactionManager().rollback();
}
}
5.再进一步改造,将工具类都添加到容器中,通过setter()自动注入 service
public class TransferServiceImpl implements TransferService {
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
private TransactionManager transactionManager;
public void setTransactionManager(TransactionManager transactionManager) {
this.transactionManager = transactionManager;
}
@Override
public void transfer(String fromCardNo, String toCardNo, int money) throws Exception {
try {
//取消事务自动提交
// ConnectionUtils.getConnectionUtils().getConnection().setAutoCommit(false);
// TransactionManager.getTransactionManager().setAutoCommit();
transactionManager.setAutoCommit();
Account from = accountDao.queryAccountByCardNo(fromCardNo);
Account to = accountDao.queryAccountByCardNo(toCardNo);
from.setMoney(from.getMoney()-money);
to.setMoney(to.getMoney()+money);
accountDao.updateAccountByCardNo(to);
int i = 1/0;
accountDao.updateAccountByCardNo(from);
//手动commit
// ConnectionUtils.getConnectionUtils().getConnection().commit();
// TransactionManager.getTransactionManager().commit();
transactionManager.commit();
} catch (Exception e) {
e.printStackTrace();
//有异常回滚事务
// ConnectionUtils.getConnectionUtils().getConnection().rollback();
// TransactionManager.getTransactionManager().rollback();
transactionManager.rollback();
}
}
}
dao
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.getConnectionUtils().getConnection();
Connection con = connectionUtils.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;
}
......
}
配置beans.xml 之前将property标签写成properties,这两个标签都可以,名字是自定义的,解析的时候对应上就可以了 只不过spring中使用的是property
<?xml version="1.0" encoding="UTF-8" ?>
<!--根标签beans,里面配置bean子标签,每一个bean子标签都代表一个类的配置-->
<beans>
<bean id="connectionUtils" class="com.example.utils.ConnectionUtils"></bean>
<bean id="accountDao" class="com.example.dao.impl.JdbcAccountDaoImpl">
<property name="ConnectionUtils" ref="connectionUtils"></property>
</bean>
<bean id="transferService" class="com.example.service.impl.TransferServiceImpl">
<property name="AccountDao" ref="accountDao"></property>
<property name="TransactionManager" ref="transactionManager"></property>
</bean>
<bean id="transactionManager" class="com.example.utils.TransactionManager">
<property name="ConnectionUtils" ref="connectionUtils"></property>
</bean>
</beans>
修改BeanFactory中的配置文件解析,新增解析properties标签,使用反射调用class中的setter(),为属性赋值
public class BeanFactory {
private static Map<String, Object> map = new HashMap<>();
/**
* 解析配置文件 创建所有的bean
*/
static {
//读取解析beans.xml
InputStream resourceAsStream = BeanFactory.class.getClassLoader().getResourceAsStream("beans.xml");
SAXReader saxReader = new SAXReader();
Document document = null;
try {
document = saxReader.read(resourceAsStream);
} catch (DocumentException e) {
e.printStackTrace();
}
//获取根节点 beans
Element rootElement = document.getRootElement();
//获取所有的bean标签
List<Element> beanLst = rootElement.selectNodes("//bean");
for (Element bean : beanLst) {
//获取每个标签的id和class
String id = bean.attributeValue("id");
String clazz = bean.attributeValue("class");
//反射创建class实例
try {
Class<?> instance = Class.forName(clazz);
//将实例存储在map中
map.put(id, instance.newInstance());
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
//获取所有的properties标签 为属性赋值
List<Element> propertiesLst = rootElement.selectNodes("//properties");
for (Element element : propertiesLst) {
//获取name和ref
String name = element.attributeValue("name");
String ref = element.attributeValue("ref");
//获取当前元素的父元素 当前properties所在的bean
Element parentElement = element.getParent();
//获取id
String parentId = parentElement.attributeValue("id");
//获取实例对象
Object parentObj = map.get(parentId);
//获取所有方法
Method[] methods = parentObj.getClass().getMethods();
for (Method method : methods) {
//通过方法名匹配到当前这个属性的setter方法
if (method.getName().equalsIgnoreCase("set" + name)) {
try {
//执行setter方法 将ref指向的对象赋值给属性
method.invoke(parentObj, map.get(ref));
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
}
/**
* 提供getBean方法
*/
public static Object getBean(String id) {
return map.get(id);
}
}
测试代码 ......
6.对方法进行增强,抽取事务管理,不在service中添加,通过代理的方式增强service
a. 新增ProxyFactory,通过类型获取代理类,ProxyFactory中需要注入事务管理类TransactionManager
public class ProxyFactory {
private TransactionManager transactionManager;
public void setTransactionManager(TransactionManager transactionManager) {
this.transactionManager = transactionManager;
}
public Object getJdkProxyClass(Object obj) {
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object invoke = null;
try {
//取消事务自动提交
transactionManager.setAutoCommit();
invoke = method.invoke(obj, args);
//手动commit
transactionManager.commit();
} catch (Exception e) {
e.printStackTrace();
//有异常回滚事务
transactionManager.rollback();
throw e;
}
return invoke;
}
});
}
}
b. 去掉service中的事务管理
public class TransferServiceImpl implements TransferService {
// private AccountDao accountDao = new JdbcAccountDaoImpl();
// private AccountDao accountDao = (AccountDao) BeanFactory.getBean("accountDao");
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
@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(to);
int i = 1/0;
accountDao.updateAccountByCardNo(from);
}
}
<bean id="transferService" class="com.example.service.impl.TransferServiceImpl">
<property name="AccountDao" ref="accountDao"></property>
<!-- <property name="TransactionManager" ref="transactionManager"></property>-->
</bean>
c. 修改servlet中的service获取
@WebServlet(name="transferServlet",urlPatterns = "/transferServlet")
public class TransferServlet extends HttpServlet {
//将proxyFactory注册到beanFactory中
private ProxyFactory proxyFactory = (ProxyFactory) BeanFactory.getBean("proxyFactory");
//调用proxyFactory.getJdkProxyClass()获取transferService的代理类
private TransferService transferService = (TransferService) proxyFactory.getJdkProxyClass(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));
}
}
d. 测试代码 ......