# Spring 練習ioc 、aop

来源:https://www.cnblogs.com/leton/archive/2019/11/12/11845740.html
-Advertisement-
Play Games

Spring 練習 通過學習spring的基礎知識,瞭解了Spring為了降低Java開發的複雜性,採取了以下4種關鍵策略: 基於POJO的輕量級和最小侵入性編程; 通過依賴註入和麵向介面實現松耦合; 基於切麵和慣例進行聲明式編程; 通過切麵和模板減少樣板式代碼。 下麵將做一個spring的練習de ...


Spring 練習

通過學習spring的基礎知識,瞭解了Spring為了降低Java開發的複雜性,採取了以下4種關鍵策略:

  • 基於POJO的輕量級和最小侵入性編程;
  • 通過依賴註入和麵向介面實現松耦合;
  • 基於切麵和慣例進行聲明式編程;
  • 通過切麵和模板減少樣板式代碼。

下麵將做一個spring的練習demo,進一步熟悉spring的ioc和aop的使用方法,以及使用spring模板的優點。

Demo說明

將構建一個用戶更刪改查的項目,其中對項目進行分層,通過spring的ioc的特性進行依賴註入。並使用aop特性增加日誌操作。資料庫操作使用了spring的jdbcTemplate簡化資料庫操作。

項目結構

創建一個maven項目,並構建如下文件夾

--springdemo
    --src
        --main
            --java
                --aop
                --conf
                --dao
                --service
                --entity
            --resources
        --test
            --java
                --service
    pom.xml

使用到的依賴有spring,slf4j,log4j,mysql-connector等。

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.tong</groupId>
  <artifactId>spring-demo</artifactId>
  <version>1.0-SNAPSHOT</version>

  <name>spring-demo</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>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
      <spring.version>4.3.2.RELEASE</spring.version>
      <slf4j.version>1.7.24</slf4j.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>
      <!-- spring 核心 -->
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>${spring.version}</version>
      </dependency>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-beans</artifactId>
          <version>${spring.version}</version>
      </dependency>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-core</artifactId>
          <version>${spring.version}</version>
      </dependency>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context-support</artifactId>
          <version>${spring.version}</version>
      </dependency>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-expression</artifactId>
          <version>${spring.version}</version>
      </dependency>
      <!-- spring aop -->
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-aop</artifactId>
          <version>${spring.version}</version>
      </dependency>
      <dependency>
          <groupId>org.aspectj</groupId>
          <artifactId>aspectjweaver</artifactId>
          <version>1.8.8</version>
      </dependency>
      <!-- spring junit -->
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-test</artifactId>
          <version>${spring.version}</version>
      </dependency>
      <!-- spring jdbc -->
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-jdbc</artifactId>
          <version>${spring.version}</version>
      </dependency>
      <!-- mysql 驅動 -->
      <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>5.1.22</version>
      </dependency>
      <!-- slf4j -->
      <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-api</artifactId>
          <version>${slf4j.version}</version>
      </dependency>
      <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-log4j12</artifactId>
          <version>${slf4j.version}</version>
      </dependency>
  </dependencies>

  <build>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-jar-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
        <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
        <plugin>
          <artifactId>maven-site-plugin</artifactId>
          <version>3.7.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-project-info-reports-plugin</artifactId>
          <version>3.0.0</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

項目分層說明

entity層

entity層即包含User.jave實體類,是一個POJO類,僅包含屬性,構造器和setter,getter方法。

如下:

package com.tong.entity;

/**
 * User實體類
 *
 * @author tongl
 * @version 1.0 11/11/2019
 */
public class User {
    Integer id;
    String name;
    String sex;
    Integer age;

    public User() {
    }

    public User(Integer id, String name, String sex, Integer age) {
        this.id = id;
        this.name = name;
        this.sex = sex;
        this.age = age;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" + "id=" + this.id + ", name='" + this.name + '\'' + ", sex='" + this.sex + '\'' + ", age=" + this.age + '}';
    }
}

dao層

DAO層主要是做數據持久層的工作,負責與資料庫進行聯絡的一些任務都封裝在此,DAO層的設計首先是設計DAO的介面,然後在Spring的配置文件中定義此介面的實現類,然後就可在模塊中調用此介面來進行數據業務的處理,而不用關心此介面的具體實現類是哪個類,顯得結構非常清晰,DAO層的數據源配置,以及有關資料庫連接的參數都在Spring的配置文件中進行配置。

