国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Spring02-Spring注解的使用、基于注解的IOC、純注解配置、整合Junit、AOP入門、基于配置文件的AOP、切入點表達式、基于配置的文件環(huán)繞通知

這篇具有很好參考價值的文章主要介紹了Spring02-Spring注解的使用、基于注解的IOC、純注解配置、整合Junit、AOP入門、基于配置文件的AOP、切入點表達式、基于配置的文件環(huán)繞通知。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

Spring注解的使用

一、項目注解 和 XML 的選擇問題

  • 學習基于注解的 IOC 配置,即注解配置 和 XML 配置要實現的功能都是一樣的,都是要降低程序間的耦合。只是配置的形式不一樣。
  • 關于實際的開發(fā)中到底使用xml還是注解,每家公司有著不同的使用習慣 , 所以這兩種配置方式我們都需要掌握。
  • 把 Spring 的 xml 配置內容改為使用注解逐步實現

二、用于創(chuàng)建對象的注解

1、注解介紹

  • @Component
  • @Repository
  • @Service
  • @Controller
注解 說明
@Component 使用在類上用于實例化Bean
@Controller 使用在web層類上用于實例化Bean
@Service 使用在service層類上用于實例化Bean
@Repository 使用在dao層類上用于實例化Bean

2、注意問題

  • 使用注解開發(fā),需要在application.xml中配置組件掃描。
  • 主鍵掃描的作用:指定那個包及其子包的Bean需要掃描以便識別使用注解配置的類、字段和方法。
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    <context:component-scan base-package="com.etime"></context:component-scan>
</beans>

3、編寫示例代碼

(1)使用@Component或@Repository標識UserDaoImpl需要Spring進行實例化。
  • UserDao接口
package com.etime.dao;
public interface UserDao {
    void show();
}
  • UserDaoImpl實現類

package com.etime.dao.impl;
package com.etime.dao.impl;

import com.etime.dao.UserDao;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;

//@Component("ud")
@Repository("ud")
public class UserDaoImpl implements UserDao {
    @Override
    public void show() {
        System.out.println("這是userDao的方法");
    }
}
(2)使用@Component或@Service標識UserServiceImpl需要Spring進行實例化
  • UserService接口
package com.etime.service;

public interface UserService {
    void show();
}
  • UserServiceImpl
package com.etime.service.impl;

import com.etime.service.UserService;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

//@Component("us")
@Service("us")
public class UserServiceImpl implements UserService {
    @Override
    public void show() {
        System.out.println("這是userService的方法");
    }
}
(3)測試
    @Test
    public void t07() {
        ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
        UserDao userDao = (UserDao) context.getBean("ud");
        userDao.show();

        UserService userService = (UserService) context.getBean("us");
        userService.show();
    }

三、基于注入數據的注解

(1)注解介紹

  • @Value
  • @Resource
  • @Autowrited
  • Qualifier
注解 說明
@Value 注入普通屬性
@Autowired 自動按照類型注入。當使用注解注入屬性時,set 方法可以省略。它只能注入其他 bean 類型。當有多個類型匹配時,使用要注入的對象變量名稱作為 bean 的 id,在 spring 容器查找,找到了也可以注入成功。找不到就報錯。 如果IOC容器當中有多個接口得實現類, 首先根據類型自動裝配, 然后再根據名稱自動裝配。
@Qualifier 結合@Autowired一起使用用于根據名稱進行依賴注入
@Resource 相當于@Autowired+@Qualifier,按照名稱進行注入,是java提供的,不是框架提供的

(2)使用@Value進行字符串的注入

@Repository("userDao")
public class UserDaoImpl implements UserDao {
    @Value("字符串")
    private String str;
    public void addUser() {
        System.out.println(str);
        System.out.println("開始新增用戶了");
    }
}

(3)使用@Autowired或者@Autowired+@Qulifier或者@Resource進行userDao的注入

第一種:
package com.etime.service.impl;

import com.etime.dao.UserDao;
import com.etime.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

//@Component("us")
@Service("us")
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    @Override
    public void show() {
        userDao.show();
    }
}

第二種:
package com.etime.service.impl;

import com.etime.dao.UserDao;
import com.etime.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

//@Component("us")
@Service("us")
public class UserServiceImpl implements UserService {

    @Autowired
    @Qualifier("ud")
    private UserDao userDao;

    @Override
    public void show() {
        userDao.show();
    }
}

第三種:
package com.etime.service.impl;

import com.etime.dao.UserDao;
import com.etime.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

//@Component("us")
@Service("us")
public class UserServiceImpl implements UserService {

    @Resource(name = "ud")
    private UserDao userDao;

    @Override
    public void show() {
        userDao.show();
    }
}

