欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

自己編寫IOC控制反轉(zhuǎn)及AOP面向切面

 更新時(shí)間:2021年06月22日 14:15:12   作者:懷瑾Hello World  
本文展示通過一個(gè)案例來自己手寫IOC和AOP代碼,通過銀行轉(zhuǎn)賬案例詳細(xì)的代碼編寫和文檔解釋來說明IOC和AOP的思想,會(huì)分享存在的問題和解決問題的思路

1.概念

IOC:Inversion of control 控制反轉(zhuǎn)

  • 控制:指的是對(duì)象創(chuàng)建(實(shí)例化、管理)的權(quán)利
  • 反轉(zhuǎn):控制權(quán)交給外部環(huán)境了(spring框架、IoC容器)
  • 傳統(tǒng)開發(fā)⽅式:⽐如類A依賴于類B,往往會(huì)在類A中new⼀個(gè)B的對(duì)象
  • IoC思想下開發(fā)方式:我們不⽤⾃⼰去new對(duì)象了,⽽是由IoC容器(Spring框架)去幫助我們實(shí)例化對(duì)象并且管理它,我們需要使⽤哪個(gè)對(duì)象,去問IoC容器要即可。
  • 解決的問題:解決對(duì)象之間的耦合問題,避免new關(guān)鍵字
  • Ioc和DI區(qū)別:IOC和DI是從不同角度描述同一件事情(對(duì)象實(shí)例化及依賴關(guān)系維護(hù)這件事情)。IOC是站在對(duì)象的角度,對(duì)象實(shí)例化及其管理的權(quán)力交給了(反轉(zhuǎn))容器。DI:Dependancy Injection(依賴注⼊),是站在容器的角度,容器會(huì)把對(duì)象依賴的其他對(duì)象注入(送進(jìn)去),比如A對(duì)象實(shí)例化過程中因?yàn)槁暶髁艘粋€(gè)B類型的屬性,那么就需要容器把B對(duì)象注入給A

AOP:Aspect oriented Programming 面向切面編程

  • 起源:aop是oop的延續(xù),oop三大特征:封裝、繼承、多態(tài)。是一種垂直縱向的繼承體系。OOP編程思想可以解決⼤多數(shù)的代碼重復(fù)問題,但是有⼀些情況是處理不了的,⽐如在頂級(jí)⽗類中的多個(gè)⽅法中相同位置出現(xiàn)了重復(fù)代碼,OOP就解決不了
  • 橫切邏輯代碼問題:1.橫切代碼重復(fù)問題。2.橫切邏輯代碼和業(yè)務(wù)代碼混雜在⼀起,代碼臃腫,維護(hù)不⽅便
  • AOP解決的問題:在不改變?cè)袠I(yè)務(wù)邏輯情況下,增強(qiáng)橫切邏輯代碼,根本上解耦合,避免橫切邏輯代碼重復(fù)
  • 面向切面編程理解:「切」:指的是橫切邏輯,原有業(yè)務(wù)邏輯代碼我們不能動(dòng),只能操作橫切邏輯代碼,所以⾯向橫切邏輯?!?#12207;」:橫切邏輯代碼往往要影響的是很多個(gè)⽅法,每⼀個(gè)⽅法都如同⼀個(gè)點(diǎn),多個(gè)點(diǎn)構(gòu)成⾯,有⼀個(gè)⾯的概念在⾥⾯

2.通過銀行轉(zhuǎn)賬案例手寫IOC和AOP

2.1.表結(jié)構(gòu)