包括介面和實現。

UserDao.java

package com.tong.dao;

import com.tong.entity.User;

/**
 * 持久化數據層介面
 *
 * @author tongl
 */
public interface UserDao {


    /**
     * 新增用戶
     *
     * @param user 用戶
     */
    void addUser(User user);

    /**
     * 根據id刪除用戶
     *
     * @param id id
     */
    void deleteUser(int id);

    /**
     * 根據id查找用戶
     *
     * @param id 用戶id
     */
    User getUser(int id);

    /**
     * 更新用戶信息
     *
     * @param user 用戶
     */
    void updateUser(User user);


}

UserDaoImpl.java

package com.tong.dao.impl;

import com.tong.dao.UserDao;
import com.tong.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
 * 持久化數據層實現
 *
 * @author tongl
 */
@Repository
public class UserDaoImpl implements UserDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    /**
     * 新增用戶
     *
     * @param user 用戶
     */
    @Override
    public void addUser(User user) {
        jdbcTemplate.update("insert into t_user values(?,?,?,?)", user.getId(), user.getName(), user.getSex(), user.getAge());
    }

    /**
     * 根據id刪除用戶
     *
     * @param id id
     */
    @Override
    public void deleteUser(int id) {
        jdbcTemplate.update("delete from t_user where id = ?", id);
    }

    /**
     * 根據id查找用戶
     *
     * @param id 用戶id
     * @return user
     */
    @Override
    public User getUser(int id) {
        List<User> users = jdbcTemplate.query("select * from t_user where id = ?",
                new BeanPropertyRowMapper<User>(User.class), id);
        if (users != null && users.size() > 0) {
            return users.get(0);
        }
        return null;
    }

    /**
     * 更新用戶
     *
     * @param user 用戶
     */
    @Override
    public void updateUser(User user) {
        jdbcTemplate.update("update t_user set name = ?, age = ?, sex = ? where id = ?",
                user.getName(), user.getAge(), user.getSex(), user.getId());
    }

}

service層

Service層主要負責業務模塊的邏輯應用設計。同樣是首先設計介面,再設計其實現的類,接著再Spring的配置文件中配置其實現的關聯。這樣我們就可以在應用中調用Service介面來進行業務處理。Service層的業務實現,具體要調用到已定義的DAO層的介面,封裝Service層的業務邏輯有利於通用的業務邏輯的獨立性和重覆利用性,程式顯得非常簡潔。

UserService.java

package com.tong.service;

import com.tong.entity.User;

/**
 * 服務層介面
 *
 * @author tongl
 * @version 1.0 10/10/2019
 */
public interface UserService {

    /**
     * 新增修改用戶
     *
     * @param user 用戶
     */
    void saveUser(User user);

    /**
     * 刪除用戶
     *
     * @param id 用戶id
     */
    void deleteUser(int id);
}

UserServiceImpl.java

package com.tong.service.impl;

import com.tong.dao.UserDao;
import com.tong.entity.User;
import com.tong.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * 服務層實現
 *
 * @author tongl
 */
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);

    /**
     * 添加修改用戶
     *
     * @param user 用戶
     */
    @Override
    public void saveUser(User user) {
        Integer id = user.getId();
        User u = userDao.getUser(id);
        if (u == null) {
            // 如果查詢user為空,那麼新增用戶
            userDao.addUser(user);
            logger.info("新增用戶:{}", user);
        } else {
            // 如果user不為空,那麼更改用戶
            userDao.updateUser(user);
            logger.info("修改用戶信息:{}", user);
        }
    }

    /**
     * 刪除用戶
     *
     * @param id 用戶id
     */
    @Override
    public void deleteUser(int id) {

        User user = userDao.getUser(id);
        userDao.deleteUser(id);

        logger.info("刪除用戶:{}", user);
    }

}

aop層

實現日誌切麵

Log.java

package com.tong.aop;

import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;

/**
 * 日誌服務
 *
 * @author tongl
 */
@Component
@ComponentScan(basePackages = {"com.fiberhome"})
@Aspect
@EnableAspectJAutoProxy
public class Log {
    Logger logger = LoggerFactory.getLogger(Log.class);

    /**
     * 配置後置通知:新增/修改用戶列印日誌
     */
    @AfterReturning("execution(* com.tong.service.*.saveUser(..))")
    public void addLog() {
        logger.info("添加/修改用戶操作-日誌記錄");
    }