(4)測試

   @Test
    public void t07() {
        ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
        /*UserDao userDao = (UserDao) context.getBean("ud");
        userDao.show();*/
        UserService userService = (UserService) context.getBean("us");
        userService.show();
    }

四、和生命周期相關的注解

(1)注解介紹

  • @PostConstruct
  • @PreDestroy
注解 說明
@PostConstruct 使用在方法上標注該方法是Bean的初始化方法
@PreDestroy 使用在方法上標注該方法是Bean的銷毀方法

(2) 使用注解初始化方法、注銷方法

  • 這兩個注解是java提供的
package com.etime.dao.impl;

import com.etime.dao.UserDao;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

//@Component("ud")
@Repository("ud")
public class UserDaoImpl implements UserDao {

    @PostConstruct
    public void init(){
        System.out.println("userDao被初始化了");
    }

    @Override
    public void show() {
        System.out.println("這是userDao的方法");
    }

    @PreDestroy
    public void destroy(){
        System.out.println("userDao被銷毀了");
    }
}

(3)測試

@Test
    public void t08() {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
        UserDao userDao = (UserDao) context.getBean("ud");
        userDao.show();
        context.close();
    }

五、用戶改變作用范圍的注解:@Scope

1、注解介紹

  • 使用@Scope標注Bean的范圍
注解 說明
@Scope 標注Bean的作用范圍,scope取值singleton prototype request session globalsession

Spring基于注解的IOC

1、 構建maven工程,添加框架技術依賴

<dependencies>
    <!--導入spring的context坐標-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <!--導入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.47</version>
    </dependency>
    <!--導入C3P0連接池-->
    <dependency>
        <groupId>com.mchange</groupId>
        <artifactId>c3p0</artifactId>
        <version>0.9.5.2</version>
    </dependency>
    <!--導入junit單元測試-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
</dependencies>

2、創(chuàng)建數據庫及數據表,并創(chuàng)建實體類

  • 實體類
package com.etime.entity;

public class User {

    private int id;
    private String name;
    private String gender;

    public User() {
    }

    public User(int id, String name, String gender) {
        this.id = id;
        this.name = name;
        this.gender = gender;
    }

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

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

3、注解配置管理的資源

(1)Dao層

  • UseDaor接口
package com.etime.dao;
import com.etime.entity.User;
import java.util.List;
public interface UserDao {
    List<User> getAllUser();
}
  • USerDaoImpl實現類
package com.etime.dao.impl;
import com.etime.dao.UserDao;
import com.etime.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;
@Repository("ud")
public class UserDaoImpl implements UserDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public List<User> getAllUser() {
        List<User> list = null;
        String sql = "select * from user";
        list = jdbcTemplate.query(sql,new BeanPropertyRowMapper<>(User.class));
        return list;
    }
}

(2)Service層

  • UserService接口
package com.etime.service;
import com.etime.entity.User;
import java.util.List;
public interface UserService {
    List<User> getAllUser();
}

  • UseServiceImpl實現類
package com.etime.service.impl;
import com.etime.dao.UserDao;
import com.etime.entity.User;
import com.etime.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service("us")
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    @Override
    public List<User> getAllUser() {
        return userDao.getAllUser();
    }
}

4、配置文件并開啟對注解的支持并配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">

    <!--配置掃描-->
    <context:component-scan base-package="com.etime"/>

    <!--讀取properties配置文件-->
    <context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
    <bean id="ds" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driver}"></property>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

    <!--JdbcTemplate對象的創(chuàng)建-->
    <bean id="jt" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="ds"></property>
    </bean>
</beans>

5、編寫測試代碼

    @Test
    public void t09() {
        ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
        UserService userService = (UserService) context.getBean("us");
        List<User> list = userService.getAllUser();
        System.out.println(list);
    }

Spring純注解配置

1、注解IOC案例待改造的問題

(1)問題引入

  • 上面的注解還不能全部替代xml配置文件,還需要使用注解替代

(2)注解替代的配置

  • 非自定義的Bean的配置:@Bean
  • 加載properties文件的配置:context:property-placeholder
  • 組件掃描的配置:context:component-scan
  • 引入其他文件:@import
  • 替代Spring核心配置文件:@Configuration,@ComponentScan,@Import

2、新注解說明

注解 說明
@Configuration 用于指定當前類是一個 Spring 配置類,當創(chuàng)建容器時會從該類上加載注解,作用等價于applicationContext.xml 配置文件。
@ComponentScan 用于指定 Spring在初始化容器時要掃描的包。 作用和在 Spring 的 xml 配置文件中的 <context:component-scan base-package=“com.offcn”/>一樣
@Bean 使用在方法上,標注將該方法的返回值存儲到 Spring容器中。 id的值默認是方法的名稱, 可以自定義id的值
@PropertySource 用于加載xxx.properties 文件中的配置 結合@Value(“${}”) 取配置文件的值。
@Import 用于導入其他配置類