CREATE TABLE `account` (
  `name` varchar(255) DEFAULT NULL COMMENT '用戶名',
  `money` varchar(255) DEFAULT NULL COMMENT '賬戶金額',
  `cardNo` varchar(255) NOT NULL COMMENT '銀行卡號(hào)'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

2.2.銀行轉(zhuǎn)賬調(diào)用關(guān)系

在這里插入圖片描述

2.3.分析存在的問題

  • (1)問題⼀:在上述案例實(shí)現(xiàn)中,service 層實(shí)現(xiàn)類在使⽤ dao 層對(duì)象時(shí),直接在TransferServiceImpl 中通過 AccountDao accountDao = new JdbcAccountDaoImpl() 獲得了 dao層對(duì)象,然⽽⼀個(gè) new 關(guān)鍵字卻將 TransferServiceImpl 和 dao 層具體的⼀個(gè)實(shí)現(xiàn)類JdbcAccountDaoImpl 耦合在了⼀起,如果說技術(shù)架構(gòu)發(fā)⽣⼀些變動(dòng),dao 層的實(shí)現(xiàn)要使⽤其它技術(shù),⽐如 Mybatis,思考切換起來的成本?每⼀個(gè) new 的地⽅都需要修改源代碼,重新編譯,⾯向接⼝開發(fā)的意義將⼤打折扣?
  • (2)問題⼆:service 層代碼沒有竟然還沒有進(jìn)⾏事務(wù)控制 ?!如果轉(zhuǎn)賬過程中出現(xiàn)異常,將可能導(dǎo)致數(shù)據(jù)庫數(shù)據(jù)錯(cuò)亂,后果可能會(huì)很嚴(yán)重,尤其在⾦融業(yè)務(wù)

2.4.解決問題思路

  • 實(shí)例化對(duì)象的⽅式除了 new 之外,還有什么技術(shù)?反射 (需要把類的全限定類名配置在xml中)
  • 考慮使⽤設(shè)計(jì)模式中的⼯⼚模式解耦合,另外項(xiàng)⽬中往往有很多對(duì)象需要實(shí)例化,那就在⼯⼚中使⽤反 射技術(shù)實(shí)例化對(duì)象,⼯⼚模式很合適
  • service 層沒有添加事務(wù)控制,怎么辦?沒有事務(wù)就添加上事務(wù)控制,⼿動(dòng)控制 JDBC 的Connection 事務(wù),但要注意將Connection和當(dāng)前線程綁定(即保證⼀個(gè)線程只有⼀個(gè)Connection,這樣操作才針對(duì)的是同⼀個(gè) Connection,進(jìn)⽽控制的是同⼀個(gè)事務(wù))。分析:數(shù)據(jù)庫的事務(wù)歸根結(jié)底是Connection的事務(wù)connection.commit();提交事務(wù) connection.rollback();回滾事務(wù)

2.5.通過IOC及AOP進(jìn)行改造

2.5.0.pom.xml

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.lagou.edu</groupId>
  <artifactId>lagou-transfer</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>

  <name>lagou-transfer Maven Webapp</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
  </properties>


  <dependencies>
    <!-- 單元測(cè)試Junit -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
    </dependency>

    <!-- mysql數(shù)據(jù)庫驅(qū)動(dòng)包 -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.35</version>
    </dependency>
    <!--druid連接池-->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.1.21</version>
    </dependency>

    <!-- servlet -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
      <scope>provided</scope>
    </dependency>

    <!-- jackson依賴 -->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.6</version>
    </dependency>

    <!--dom4j依賴-->
    <dependency>
      <groupId>dom4j</groupId>
      <artifactId>dom4j</artifactId>
      <version>1.6.1</version>
    </dependency>
    <!--xpath表達(dá)式依賴-->
    <dependency>
      <groupId>jaxen</groupId>
      <artifactId>jaxen</artifactId>
      <version>1.1.6</version>
    </dependency>
    <!--引入cglib依賴包-->
    <dependency>
      <groupId>cglib</groupId>
      <artifactId>cglib</artifactId>
      <version>2.1_2</version>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <!-- 配置Maven的JDK編譯級(jí)別 -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.2</version>
        <configuration>
          <source>11</source>
          <target>11</target>
          <encoding>UTF-8</encoding>
        </configuration>
      </plugin>

      <!-- tomcat7插件 -->
      <!-- 注意:目前來說,maven中央倉庫還沒有tomcat8的插件 -->
      <plugin>
        <groupId>org.apache.tomcat.maven</groupId>
        <artifactId>tomcat7-maven-plugin</artifactId>
        <version>2.2</version>
        <configuration>
          <port>8080</port>
          <path>/</path>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

2.5.1.index.xml

<!doctype html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>轉(zhuǎn)賬匯款</title>

    <script type="text/javascript" src="js/jquery-3.4.1.min.js"></script>


    <style type="text/css">
        body {
            background-color:#00b38a;
            text-align:center;
        }

        .lp-login {
            position:absolute;
            width:500px;
            height:300px;
            top:50%;
            left:50%;
            margin-top:-250px;
            margin-left:-250px;
            background: #ffffff;
            border-radius: 4px;
            box-shadow: 0 0 10px #12a591;
            padding: 57px 50px 35px;
            box-sizing: border-box
        }


        .lp-login .submitBtn {
            display:block;
            text-decoration:none;
            height: 48px;
            width: 150px;
            line-height: 48px;
            font-size: 16px;
            color: #fff;
            text-align: center;
            background-image: -webkit-gradient(linear, left top, right top, from(#09cb9d), to(#02b389));
            background-image: linear-gradient(90deg, #09cb9d, #02b389);
            border-radius: 3px
        }


        input[type='text'] {
            height:30px;
            width:250px;
        }

        span {
            font-style: normal;
            font-variant-ligatures: normal;
            font-variant-caps: normal;
            font-variant-numeric: normal;
            font-variant-east-asian: normal;
            font-weight: normal;
            font-stretch: normal;
            font-size: 14px;
            line-height: 22px;
            font-family: "Hiragino Sans GB", "Microsoft Yahei", SimSun, Arial, "Helvetica Neue", Helvetica;
        }

    </style>
    <script type="text/javascript">
        $(function(){
            $(".submitBtn").bind("click",function(){
                var fromAccount = $("#fromAccount").val();
                var toAccount = $("#toAccount").val();
                var money = $("#money").val();

                if(money == null || $.trim(money).length == 0){
                    alert("sorry,必須輸入轉(zhuǎn)賬金額~");
                    return;
                }

                $.ajax({
                    url:'/transferServlet',
                    type:'POST',    //GET
                    async:false,    //或false,是否異步
                    data:{
                        fromCardNo:fromAccount.split(' ')[1],
                        toCardNo:toAccount.split(' ')[1],
                        money:money
                    },
                    timeout:5000,    //超時(shí)時(shí)間
                    dataType:'json', //返回的數(shù)據(jù)格式:json/xml/html/script/jsonp/text
                    success:function(data){
                        if("200" == data.status){
                            alert("轉(zhuǎn)賬成功~~~");
                        }else{
                            alert("轉(zhuǎn)賬失敗~~~,message:" + data.message);
                        }
                    }
                })
            })
        })

        //檢查輸入值是否為整數(shù)
        function checkFormat(obj){
            var reg = /^[0-9]+[0-9]*]*$/;
            if($.trim($(obj).val()).length>0){
                if(!reg.test($(obj).val())){
                    alert("輸入格式錯(cuò)誤!請(qǐng)輸整數(shù)!");
                    $(obj).val("");
                }else{
                    $(obj).val(parseInt($(obj).val()));
                }
            }
        }
    </script>
</head>
<body>


<form>
    <table class="lp-login">
        <tr>
            <td align="right"><span>收款賬戶</span></td>
            <td align="center">
                <input type="text" id="toAccount" value="韓梅梅 6029621011001" disabled></input>
            </td>
        </tr>
        <tr>
            <td align="right"><span>付款賬戶</span></td>
            <td align="center">
                <input type="text" id="fromAccount" value="李大雷 6029621011000" disabled></input>
            </td>
        </tr>
        <tr>
            <td align="right"><span>轉(zhuǎn)賬金額</span></td>
            <td align="center">
                <input type="text" id="money" onblur="checkFormat(this)"></input>
            </td>
        </tr>
        <tr align="center">
            <td colspan="2">
                <a href="javasrcipt:void(0)" rel="external nofollow"  class="submitBtn"><span>轉(zhuǎn) 出</span></a>
            </td>
        </tr>
    </table>
</form>

</body>
</html>

2.5.2.beans.xml

<?xml version="1.0" encoding="UTF-8" ?>
<beans>
    <!--id:唯一標(biāo)識(shí), class類的全路徑-->
    <bean id="accountDao" class="com.lagou.edu.dao.impl.JdbcAccountDaoImpl">
        <property name="ConnectionUtils" ref="connectionUtils"></property>
    </bean>
    <bean id="transferService" class="com.lagou.edu.service.impl.TransferServiceImpl">
        <!--set+ name,將屬性注入-->
        <property name="AccountDao" ref="accountDao"></property>
    </bean>

    <!--配置新增的三個(gè)組件-->
    <!--連接池工具類-->
    <bean id="connectionUtils" class="com.lagou.edu.utils.ConnectionUtils"></bean>

    <!--事務(wù)管理器-->
    <bean id="transactionManager" class="com.lagou.edu.utils.TransactionManager">
        <property name="ConnectionUtils" ref="connectionUtils"></property>
    </bean>

    <!--代理對(duì)象工廠-->
    <bean id="proxyFactory" class="com.lagou.edu.factory.ProxyFactory">
        <property name="TransactionManager" ref="transactionManager"></property>
    </bean>


</beans>

2.5.3.工具類

  • ConnectionUtils
package com.lagou.edu.utils;

import com.alibaba.druid.pool.DruidPooledConnection;

import java.sql.Connection;
import java.sql.SQLException;

/**
 * 獲取數(shù)據(jù)庫連接工具類
 */
public class ConnectionUtils {

/*    private ConnectionUtils(){}

    public static ConnectionUtils getInstance(){
        return new ConnectionUtils();
    }*/

    // 1.單例,保證線程獲取到的連接是同一個(gè)。(每次新new ConnectionUtils,那么里面的threadlocal也是新的,connection也是新的)
    private ThreadLocal<Connection> threadLocal = new ThreadLocal<>();

    public Connection getCurrentThreadConn() throws SQLException {
        Connection connection = threadLocal.get();
        if (connection == null){
            connection = DruidUtils.getInstance().getConnection();
            // 創(chuàng)建完成后一定要設(shè)置回去
            threadLocal.set(connection);
        }
        return connection;
    }

}
  • DruidUtils
package com.lagou.edu.utils;

import com.alibaba.druid.pool.DruidDataSource;


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("123456");

    }

    public static DruidDataSource getInstance() {
        return druidDataSource;
    }

}
  • TransactionManager
package com.lagou.edu.utils;

import java.sql.Connection;
import java.sql.SQLException;

/**
 * 事務(wù)管理器
 */
public class TransactionManager {

    private ConnectionUtils connectionUtils;

    public void setConnectionUtils(ConnectionUtils connectionUtils) {
        this.connectionUtils = connectionUtils;
    }
    /*    private TransactionManager(){}

    private static TransactionManager transactionManager = new TransactionManager();

    public static TransactionManager getInstance(){
        return transactionManager;
    }*/

    public void beginTranscation() throws SQLException {
        Connection conn = connectionUtils.getCurrentThreadConn();
        conn.setAutoCommit(false);
        System.out.println(conn.getAutoCommit() + ":開啟事務(wù)的連接:"+conn);
    }

    public void commit() throws SQLException {
        connectionUtils.getCurrentThreadConn().commit();
        System.out.println("提交的連接:"+connectionUtils.getCurrentThreadConn());
    }

    public void rollback() throws SQLException {
        connectionUtils.getCurrentThreadConn().rollback();
        System.out.println("回滾的連接:"+connectionUtils.getCurrentThreadConn());
    }

}
  • JsonUtils
package com.lagou.edu.utils;

import java.util.List;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * JSON工具類(使用的是jackson實(shí)現(xiàn)的)
 */
public class JsonUtils {

    private static final ObjectMapper MAPPER = new ObjectMapper();

    /**
     * 將對(duì)象轉(zhuǎn)換成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結(jié)果集轉(zhuǎn)化為對(duì)象
     * 
     * @param jsonData json數(shù)據(jù)
     * @param beanType 對(duì)象中的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數(shù)據(jù)轉(zhuǎn)換成pojo對(duì)象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;
    }
    
}

2.5.4.pojo

  • Account
package com.lagou.edu.pojo;


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 +
                '}';
    }
}

2.5.5.工廠類

  • BeanFactory
package com.lagou.edu.factory;

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;

/**
 * 工廠類
 * 作用1:解析xml文件,使用反射技術(shù)實(shí)例化bean對(duì)象,放入map中待用;
 * 作用2:提供接口方法根據(jù)id從map中獲取bean(靜態(tài)方法)
 *
 */
public class BeanFactory {

    private static Map<String,Object> map = new HashMap<>();

   // 0.服務(wù)一啟動(dòng),就將對(duì)象加載至容器中,這里使用靜態(tài)代碼塊
    static{
        // 1.解析對(duì)象配置文件
       InputStream resourceAsStream = BeanFactory.class.getClassLoader().getResourceAsStream("beans.xml");
       try {
           // 使用dom4j技術(shù),首先獲取根節(jié)點(diǎn) <beans>
           Element rootElement = new SAXReader().read(resourceAsStream).getRootElement();
           // 使用xpath,尋找 <bean > 節(jié)點(diǎn)
           List<Element> beanList = rootElement.selectNodes("http://bean");
           for (Element element : beanList) {
               String id = element.attributeValue("id");
               String aClass = element.attributeValue("class");
               // 2.使用反射技術(shù),根據(jù)類的全路徑創(chuàng)建對(duì)象
               Class<?> aClass1 = Class.forName(aClass);
               Object o = aClass1.newInstance();

               // 3.將解析后的對(duì)象放入容器中(map)
               map.put(id,o);
           }

           // 遍歷property標(biāo)簽,將屬性注入,維護(hù)bean之間的依賴關(guān)系
           List<Element> propertyList = rootElement.selectNodes("http://property");
           for (Element element : propertyList) {
               String name = element.attributeValue("name");
               String ref = element.attributeValue("ref");

               // 使用反射技術(shù),設(shè)置屬性
               Element parent = element.getParent();
               String parentId = parent.attributeValue("id");
               Object parentObj = map.get(parentId);
               Method[] methods = parentObj.getClass().getMethods();
               // 獲取所有方法,尋找set+name,將ref設(shè)置
               for (Method method : methods) {
                   if(method.getName().equalsIgnoreCase("set"+name)){
                       Object propertyObj = map.get(ref);
                       method.invoke(parentObj,propertyObj);
                   }
               }
               // 維護(hù)依賴關(guān)系后重新將bean放入map中
               map.put(parentId,parentObj);
           }





       } catch (DocumentException | ClassNotFoundException e) {
           e.printStackTrace();
       } catch (IllegalAccessException e) {
           e.printStackTrace();
       } catch (InstantiationException e) {
           e.printStackTrace();
       } catch (InvocationTargetException e) {
           e.printStackTrace();
       }


   }

    // 3.提供獲取對(duì)象的方法
    public static Object getBean(String id){
        return map.get(id);
    }


}
  • ProxyFactory
package com.lagou.edu.factory;

import com.lagou.edu.utils.TransactionManager;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 *
 * 代理對(duì)象工廠:生成代理對(duì)象的
 */

public class ProxyFactory {


    private TransactionManager transactionManager;

    public void setTransactionManager(TransactionManager transactionManager) {
        this.transactionManager = transactionManager;
    }

     /*private ProxyFactory(){

    }

   private static ProxyFactory proxyFactory = new ProxyFactory();

    public static ProxyFactory getInstance() {
        return proxyFactory;
    }*/



    /**
     * Jdk動(dòng)態(tài)代理
     * @param obj  委托對(duì)象
     * @return   代理對(duì)象
     */
    public Object getJdkProxy(Object obj) {

        // 獲取代理對(duì)象
        return  Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        Object result = null;

                        try{
                            // 開啟事務(wù)(關(guān)閉事務(wù)的自動(dòng)提交)
                            transactionManager.beginTranscation();

                            result = method.invoke(obj,args);

                            // 提交事務(wù)

                            transactionManager.commit();
                        }catch (Exception e) {
                            e.printStackTrace();
                            // 回滾事務(wù)
                            transactionManager.rollback();

                            // 拋出異常便于上層servlet捕獲
                            throw e;

                        }

                        return result;
                    }
                });

    }


    /**
     * 使用cglib動(dòng)態(tài)代理生成代理對(duì)象
     * @param obj 委托對(duì)象
     * @return
     */
    public Object getCglibProxy(Object obj) {
        return  Enhancer.create(obj.getClass(), new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                Object result = null;
                try{
                    // 開啟事務(wù)(關(guān)閉事務(wù)的自動(dòng)提交)
                    transactionManager.beginTranscation();

                    result = method.invoke(obj,objects);

                    // 提交事務(wù)
                    transactionManager.commit();
                }catch (Exception e) {

                    // 回滾事務(wù)
                    transactionManager.rollback();

                    e.printStackTrace();

                    // 拋出異常便于上層servlet捕獲
                    throw e;

                }
                return result;
            }
        });
    }
}