    /**
     * 配置後置通知:刪除用戶列印日誌
     */
    @AfterReturning("execution(* com.tong.service.*.deleteUser(..))")
    public void deleteLog() {
        logger.info("刪除用戶操作-日誌記錄");
    }
}

config

本項目使用Java配置方式,這裡是Java配置文件。

DataConfig.java

package com.tong.conf;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.*;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;


@Configuration
@ComponentScan(basePackages = {"com.tong"})
@PropertySource(value = "classpath:db.properties")
@Scope("singleton")
public class DataConfig {

    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;

    /**
     * 創建連接池
     *
     * @return dataSource
     */
    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(driver);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }

    @Bean
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }

    @Bean
    public JdbcTemplate getJdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }

}

測試類

UserServiceTest

package com.tong.service;

import com.tong.conf.DataConfig;
import com.tong.entity.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;


/**
 * 用戶服務測試類
 * @author tongl
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {DataConfig.class})
public class UserServiceTest {

    @Autowired
    private UserService userService;

    /**
     * 添加用戶測試
     */
    @Test
    public void testAddUser(){
        User user = new User(1001,"張三","男",17);
        User user2 = new User(1001,"張三","男",20);
        User user3 = new User(1012,"張四","男",18);
        //System.out.println(user);
        userService.saveUser(user);
        userService.saveUser(user2);
        userService.saveUser(user3);
    }

    /**
     * 刪除用戶測試
     */
    @Test
    public void testDeleteUser(){

        userService.deleteUser(1001);
        userService.deleteUser(1002);
    }
}

resources文件

db.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///user?useUnicode=true&characterEncoding=utf-8
jdbc.username=root
jdbc.password=root

log4j.properties

### 設置###
log4j.rootLogger = info,stdout,D,E

### 輸出信息到控制抬 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n

### 輸出DEBUG 級別以上的日誌到logs/debug.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = logs/debug.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG 
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

### 輸出ERROR 級別以上的日誌到logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =logs/error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR 
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

源代碼

spring-demo


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 'Specifying a namespace in include() without providing an app_name ’ 從include()函數可以看出來,這個函數有兩個參數,一個arg,一個namespace,我在代碼中也是兩個參數,但是異常中提示了,沒有提供app_name,還 ...
  • Go沒有像Java那樣的異常機制,它不能拋出異常,而是使用了 panic和recover機制。一定要記住,應當把它作為最後的手段來使用,也就是說,我們的代碼中應當沒有,或者很少有panic這樣的東西。 ...
  • 本文收錄在Python從入門到精通系列文章系列 學完前面的幾個章節後,博主覺得有必要在這裡帶大家做一些練習來鞏固之前所學的知識,雖然迄今為止我們學習的內容只是Python的冰山一角,但是這些內容已經足夠我們來構建程式中的邏輯。對於編程語言的初學者來說,在學習了Python的核心語言元素(變數、類型、 ...
  • 下載中間件 簡介 下載器,無法執行js代碼,本身不支持代理 下載中間件用來hooks進Scrapy的request/response處理過程的框架,一個輕量級的底層系統,用來全局修改scrapy的request和response scrapy框架中的下載中間件,是實現了特殊方法的類,scrapy系統 ...
  • 你好,我是彤哥,本篇是netty系列的第一篇。 歡迎來我的公從號 彤哥讀源碼 系統地學習 源碼&架構 的知識。 簡介 本文主要講述netty系列的整體規劃,並調查一下大家喜歡的學習方式。 知識點 netty系列彤哥準備分成三個大的模塊來完成: 入門篇 入門篇主要講述一些必備的基礎知識,例如IO的五種 ...
  • 一、安裝activeMQ ​ 安裝步驟參照網上教程,本文不做介紹 二、修改activeMQ配置文件 ​ broker新增配置信息 schedulerSupport="true" 三、創建SpringBoot工程 ]() 1. 配置ActiveMQ工廠信息,信任包必須配置否則會報錯 2. 消息實體類 ...
  • 1、冒泡排序 在要排序的一組數中,對當前還未排好的序列,從前往後對相鄰的兩個數依次進行比較和調整,讓較大的數往下沉,較小的往上冒。即,每當兩相鄰的數比較後發現它們的排序與排序要求相反時,就將它們互換。 1 // 升序 2 $arr=[1,43,54,62,21,66,32,78,36,76,39]; ...
  • 由於我本地的mysql版本比較低,最近想著要升級一下mysql版本,鑒於docker容器的火熱,就想著在本地裝個docker環境,然後下載最新版的mysql鏡像,完成mysql8.0的安裝。電腦是windows 10版本。 一 啟用Hyper V 打開控制面板 程式 啟用或關閉windows功能,勾 ...