2、編寫示例代碼

(1)創(chuàng)建db.properties文件

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///spring
jdbc.username=root
jdbc.password=111

(2)@PropertySource,@value,@Bean的使用:

package com.etime.util;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.sql.DataSource;
import java.beans.PropertyVetoException;

/**
 * 做數據庫相關配置
 * 1、讀取properties文件內容
 * 2、根據讀取的內容生成連接池對象
 * 3、根據連接池對象獲取JdbcTemplate對象
 */

@PropertySource("classpath:jdbc.properties")
public class DataSourceConfig {
    @Value("${jdbc.driver}")
    private String driverClass;

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

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

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

    public DataSource getDataSource() throws PropertyVetoException {
        ComboPooledDataSource ds = new ComboPooledDataSource();
        ds.setDriverClass(driverClass);
        ds.setJdbcUrl(url);
        ds.setUser(username);
        ds.setPassword(password);
        return ds;
    }

    @Bean(name = "jdbcTemplate")
    public JdbcTemplate getJdbcTemplate() throws PropertyVetoException {
        return new JdbcTemplate(getDataSource());
    }
}

(3)@Configuration,@ComponentScan,@Import的使用

package com.etime.util;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
@Import(DataSourceConfig.class)
@ComponentScan("com.etime")
public class SpringConfig {
}

3、通過注解獲取容器

    @Test
    public void t10() {
        ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
        UserService userService = (UserService) context.getBean("us");
        List<User> list = userService.getAllUser();
        System.out.println(list);
    }

Spring整合Junit

1、Spring整合Junit介紹

  • Spring整合Junit單元測試在學習階段、開發(fā)階段是經常使用的。
  • 如果開發(fā)過程當中完全不使用該技術點,不影響開發(fā)效果,可能會影響開發(fā)進度,為提高開發(fā)效率,避免重復性代碼,Spring整合Junit單元測試務必要掌握,在使用Spring框架開發(fā)時,我們也推薦使用整合Junit后進行測試

2、IOC測試類中的問題和解決思路

(1)問題引出

  • 在測試類中,每個測試方法都有以下兩行代碼:
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml");

(2)解決思路

  • 這兩行代碼的作用是獲取容器,如果不寫的話,直接會提示空指針異常。所以又不能輕易刪掉。
  • 故,引出Spring整合Junit

3、注解介紹

注解 說明
@RunWith 替換原有運行器
@ContextConfiguration 指定 Spring 配置文件的位置
@Autowired 給測試類中的變量注入數據

4、 整合Junit配置步驟

(1) 添加技術依賴

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>${spring.version}</version>
</dependency>

(2)使用注解完成容器的加載

@RunWith :替換原有運行器

@ContextConfiguration:指定 Spring 配置文件的位置

@Autowired:給測試類中的變量注入數據

package com.etime.test;

import com.etime.entity.Account;
import com.etime.dao.UserDao;
import com.etime.entity.User;
import com.etime.service.AccountService;
import com.etime.service.UserService;
import com.etime.util.SpringConfig;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.List;

@RunWith(SpringJUnit4ClassRunner.class)
//加載Spring的配置類,生成容器對象
@ContextConfiguration(classes = {SpringConfig.class})
public class SpringTest {

    @Autowired
    private ApplicationContext context;

    @Test
    public void t11() {
        UserService userService = (UserService) context.getBean("us");
        List<User> list = userService.getAllUser();
        System.out.println(list);
    }
}

SpringAOP入門

1、什么是 AOP

  • AOP 為 Aspect Oriented Programming 的縮寫。
  • 意思為面向切面編程,通過 預編譯方式 和 運行期動態(tài)代理實現程序功能的統一維護的一種技術

2、AOP編程思想

  • 面向切面編程(AOP)是一種編程的思想,是 OOP 的延續(xù),是軟件開發(fā)中的一個熱點,也是Spring框架中的一個重要內容,是 函數式編程的一種衍生泛型。
  • 利用 AOP 可以對業(yè)務邏輯的各個部分進行隔離,,從而使得業(yè)務邏輯各部分之間的耦合度降低,提高程序的可重用性,同時提高了開發(fā)的效率。
  • AOP 使用場景
    • 事務管理
    • 權限校驗
    • 日志記錄
    • 性能監(jiān)控

3、SPring中的常用術語

(1)Joinpoint

  • Joinpoint(連接點):所謂連接點是指那些被攔截到的點。
    • 在spring中,這些點指的是方法,因為spring只支持方法類型的連接點