2.5.6.dao層

  • AccountDao
    package com.lagou.edu.dao;
    
    import com.lagou.edu.pojo.Account;
    
    
    public interface AccountDao {
    
        Account queryAccountByCardNo(String cardNo) throws Exception;
    
        int updateAccountByCardNo(Account account) throws Exception;
    }
  • 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;
    
    
    public class JdbcAccountDaoImpl implements AccountDao {
    
        private ConnectionUtils connectionUtils;
    
        public void setConnectionUtils(ConnectionUtils connectionUtils) {
            this.connectionUtils = connectionUtils;
        }
    
    
        public void init() {
            System.out.println("初始化方法.....");
        }
    
        public void destory() {
            System.out.println("銷毀方法......");
        }
    
        @Override
        public Account queryAccountByCardNo(String cardNo) throws Exception {
            //從連接池獲取連接
    //         Connection con = DruidUtils.getInstance().getConnection();
            // 從當(dāng)前線程中獲取連接池對(duì)象
            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(); // 不能將當(dāng)前線程的連接關(guān)閉了,不然同個(gè)線程同個(gè)業(yè)務(wù)中其他更新方法獲取的連接就不是同一個(gè)
    
            return account;
        }
    
        @Override
        public int updateAccountByCardNo(Account account) throws Exception {
    
            // 從連接池獲取連接
            // 改造為:從當(dāng)前線程當(dāng)中獲取綁定的connection連接
    //        Connection con = DruidUtils.getInstance().getConnection();
            // 從當(dāng)前線程中獲取連接池對(duì)象
            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;
        }
    }