一周排行
    -Advertisement-
    Play Games
  • 概述:在C#中,++i和i++都是自增運算符,其中++i先增加值再返回,而i++先返回值再增加。應用場景根據需求選擇,首碼適合先增後用,尾碼適合先用後增。詳細示例提供清晰的代碼演示這兩者的操作時機和實際應用。 在C#中,++i 和 i++ 都是自增運算符,但它們在操作上有細微的差異,主要體現在操作的 ...
  • 上次發佈了:Taurus.MVC 性能壓力測試(ap 壓測 和 linux 下wrk 壓測):.NET Core 版本,今天計劃準備壓測一下 .NET 版本,來測試並記錄一下 Taurus.MVC 框架在 .NET 版本的性能,以便後續持續優化改進。 為了方便對比,本文章的電腦環境和測試思路,儘量和... ...
  • .NET WebAPI作為一種構建RESTful服務的強大工具,為開發者提供了便捷的方式來定義、處理HTTP請求並返迴響應。在設計API介面時,正確地接收和解析客戶端發送的數據至關重要。.NET WebAPI提供了一系列特性,如[FromRoute]、[FromQuery]和[FromBody],用 ...
  • 原因:我之所以想做這個項目,是因為在之前查找關於C#/WPF相關資料時,我發現講解圖像濾鏡的資源非常稀缺。此外,我註意到許多現有的開源庫主要基於CPU進行圖像渲染。這種方式在處理大量圖像時,會導致CPU的渲染負擔過重。因此,我將在下文中介紹如何通過GPU渲染來有效實現圖像的各種濾鏡效果。 生成的效果 ...
  • 引言 上一章我們介紹了在xUnit單元測試中用xUnit.DependencyInject來使用依賴註入,上一章我們的Sample.Repository倉儲層有一個批量註入的介面沒有做單元測試,今天用這個示例來演示一下如何用Bogus創建模擬數據 ,和 EFCore 的種子數據生成 Bogus 的優 ...
  • 一、前言 在自己的項目中,涉及到實時心率曲線的繪製,項目上的曲線繪製,一般很難找到能直接用的第三方庫,而且有些還是定製化的功能,所以還是自己繪製比較方便。很多人一聽到自己畫就害怕,感覺很難,今天就分享一個完整的實時心率數據繪製心率曲線圖的例子;之前的博客也分享給DrawingVisual繪製曲線的方 ...
  • 如果你在自定義的 Main 方法中直接使用 App 類並啟動應用程式,但發現 App.xaml 中定義的資源沒有被正確載入,那麼問題可能在於如何正確配置 App.xaml 與你的 App 類的交互。 確保 App.xaml 文件中的 x:Class 屬性正確指向你的 App 類。這樣,當你創建 Ap ...
  • 一:背景 1. 講故事 上個月有個朋友在微信上找到我,說他們的軟體在客戶那邊隔幾天就要崩潰一次,一直都沒有找到原因,讓我幫忙看下怎麼回事,確實工控類的軟體環境複雜難搞,朋友手上有一個崩潰的dump,剛好丟給我來分析一下。 二:WinDbg分析 1. 程式為什麼會崩潰 windbg 有一個厲害之處在於 ...
  • 前言 .NET生態中有許多依賴註入容器。在大多數情況下,微軟提供的內置容器在易用性和性能方面都非常優秀。外加ASP.NET Core預設使用內置容器,使用很方便。 但是筆者在使用中一直有一個頭疼的問題:服務工廠無法提供請求的服務類型相關的信息。這在一般情況下並沒有影響,但是內置容器支持註冊開放泛型服 ...
  • 一、前言 在項目開發過程中,DataGrid是經常使用到的一個數據展示控制項,而通常表格的最後一列是作為操作列存在,比如會有編輯、刪除等功能按鈕。但WPF的原始DataGrid中,預設只支持固定左側列,這跟大家習慣性操作列放最後不符,今天就來介紹一種簡單的方式實現固定右側列。(這裡的實現方式參考的大佬 ...