(2)Pointcut

  • Pointcut(切入點):所謂切入點是指我們要對哪些 Joinpoint 進行攔截的定義。
  • 真正被增強的方法

(3)Advice

  • Advice(通知/ 增強):所謂通知是指攔截到 Joinpoint 之后所要做的事情就是通知。

4、面試問題

(1)通知的類型

  • 前置通知,正常返回通知,異常通知,最終通知,環(huán)繞通知。

(2)Introduction

  • Introduction(引介,了解): 引介是一種特殊的通知在不修改類代碼的前提下, Introduction 可以在運行期為類動態(tài)地添加一些方 法或 Field。

(3)Target

  • Target(目標對象):代理的目標對象

(4)Proxy

  • Proxy (代理):一個類被 AOP 織入增強后,就產生一個結果代理類

(5)Weaving

  • Weaving(織入):是指把增強應用到目標對象來創(chuàng)建新的代理對象的過程。
  • spring采用動態(tài)代理織入,而AspectJ采用編譯期織入和類裝載期織入

(5)Aspect

  • Aspect(切面):是切入點和通知(引介)的結合,描述了 增強具體應用的位置。

5、AOP 的作用及優(yōu)勢

(1)作用

  • 在程序運行期間,在不修改源碼的情況下對方法進行功能增強。體現了java語言的動態(tài)性【反射】

(2)優(yōu)勢

  • 減少重復代碼,提高開發(fā)效率,并且便于維護

Spring實現轉賬案例

一、實現步驟

1、搭建一個轉賬的業(yè)務環(huán)境,準備所需資源,數據庫表以及實體類
2、持久層具體實現使用DBUtils 方便操作連接對象,管理事務
3、搭建業(yè)務層,完成對持久層的調用
4、演示轉賬測試用例,在沒有遇到異常情況下成功轉賬,在轉賬過程當中遇到意外情況,損失了數據的一致性,從而引出事務。

二、編寫代碼示例

1、準備Account表以及對應的實體bean

public class Account implements Serializable {
    private Integer id;
    private String name;
    private double money;

    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 double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }

    @Override
    public String toString() {
        return "Account{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", money=" + money +
                '}';
    }
}

2、創(chuàng)建AccountDao接口以及對應的實現類

  • AccountDao接口
package com.etime.dao;

import com.etime.entity.Account;

public interface AccountDao {
    public Account getByName(String name);
    public int update(Account account);
}
  • AccountDaoImpl實現類
package com.etime.dao.impl;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.etime.dao.AccountDao;
import com.etime.entity.Account;
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.sql.SQLException;

@Repository("accountDao")
public class AccountDaoImpl implements AccountDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public Account getByName(String name) {
        String sql ="select *from account where name =? ";
        return jdbcTemplate.queryForObject(sql,new BeanPropertyRowMapper<Account>(Account.class),name);
    }

    @Override
    public int update(Account account) {
        String sql ="update account set money =? where name =? ";
        return jdbcTemplate.update(sql,account.getMoney(),account.getName());
    }
}

3、創(chuàng)建AccountService接口以及對應的實現類

package com.etime.service;

public interface AccountService {
    public void transfer(String sourceAccountName,String targetAccountName,double money);
}
package com.etime.service.impl;

import com.etime.dao.AccountDao;
import com.etime.dao.impl.AccountDaoImpl;
import com.etime.entity.Account;
import com.etime.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service("accountService")
public class AccountServiceImpl implements AccountService {

    @Autowired
    private AccountDao accountDao;

    @Override
    public void transfer(String sourceAccountName, String targetAccountName, double money) {
        //收錢的
        Account tAccount = accountDao.getByName(targetAccountName);
        tAccount.setMoney(tAccount.getMoney()+money);
        int rows2 = accountDao.update(tAccount);
        System.out.println("收錢的:"+rows2);

        //給錢的
        Account sAccount = accountDao.getByName(sourceAccountName);
        sAccount.setMoney(sAccount.getMoney()-money);
        int rows1 = accountDao.update(sAccount);
        System.out.println("給錢的:"+rows1);
    }
}

4、測試轉賬業(yè)務

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {DataSourceConfiguration.class})
public class SpringTest {

    @Autowired
    private ApplicationContext applicationContext;

    @Test
    public void t01(){
        AccountService us = (AccountService)applicationContext.getBean("accountService");
        us.transfer("aaa","bbb",500);
    }

5、測試沒有事務正常情況和異常情況轉賬結果

  • 沒有遇到異常情況,轉賬結果正常。aaa賬戶減少500元,bbb賬戶增加500元

  • 模擬異常情況轉賬結果aaa向bbb轉賬1000

6、編寫ConnectionUtils工具類管理數據庫連接

  • 轉賬過程,由于遇到異常情況,轉賬損失了數據的一致性,加入事務控制。