2.5.7.service層

  • TransferService
    package com.lagou.edu.service;
    
    
    public interface TransferService {
    
        void transfer(String fromCardNo,String toCardNo,int money) throws Exception;
    }
  • TransferServiceImpl
    package com.lagou.edu.service.impl;
    
    import com.lagou.edu.dao.AccountDao;
    import com.lagou.edu.pojo.Account;
    import com.lagou.edu.service.TransferService;
    import com.lagou.edu.utils.TransactionManager;
    
    
    public class TransferServiceImpl implements TransferService {
    
    //    private AccountDao accountDao = new JdbcAccountDaoImpl();
    
    //     private AccountDao accountDao = (AccountDao) BeanFactory.getBean("accountDao");
    
        // 最佳狀態(tài)
        private AccountDao accountDao;
    
        // 構(gòu)造函數(shù)傳值/set方法傳值
    
        public void setAccountDao(AccountDao accountDao) {
            this.accountDao = accountDao;
        }
    
    
    
        @Override
        public void transfer(String fromCardNo, String toCardNo, int money) throws Exception {
    
    //        try {
    //            // 開啟事務(wù)(設(shè)置自動(dòng)提交關(guān)閉)
    //            TransactionManager.getInstance().beginTranscation();
                Account from = accountDao.queryAccountByCardNo(fromCardNo);
                Account to = accountDao.queryAccountByCardNo(toCardNo);
    
                from.setMoney(from.getMoney()-money);
                to.setMoney(to.getMoney()+money);
    
                accountDao.updateAccountByCardNo(to);
                int c = 1/0;
                accountDao.updateAccountByCardNo(from);
                // 事務(wù)提交
    //            TransactionManager.getInstance().commit();
    //        }catch (Exception e){
    //            // 事務(wù)回滾
    //            TransactionManager.getInstance().rollback();
    //            throw e;
    //        }
    
    
        }
    }

2.5.8.controller層

  • 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;
    
    
    @WebServlet(name="transferServlet",urlPatterns = "/transferServlet")
    public class TransferServlet extends HttpServlet {
    
        // 1. 實(shí)例化service層對(duì)象
    //    private TransferService transferService = new TransferServiceImpl();
    //    private TransferService transferService = (TransferService) BeanFactory.getBean("transferService");
    
        // 從工廠獲取委托對(duì)象,使用代理對(duì)象,主要增加了事務(wù)控制
        private ProxyFactory proxyFactory = (ProxyFactory) BeanFactory.getBean("proxyFactory");
        private TransferService transferService = (TransferService) proxyFactory.getJdkProxy((TransferService) 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 {
    
            // 設(shè)置請(qǐng)求體的字符編碼
            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. 調(diào)用service層方法
                transferService.transfer(fromCardNo,toCardNo,money);
                result.setStatus("200");
            } catch (Exception e) {
                e.printStackTrace();
                result.setStatus("201");
                result.setMessage(e.toString());
            }
    
            // 響應(yīng)
            resp.setContentType("application/json;charset=utf-8");
            resp.getWriter().print(JsonUtils.object2Json(result));
        }
    }

2.5.9.注意事項(xiàng)

com.lagou.edu.utils.ConnectionUtils#getCurrentThreadConn中一定要注意,第一次獲取連接為空時(shí),創(chuàng)建連接后要設(shè)置到當(dāng)前線程中。