  • 事務要么同時成功,事務提交;要么都同時失敗,事務回滾;要保證咋同一個事務當中進行操作,那么必須保證同一個連接對象。

  • 如何保證持久層和業(yè)務層使用同一個連接對象呢?

    • 引入ThreadLocal對象,該對象的特點,對象提供的存,取,移除的常用方法。
  • ConnectionUtils 工具類提供的管理連接的方法,就能保證持久層以及業(yè)務層獲得相同的連接對象,保證在同一個事務當中進行操作文章來源地址http://www.zghlxwxcb.cn/news/detail-437879.html

package com.etime.util;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.sql.Connection;

@Component
public class ConnectionUtil {
    private ThreadLocal<Connection> tl = new ThreadLocal<Connection>();

    @Autowired
    private JdbcTemplate jdbcTemplate;

    /**
     * 獲取當前線程上的連接
     * @return
     */
    public Connection getThreadConnection() {
        try{
            //1.先從ThreadLocal上獲取
            Connection connection = tl.get();
            //2.判斷當前線程上是否有連接
            if (connection == null) {
                //3.從jdbcTemplate中獲取一個連接,并且存入ThreadLocal中
                connection = jdbcTemplate.getDataSource().getConnection();
                tl.set(connection);
            }
            //4.返回當前線程上的連接
            return connection;
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }
    /**
     * 把連接和線程解綁
     */
    public void removeConnection(){
        tl.remove();
    }
}

7、編寫事務管理工具類TransactionManager

  • TransactionManager 是管理事務的工具類,它主要定義了 和事務相關的方法。
    • 例如:例如:事務的開啟,事務的提交,事務的回滾操作等
  • 該工具類目前需要手動創(chuàng)建和管理。
  • 使用Spring進行事務管理后,該工具類由Spring提供,不需要手動編寫和管理。
  • 該工具類重在理解,為Spring進行事務管理做好鋪墊
package com.etime.util;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class TransactionManager {

    @Autowired
    private ConnectionUtil connectionUtil;

    //開啟事務
    public  void beginTransaction(){
        try {
            connectionUtil.getThreadConnection().setAutoCommit(false);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    //提交事務
    public  void commit(){
        try {
            connectionUtil.getThreadConnection().commit();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    //回滾事務
    public  void rollback(){
        try {
            connectionUtil.getThreadConnection().rollback();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    //釋放資源
    public  void release(){
        try {
            connectionUtil.removeConnection();//當前線程解除綁定
            connectionUtil.getThreadConnection().close();//還回連接池中
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

8、編寫業(yè)務層及數據訪問層事務控制代碼并配置Spring的IOC

(1)Dao層
package com.etime.dao.impl;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.etime.dao.AccountDao;
import com.etime.entity.Account;
import com.etime.util.ConnectionUtil;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
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 javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

@Repository("accountDao")
public class AccountDaoImpl implements AccountDao {

    @Autowired
    private ConnectionUtil connectionUtil;

    @Autowired
    private QueryRunner queryRunner;

    @Override
    public Account getByName(String name) throws SQLException {
        Connection conn = connectionUtil.getThreadConnection();
        String sql ="select *from account where name =? ";
        return queryRunner.query(conn,sql,new BeanHandler<>(Account.class),name);
    }

    @Override
    public int update(Account account) throws SQLException {
        Connection conn = connectionUtil.getThreadConnection();
        String sql ="update account set money =? where name =? ";
        return queryRunner.update(conn,sql,account.getMoney(),account.getName());
    }
}
  • 數據訪問層用到了QueryRunner,相關配置
        <dependency>
            <groupId>commons-dbutils</groupId>
            <artifactId>commons-dbutils</artifactId>
            <version>1.7</version>
        </dependency>
  • SpringConfiguration.java 配置類將QueryRunner對象交給Spring進行管理
 @Bean
    public QueryRunner getQueryRunner(){
        return new QueryRunner();
    }
(2)Service層
package com.etime.service.impl;

import com.etime.dao.AccountDao;
import com.etime.entity.Account;
import com.etime.service.AccountService;
import com.etime.util.TransactionManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service("accountService")
public class AccountServiceImpl implements AccountService {

    @Autowired
    private AccountDao accountDao;

    @Autowired
    private TransactionManager transactionManager;

    @Override
    public void transfer(String sourceAccountName, String targetAccountName, double money) {
        try{
            //開啟事務
            transactionManager.beginTransaction();

            //收錢的
            Account tAccount = accountDao.getByName(targetAccountName);
            tAccount.setMoney(tAccount.getMoney()+money);
            int rows2 = accountDao.update(tAccount);
            System.out.println("收錢的:"+rows2);

            //給錢的
            Account sAccount = accountDao.getByName(sourceAccountName);
            sAccount.setMoney(sAccount.getMoney()-money);
            int rows1 = accountDao.update(sAccount);
            System.out.println("給錢的:"+rows1);

            //提交事務
            transactionManager.commit();
        }catch (Exception exception){
            //回滾事務
            transactionManager.rollback();
            exception.printStackTrace();
        }finally {
            //釋放資源
            transactionManager.release();
        }
    }
}
(3)轉賬測試
package com.etime.test;

import com.etime.entity.User;
import com.etime.service.AccountService;
import com.etime.service.UserService;
import com.etime.service.impl.AccountServiceImpl;
import com.etime.util.DataSourceConfiguration;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {DataSourceConfiguration.class})
public class SpringTest {

    @Autowired
    private ApplicationContext applicationContext;

    @Test
    public void t01(){
        AccountService us = (AccountService)applicationContext.getBean("accountService");
        us.transfer("aaa","bbb",2000);
    }

}
  • 結果:正常轉賬成功,遇到異常情況, 事務進行回滾,保證了數據的一致性。

Spring基于配置文件的AOP

1、環(huán)境搭建

(1)構建maven工程添加依賴

    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.8.7</version>
    </dependency>

(2)代碼編寫

  • 實體類、持久層、業(yè)務層使用Spring實現轉賬案例的代碼

(3)創(chuàng)建 Spring 的配置文件并導入約束

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath*:db.properties</value>
            </list>
        </property>
    </bean>
    <!--數據源對象-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driver}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
    <!--配置JdbcTemplate模板對象-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <context:component-scan base-package="com.etime"></context:component-scan>
    <bean id="transactionManager" class="com.etime.util.TransactionManager"></bean>
    
</beans>

2、AOP 配置步驟

(1)使用 aop:confing 聲明 AOP 配置

  • 作用: 開始聲明aop配置
<aop:config>
      <!-- 配置的代碼都寫在此處 -->
</aop:config>

(2) 使用 aop:aspect 配置切面

  • 作用: 用于配置切面
  • 屬性
    • id :給切面提供一個唯一標識。
    • ref:引用配置好的通知類 bean 的 id。
   <aop:aspect id="tm" ref="transactionManager">
            ...
   </aop:aspect>

(3) 使用 aop:pointcut 配置切入點表達式

  • 作用: 用于配置切入點表達式。就是指定對哪些類的哪些方法進行增強。
  • 屬性
    • expression:用于定義切入點表達式。
    • id:用于給切入點表達式提供一個唯一標識
<aop:pointcut id="point1" expression="execution(public void com.etime.service.impl.AccountServiceImpl.transfer(..))"/

(4) 使用 aop:xxx 配置對應的通知類型

a.前置通知
  • aop:before
  • 作用:用于配置前置通知。指定增強的方法在切入點方法之前執(zhí)行
  • 屬性
    • method:用于指定通知類中的增強方法名稱
    • ponitcut-ref:用于指定切入點的表達式的引用
    • poinitcut:用于指定切入點表達式
  • 執(zhí)行時間
    • 切入點方法執(zhí)行之前執(zhí)行
<aop:before method="beginTransaction" pointcut-ref="point1"></aop:before>
b.后置通知
  • aop:after-returning
  • 作用: 用于配置后置通知
  • 屬性
    • method:指定通知中方法的名稱。
    • pointct:定義切入點表達式
    • pointcut-ref:指定切入點表達式的引用
  • 執(zhí)行時間
    • 切入點方法正常執(zhí)行之后。它和異常通知只能有一個執(zhí)行
<aop:after-returning method="commit" pointcut-ref="point1"></aop:after-returning> 
c.異常通知
  • aop:after-throwing
  • 作用:用于配置異常通知
  • 屬性
    • method:指定通知中方法的名稱。
    • pointct:定義切入點表達式
    • pointcut-ref:指定切入點表達式的引用
  • 執(zhí)行時間
    • 切入點方法執(zhí)行產生異常后執(zhí)行。它和后置通知只能執(zhí)行一個
<aop:after-throwing method="rollback" pointcut-ref="point1"></aop:after-throwing>
d.最終通知
  • aop:after
  • 作用:用于配置最終通知
  • 屬性
    • method:指定通知中方法的名稱。
    • pointct:定義切入點表達式
    • pointcut-ref:指定切入點表達式的引用
  • 執(zhí)行時間
    • 無論切入點方法執(zhí)行時是否有異常,它都會在其后面執(zhí)行。
<aop:after method="release" pointcut-ref="point1"></aop:after>

3、切入點表達式說明

(1)切點表達式的語法

execution([修飾符] 返回值類型 包名.類名.方法名(參數))
  • 訪問修飾符可以省略
  • 返回值類型、包名、類名、方法名可以使用星號* 代表任意
  • 包名與類名之間一個點 . 代表當前包下的類,兩個點 … 表示當前包及其子包下的類
  • 參數列表可以使用兩個點 … 表示任意個數,任意類型的參數列表
a.全匹配方式
public void 
com.etime.service.impl.AccountServiceImpl.saveAccount(com.etime.domain.Account)
b.訪問修飾符可以省略
void com.etime.service.impl.AccountServiceImpl.saveAccount(com.etime.domain.Account)
c.返回值可以使用*號,表示任意值
* com.etime.service.impl.AccountServiceImpl.saveAccount(com.etime.domain.Account)
d.包名可以使用 * 號,表示任意包 (但是有幾級包,需要寫幾個 *)
* *.*.*.*.AccountServiceImpl.saveAccount(com.etime.domain.Account)
e.使用…來表示當前包,及其子包
* com..AccountServiceImpl.saveAccount(com.etime.domain.Account)
f.類名可以使用*號,表示任意類
* com..*.saveAccount(com.etime.domain.Account)
g.方法名可以使用*號,表示任意方法
* com..*.*( com.etime.domain.Account)
h.參數列表可以使用*,表示參數可以是任意數據類型,但是必須有參數
* com..*.*(*)
i.參數列表可以使用…表示有無參數均可,有參數可以是任意類型
* com..*.*(..)
j.全通配方式:
* *..*.*(..)
k.注意:通常情況下,我們都是對業(yè)務層的方法進行增強,所以切入點表達式都是切到業(yè)務層實現類。
execution(* com.etime.service.impl.*.*(..))

4、環(huán)繞通知配置事務管理

(1)在TransactionManager類當中添加方法

/**
     * 環(huán)繞通知:
     * spring 框架為我們提供了一個接口:ProceedingJoinPoint,它可以作為環(huán)繞通知的方法參數。
     * 在環(huán)繞通知執(zhí)行時,spring 框架會為我們提供該接口的實現類對象,我們直接使用就行。
     * @param pjp
     * @return
     */
public Object transactionAround(ProceedingJoinPoint pjp) {
    //定義返回值
    Object returnValue = null;
    try {
        //獲取方法執(zhí)行所需的參數
        Object[] args = pjp.getArgs();
        //前置通知:開啟事務
        beginTransaction();
        //執(zhí)行方法
        returnValue = pjp.proceed(args);
        //后置通知:提交事務
        commit();
    }catch(Throwable e) {
        //異常通知:回滾事務
        rollback();
        e.printStackTrace();
    }finally {
        //最終通知:釋放資源
        release();
    }
    return returnValue;
}

(2)環(huán)繞通知

  • aop:around
  • 作用:用于配置環(huán)繞通知
  • 屬性
    • method:指定通知中方法的名稱。
    • pointct:定義切入點表達式
    • pointcut-ref:指定切入點表達式的引用
  • 說明:它是 spring 框架為我們提供的一種可以在代碼中手動控制增強代碼什么時候執(zhí)行的方式。
  • 注意:通常情況下,環(huán)繞通知都是獨立使用的
    <aop:config>
        <aop:aspect id="tm" ref="transactionManager">
            <aop:pointcut id="point1"
                          expression="execution(public void com.etime.service.impl.AccountServiceImpl.transfer(..))"/>
            <aop:around method="transactionAround" pointcut-ref="point1"></aop:around>
        </aop:aspect>
    </aop:config>

到了這里,關于Spring02-Spring注解的使用、基于注解的IOC、純注解配置、整合Junit、AOP入門、基于配置文件的AOP、切入點表達式、基于配置的文件環(huán)繞通知的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • Spring——基于注解的AOP配置

    Spring——基于注解的AOP配置

    1.1.pom.xml 1.2.dao 1.3.service 1.4.applicationContext.xml 1.5.測試 2.1.applicationContext.xml 2.2.AOP配置 常用注解 @Aspect:把當前類聲明為切面類 @Before:前置通知,可以指定切入點表達式 @AfterReturning:后置【try】通知,可以指定切入點表達式 @AfterThrowing:異常【catch】通知,可以指定切入點表達

    2024年01月22日
    瀏覽(20)
  • 【Spring進階系列丨第八篇】Spring整合junit & 面向切面編程(AOP)詳解

    【Spring進階系列丨第八篇】Spring整合junit & 面向切面編程(AOP)詳解

    ? @ContextConfiguration注解需要注意的細節(jié)是: classes:指定的是主配置類的字節(jié)碼 locations:指定xml文件的位置 ? 首先來看一個問題,假如我現在有一個UserServiceImpl用戶業(yè)務類,其中呢,有一個保存用戶的方法,即: ? 現在的需求是:我要在保存用戶之前新增事務的功能,你

    2024年04月13日
    瀏覽(25)
  • 淺談 Spring IOC 和 DI 以及 Spring 整合 Mybatis 的十四 個注解

    淺談 Spring IOC 和 DI 以及 Spring 整合 Mybatis 的十四 個注解

    控制 : 指對對象的創(chuàng)建權 反轉: 對象的創(chuàng)建由程序員在類中主動創(chuàng)建變?yōu)橛蒘pring自動創(chuàng)建 Spring方式:所有的對象都是由Spring框架提前創(chuàng)建出來,存儲到一個容器中,servlet需要Service了,就向Spring要一個 技術的作用 : 通過底層反射原理來 解開對象之間的耦合 注解 @Compone

    2024年02月16日
    瀏覽(50)
  • MyBatis與Spring集成&常用注解以及AOP和PageHelper分頁插件整合

    MyBatis與Spring集成&常用注解以及AOP和PageHelper分頁插件整合

    目錄 前言 一、MyBatis與Spring整合的好處以及兩者之間的關系 1.好處 2.關系 ?二、MyBatis和Spring集成 1.導入pom.xml 2.編寫配置文件? 3.利用mybatis逆向工程生成模型層代碼 三、常用注解 ?四、AOP整合pageHelper分頁插件 創(chuàng)建一個切面 測試 MyBatis是一個開源的持久層框架,而Spring是一個

    2024年02月07日
    瀏覽(28)
  • 注解實現(基于Spring AOP)

    切入點表達式 Spring AOP 支持的切入點主要有以下幾種: execution:用于匹配方法執(zhí)行的連接點。這是最常用的切入點指示器。你可以指定具體的方法,或者類來匹配。 例如: execution(* com.example.service.*.*(..)) ,這個表達式表示匹配 com.example.service 包下的所有類的所有方法。 wit

    2024年02月16日
    瀏覽(18)
  • Spring AOP官方文檔學習筆記(二)之基于注解的Spring AOP

    1.@Aspect注解 (1) @Aspect注解用于聲明一個切面類,我們可在該類中來自定義切面,早在Spring之前,AspectJ框架中就已經存在了這么一個注解,而Spring為了提供統一的注解風格,因此采用了和AspectJ框架相同的注解方式,這便是@Aspect注解的由來,換句話說,在Spring想做AOP框架之前,

    2023年04月17日
    瀏覽(25)
  • 11、Spring之基于注解的AOP

    11、Spring之基于注解的AOP

    創(chuàng)建名為spring_aop_annotation的新module,過程參考9.1節(jié) 注意:AOP需要在IOC的基礎上實現,因此需要導入IOC的依賴 11.2.1.1、配置前置方法 11.2.1.2、測試使用效果 由控制臺日志可知,切面類的前置通知(方法),通過切入點表達式,作用到了目標方法的連接點上 11.2.2.1、改進前置方

    2024年02月13日
    瀏覽(27)
  • Spring IOC基于XML和注解管理Bean(一)

    Spring IOC基于XML和注解管理Bean(一)

    Spring IOC基于XML和注解管理Bean(二) IoC 是 Inversion of Control 的簡寫,譯為“ 控制反轉 ”,它不是一門技術,而是一種設計思想,是一個重要的面向對象編程法則,能夠指導我們如何設計出 松耦合 、更優(yōu)良的程序。 Spring 通過 IoC 容器來管理所有 Java 對象的實例化和初始化,控

    2024年02月08日
    瀏覽(20)
  • Spring IOC基于XML和注解管理Bean(二)

    Spring IOC基于XML和注解管理Bean(一) 2.9、實驗八:p命名空間 引入p命名空間 引入p命名空間后,可以通過以下方式為bean的各個屬性賦值 2.10、實驗九:引入外部屬性文件 ①加入依賴 ②創(chuàng)建外部屬性文件 [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳

    2024年02月09日
    瀏覽(26)
  • Spring Boot學習隨筆- 集成JSP模板(配置視圖解析器)、整合Mybatis(@MapperScan注解的使用)

    Spring Boot學習隨筆- 集成JSP模板(配置視圖解析器)、整合Mybatis(@MapperScan注解的使用)

    學習視頻:【編程不良人】2021年SpringBoot最新最全教程 在main創(chuàng)建webapp,然后創(chuàng)建index.jsp進行測試,在訪問之前需要進行一個設置,否則springboot是找不到jsp頁面的 修改jsp無需重啟應用 數據庫訪問框架:hibernate、jpa、mybatis【主流】 SpringBoot(微框架) = Spring(工廠) + SpringMV

    2024年02月05日
    瀏覽(58)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包