if (connection == null){
            connection = DruidUtils.getInstance().getConnection();
            // 創(chuàng)建完成后一定要設(shè)置回去
            threadLocal.set(connection);
        }

總結(jié)

本篇介紹了IOC和AOP的思想,以及通過一個(gè)案例來進(jìn)行解釋說明,希望對(duì)大家有所幫助,更多相關(guān)手寫IOC和AOP代碼內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • MyBatis源碼解析之Transaction事務(wù)模塊

    MyBatis源碼解析之Transaction事務(wù)模塊

    這篇文章主要介紹了MyBatis源碼解析之Transaction事務(wù)模塊,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • Spring鉤子接口匯總分析使用示例

    Spring鉤子接口匯總分析使用示例

    Spring提供了非常多的擴(kuò)展接口,官方將這些接口稱之為鉤子,這些鉤子會(huì)在特定的時(shí)間被回調(diào),以此來增強(qiáng)Spring功能,眾多優(yōu)秀的框架也是通過擴(kuò)展這些接口,來實(shí)現(xiàn)自身特定的功能,如SpringBoot、mybatis等
    2023-01-01
  • IDEA中配置多個(gè)版本的JDK的實(shí)現(xiàn)示例

    IDEA中配置多個(gè)版本的JDK的實(shí)現(xiàn)示例

    IDEA可以配置多個(gè)JDK,根據(jù)需要使用不同版本的,本文就來介紹一下IDEA中配置多個(gè)版本的JDK的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-03-03
  • 詳解Lombok的坑

    詳解Lombok的坑

    這篇文章主要介紹了詳解Lombok的坑,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • 關(guān)于springboot集成swagger及knife4j的增強(qiáng)問題

    關(guān)于springboot集成swagger及knife4j的增強(qiáng)問題

    這篇文章主要介紹了springboot集成swagger以及knife4j的增強(qiáng),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-03-03
  • 什么是Java自旋鎖

    什么是Java自旋鎖

    這篇文章主要介紹了什么是Java自旋鎖,在有些場(chǎng)景中,同步資源的鎖定時(shí)間很短,為了這一小段時(shí)間去切換線程,線程掛起和恢復(fù)現(xiàn)場(chǎng)的花費(fèi)可能會(huì)讓系統(tǒng)得不償失,下面來了解具體內(nèi)容介紹吧
    2022-01-01
  • Hystrix?Dashboard斷路監(jiān)控儀表盤的實(shí)現(xiàn)詳細(xì)介紹

    Hystrix?Dashboard斷路監(jiān)控儀表盤的實(shí)現(xiàn)詳細(xì)介紹

    這篇文章主要介紹了Hystrix?Dashboard斷路監(jiān)控儀表盤的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-09-09
  • SpringBoot數(shù)據(jù)校驗(yàn)功能的實(shí)現(xiàn)

    SpringBoot數(shù)據(jù)校驗(yàn)功能的實(shí)現(xiàn)

    這篇文章主要介紹了SpringBoot數(shù)據(jù)校驗(yàn)功能的實(shí)現(xiàn),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-02-02
  • springmvc mybatis集成配置示例

    springmvc mybatis集成配置示例

    本文主要介紹springmvc+mybatis集成配置,這里提供了實(shí)例代碼,和簡(jiǎn)單說明,有需要的小伙伴可以參考下
    2016-09-09
  • Redisson之分布式鎖原理全面分析

    Redisson之分布式鎖原理全面分析

    這篇文章主要介紹了Redisson分布式鎖原理,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-03-03

最新評(píng)論