学习笔记(狂神Java Spring5 P1-P28)

本文详细讲解了Spring框架中的IoC控制反转和DI依赖注入,包括使用构造器注入、Set注入、属性自动装配(byName和byType)、注解@Autowired和@Resource的应用,以及Spring配置文件的编写和测试。涵盖了Spring的核心模块和配置机制,适合进阶学习者参考。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

学习笔记源码下载地址

1、Ioc

Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器(框架)。
官网: http://spring.io/

Spring 框架是一个分层架构,由 7 个定义良好的模块组成。(核心容器,Spring 上下文,Spring AOP,SpringDAO,SpringORM,Spring Web模块,Spring MVC 框架)Spring 模块构建在核心容器之上,核心容器定义了创建、配置和管理 bean 的方式 .组成 Spring 框架的每个模块(或组件)都可以单独存在,或者与其他一个或多个模块联合实现。

- 回顾
UserDao接口

public interface UserDao {
    public void getUser();
}

UserDaoImpl

package dao;

public class UserDaoImpl implements UserDao {
    @Override
    public void getUser() {
        System.out.println("默认获取用户数据");
    }
}

UserService

package service;

public interface UserService {
    public void getUser();
}

UserServiceImpl

package service;

import dao.UserDao;
import dao.UserDaoImpl;
import dao.UserDaoMySqlImpl;

public class UserServiceImpl implements UserService {
    private UserDao userDao = new UserDaoImpl();

    private UserDao userDao1 = new UserDaoMySqlImpl();


    @Override
    public void getUser() {
        userDao.getUser();
        userDao1.getUser();
    }
}

MyTest

import dao.UserDaoImpl;
import dao.UserDaoMySqlImpl;
import dao.UserDaoOracleImpl;
import org.junit.Test;
import service.UserService;
import service.UserServiceImpl;

public class MyTest {
    @Test
    public void test() {
        UserService service = new UserServiceImpl();
        service.getUser();
    }
  }

- 修改后
增加一个UserDao实现类

public class UserDaoMySqlImpl implements UserDao {
    @Override
    public void getUser() {
        System.out.println("MySql获取用户数据");
    }
}

还得再再Impl中增加一个实现类的实现

public class UserServiceImpl implements UserService {
    private UserDao userDao = new UserDaoMySqlImpl();
 
    @Override
    public void getUser() {
        userDao.getUser();
    }
}

解决反复增加实现类的时候又得要去修改增加Service中的实现所以在service的实现中利用set

public class UserServiceImpl implements UserService {
    private UserDao userDao;

    // 利用set实现
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

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

测试:

@Test
    public void test1() {
        UserServiceImpl service = new UserServiceImpl();


        service.setUserDao(new UserDaoMySqlImpl());
        service.getUser();

	
        service.setUserDao(new UserDaoImpl());
        service.getUser();

        service.setUserDao(new UserDaoOracleImpl());
        service.getUser();
    }

2、HelloSpring

编写实体类

package pojo;

import lombok.Data;

@Data
public class Hello {
    private String string;

    public void show() {
        System.out.println("Hello," + string);
    }
}

编写我们的Sprng配置文件命名为beans.xml

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

    <!--bean就是java对象 , 由Spring创建和管理-->
    <bean id="hello" class="pojo.Hello">
        <property name="string" value="Spring"/>
    </bean>
</beans>

测试

import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import pojo.Hello;

public class MyTest {
    @Test
    public void test(){
        //解析beans.xml文件 , 生成管理相应的Bean对象
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        //getBean : 参数即为spring配置文件中bean的id .
        Hello hello = (Hello) context.getBean("hello");
        hello.show();
    }
}

完善我们的上一个案例

在我们的上一个案例中新增文件beans.xml

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

    <!--bean就是java对象 , 由Spring创建和管理-->
    <bean id="DaoImpl" class="dao.UserDaoImpl"></bean>
    <bean id="MySqlImpl" class="dao.UserDaoMySqlImpl"></bean>
    <bean id="OracleImpl" class="dao.UserDaoOracleImpl"></bean>


    <bean id="UserServiceImpl" class="service.UserServiceImpl">
<!--     用户提什么我们就修改这里就好了
   <property name="userDao" ref="MySqlImpl"></property>-->
        <property name="userDao" ref="OracleImpl"></property>
     </bean>
</beans>

测试

    @Test
    public void test2() {
        //解析beans.xml文件 , 生成管理相应的Bean对象
        ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("beans.xml");
        //getBean : 参数即为spring配置文件中bean的id .
        UserServiceImpl userServiceImpl = (UserServiceImpl) classPathXmlApplicationContext.getBean("UserServiceImpl");
        userServiceImpl.getUser();
    }

- 验证IOC创建对象方式
通过无参构造方法来创建
实体类

package pojo;

public class User {

    private String name;

    public User() {
        System.out.println("user无参构造方法");
    }

    public String getName() {
        return name;
    }

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

    public void show() {
        System.out.println("name=" + name);
    }

}

beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">
 
    <bean id="user" class="pojo.User">
        <property name="name" value="zzzzz"/>
    </bean>
</beans>

测试

 @Test
    public void test4() {
        ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("beans.xml");
        //在执行getBean的时候, user已经创建好了 , 通过无参构造
        User user = (User) classPathXmlApplicationContext.getBean("user");
        //调用对象的方法 .
        user.show();
    }

结果显示在调用show方法之前,User对象已经通过无参构造初始化了!

通过有参构造方法来创建
有参实体类

package pojo;

public class User {

    private String name;
/*    public User() {
        System.out.println("user无参构造方法");
    }*/
    
    public User(String name) {
        this.name = name;
    }


    public String getName() {
        return name;
    }

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

    public void show() {
        System.out.println("name=" + name);
    }

}

beans.xml 有三种方式编写
方式一:

<!-- 第一种根据index参数下标设置 -->
<bean id="user" class="pojo.User">
    <!-- index指构造方法 , 下标从0开始 -->
    <constructor-arg index="0" value="111112"/>
</bean>

方式二:

<!-- 第二种根据参数名字设置 -->
<bean id="user" class="pojo.User">
    <!-- name指参数名 -->
    <constructor-arg name="name" value="222222"/>
</bean>

方式三:

<!-- 第三种根据参数类型设置 -->
<bean id="user" class="pojo.User">
    <constructor-arg type="java.lang.String" value="3333332"/>
</bean>

测试

    @Test
    public void test5(){
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        User user = (User) context.getBean("user");
        user.show();
    }

3、配置

  • 别名

alias 设置别名 , 为bean设置别名 , 可以设置多个别名

<!--设置别名:在获取Bean的时候可以使用别名获取-->
<alias name="user" alias="user2"/>
  • Bean的配置
<!--bean就是java对象,由Spring创建和管理-->
 
<!--
    id 是bean的标识符,要唯一,如果没有配置id,name就是默认标识符
    如果配置id,又配置了name,那么name是别名
    name可以设置多个别名,可以用逗号,分号,空格隔开
    如果不配置id和name,可以根据applicationContext.getBean(.class)获取对象;
 
    class是bean的全限定名=包名+类名
-->
<bean id="hello" name="hello2 h2,h3;h4" class="pojo.Hello">
    <property name="name" value="Spring"/>
</bean>

一般用于团队开发使用,多个配置文件合并为一个文件

<import resource="{path}/beans.xml"/>

4、DI依赖注入

方式一:

  • 构造器注入(已经讲过)

方式二:

  • Set注入
    准备工作
    pojo.Address.java
package pojo;

import lombok.Data;

@Data
public class Address {

    private String address;
    
}

pojo.Student.java

package pojo;


import java.util.*;


public class Student {

    private String name;
    private Address address;
    private String[] books;
    private List<String> hobbys;
    private Map<String, String> card;
    private Set<String> games;
    private String wife;
    private Properties info;

    public Student() {
    }

    public Student(String name, Address address, String[] books, List<String> hobbys, Map<String, String> card, Set<String> games, String wife, Properties info) {
        this.name = name;
        this.address = address;
        this.books = books;
        this.hobbys = hobbys;
        this.card = card;
        this.games = games;
        this.wife = wife;
        this.info = info;
    }

    public String getName() {
        return name;
    }

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

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    public String[] getBooks() {
        return books;
    }

    public void setBooks(String[] books) {
        this.books = books;
    }

    public List<String> getHobbys() {
        return hobbys;
    }

    public void setHobbys(List<String> hobbys) {
        this.hobbys = hobbys;
    }

    public Map<String, String> getCard() {
        return card;
    }

    public void setCard(Map<String, String> card) {
        this.card = card;
    }

    public Set<String> getGames() {
        return games;
    }

    public void setGames(Set<String> games) {
        this.games = games;
    }

    public String getWife() {
        return wife;
    }

    public void setWife(String wife) {
        this.wife = wife;
    }

    public Properties getInfo() {
        return info;
    }

    public void setInfo(Properties info) {
        this.info = info;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ",\n address=" + address.toString() +
                ", \n books=" + Arrays.toString(books) +
                ",\n hobbys=" + hobbys +
                ", \ncard=" + card +
                ", \ngames=" + games +
                ", \nwife='" + wife + '\'' +
                ", \ninfo=" + info +
                '}';
    }
}


配置beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--    Bean注入-->
    <bean id="address" class="pojo.Address">
        <property name="address" value="陕西"/>
    </bean>


    <bean id="student" class="pojo.Student">
        <!--    常量注入-->
        <property name="name" value="小明"/>

        <!--    Bean注入-->
        <property name="address" ref="address"/>

        <!--    数组注入-->
        <property name="books">
            <array>
                <value>西游记</value>
                <value>红楼梦</value>
                <value>水浒传</value>
                <value>三国演绎</value>
            </array>
        </property>

        <!--        List注入-->
        <property name="hobbys">
            <list>
                <value>听歌</value>
                <value>看电影</value>
                <value>爬山</value>
            </list>
        </property>

        <!--        Map注入-->
        <property name="card">
            <map>
                <entry key="工商" value="1234567890"/>
                <entry key="长安" value="234567890"/>
            </map>
        </property>

        <!--set注入-->
        <property name="games">
            <set>
                <value>DATA</value>
                <value>LOL</value>
                <value>COC</value>
            </set>
        </property>

        <!--Null注入-->

        <property name="wife">
            <null/>
        </property>


        <!--        Properties注入-->

        <property name="info">
            <props>
                <prop key="学号">1234567890</prop>
                <prop key="性别"></prop>
                <prop key="姓名">小明</prop>
            </props>
        </property>
    </bean>


</beans>

测试:

import org.junit.jupiter.api.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import pojo.Student;


public class MyTest {
    @Test
    public void test() {
        ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("beans.xml");
        Student student = (Student) classPathXmlApplicationContext.getBean("student");
        System.out.println(student.toString());
    }
}

结果展示:
在这里插入图片描述
方式三:

  • 拓展
    p命名
    User.java
package pojo;

public class User {
    private String name;
    private int age;

    public User() {
    }

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

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


在xml文件中加入头文件约束

       xmlns:p="http://www.springframework.org/schema/p"
    <!--P(属性: properties)命名空间 , 属性依然要设置set方法-->
    <bean id="user" class="pojo.User" p:name="zzzz" p:age="18">

测试:

    @Test
    public void test01(){
        ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("beans.xml");
        User user = (User) classPathXmlApplicationContext.getBean("user");
        System.out.println(user);
    }

c命名注入
加入头文件约束

xmlns:c="http://www.springframework.org/schema/c"

配置

<!--C(构造: Constructor)命名空间 , 属性依然要设置set方法-->
 <bean id="user" class="pojo.User" c:name="狂神" c:age="18"/>

测试

    @Test
    public void test01(){
        ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("beans.xml");
        User user = (User) classPathXmlApplicationContext.getBean("user");
        System.out.println(user);
    }

Bean的作用域
在这里插入图片描述单例模式(Spring默认)

<bean id="user" class="pojo.User" c:name="zzzzzzzzzzz" c:age="18" scope="singleton">

原型模式(每次丛容器中get的时候都会产生一个新对象)

<bean id="user" class="pojo.User" c:name="zzzzzzzzzzzzz" c:age="18" scope="singleton">

其余(request、session)的都是在WEB开发中才能用得到的

5、Bean的自动装配

Spring中bean有三种装配机制,分别是:

在xml中显式配置;
在java中显式配置;
隐式的bean发现机制和自动装配。(重要主讲)

- 搭建环境

新建maven项目
创建两个实体类

package pojo;

import lombok.Data;

@Data
public class Cat {
    public void shout() {
        System.out.println("miao~");
    }
}

package pojo;

import lombok.Data;

@Data
public class Dog {
    public void shout() {
        System.out.println("wang~");
    }
}

创建一个people类

package pojo;

import lombok.Data;

@Data
public class People {
    private Cat cat;
    private Dog dog;
    private String str;
}

配置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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="dog" class="pojo.Dog"/>
    <bean id="cat" class="pojo.Cat"/>
    <bean id="people" class="pojo.People">
        <property name="cat" ref="cat"/>
        <property name="dog" ref="dog"/>
        <property name="str" value="zzzzzz"/>
    </bean>
</beans>

测试

import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import pojo.People;

public class MyTest {

    @Test
    public void testMethodAutowire() {
        ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("beans.xml");
        People user = (People) classPathXmlApplicationContext.getBean("people");
        user.getCat().shout();
        user.getDog().shout();
    }
}

- autowire byName (按名称自动装配)

修改bean配置,增加一个属性 autowire=“byName”

    <bean id="user" class="pojo.People" autowire="byName">
        <property name="str" value="zzzzzzzzzzzz"/>
    </bean>

再次输出,显示正常

修改上面注入bean中的id属性的值如:catXXXX或者dogXXX再次运行时就会报错。

结论:byname会自动在容器上下文中查找和自己对象set方法后面值对应的 bean id

- autowire byType (按类型自动装配)

将people的bean配置修改一下 : autowire=“byType”

<bean id="people" class="pojo.People" autowire="byType">
    <property name="str" value="zzzzzzzzzzzzz"/>
</bean>

测试正常输出

结论:byType会自动在容器上下文中查找和自己对象属性类型对应的 bean

- 使用注解

准备工作:
导入spring配置文件中context文件头并开启属性注解支持!

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

    <context:annotation-config/>

</beans>

@Autowired(按类型自动转配的,不支持id匹配)

package pojo;

import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;

@Data
public class People {
    @Autowired
    //如果允许对象为null,设置required = false,默认为true
    private Cat cat;
    @Autowired
    private Dog dog;
    private String str;
}

xml

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">
    <context:annotation-config/>
    <bean id="dog" class="pojo.Dog"/>
    <bean id="cat" class="pojo.Cat"/>
    <bean id="people" class="pojo.People">
    </bean>
</beans>

@Qualifier

  • @Autowired是根据类型自动装配的,加上@Qualifier则可以根据byName的方式自动装配不能单独使用。

配置文件修改内容,保证类型存在对象。且名字不为类的默认名字!

<bean id="dog1" class="pojo.Dog"/>
<bean id="dog" class="pojo.Dog"/>
<bean id="cat1" class="pojo.Cat"/>
<bean id="cat" class="pojo.Cat"/>

在属性上添加Qualifier注解

@Autowired
@Qualifier(value = "cat2")
private Cat cat;
@Autowired
@Qualifier(value = "dog2")
private Dog dog;

@Resource

@Resource如有指定的name属性,先按该属性进行byName方式查找装配;

其次再进行默认的byName方式进行装配;

如果以上都不成功,则按byType的方式自动装配。

都不成功,则报异常。

实体类

package pojo;

import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

import javax.annotation.Resource;

@Data
public class People {

    @Resource(name = "cat1")
    private Cat cat;
    //如果允许对象为null,设置required = false,默认为true

    @Autowired
    @Qualifier(value = "dog1")
    private Dog dog;
    private String str;
}

xml

<bean id="cat1" class="pojo.Cat"/>

小结
1、@Autowired与@Resource都可以用来装配bean。都可以写在字段上,或写在setter方法上。

2、@Autowired默认按类型装配(属于spring规范),默认情况下必须要求依赖对象必须存在,如果要允许null 值,可以设置它的required属性为false,如:@Autowired(required=false) ,如果我们想使用名称装配可以结合@Qualifier注解进行使用

3、@Resource(属于J2EE复返),默认按照名称进行装配,名称可以通过name属性进行指定。如果没有指定name属性,当注解写在字段上时,默认取字段名进行按照名称查找,如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。

它们的作用相同都是用注解方式注入对象,但执行顺序不同。@Autowired先byType,@Resource先byName。

6、使用注解开发

- Bean的实现

  • 在xml中配置指定注解扫描包及文件约束
   <?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:annotation-config/>
    <!--指定注解扫描包-->
    <context:component-scan base-package="包名"/>


</beans>
  • 编写实体类并添加注解
package pojo;

import org.springframework.stereotype.Component;

@Component("user")
// 相当于配置文件中 <bean id="user" class="当前注解的类"/>
public class User {
    public String name = "zzzzzz";
}

测试

import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import pojo.User;

public class MyTest {
    @Test
    public void test() {
        ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("beans.xml");
        User user = (User) classPathXmlApplicationContext.getBean("user");
        System.out.println(user.name);
    }
}

- 属性如何注入
可以不用提供set方法,直接在直接名上添加@value(“值”)

package pojo;

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

@Component("user")
// 相当于配置文件中 <bean id="user" class="当前注解的类"/>
public class User {
    // 相当于配置文件中 <property name="name" value="zzzzzzzzzzz"/>
    @Value("zzzzzz")
    public String name;
}

- 衍生的注解

@Component三个衍生注解(功能一样,目前使用哪一个功能都一样。)

@Controller:web层

@Service:service层

@Repository:dao层

- 自动装配

  • @Autowired:自动装配通过类型,名字否则使用@Qualifier(value=“xxxx”)
  • @Nullable 字段标记了这个注解,说明这个字段可以时null
  • @Resource 自动装配通过名字,类型

- 作用域

@Controller("user")
@Scope("prototype")
public class User {
    @Value("zzzzzzzzz")
    public String name;
}

总结

XML与注解比较

XML可以适用任何场景 ,结构清晰,维护方便

注解不是自己提供的类使用不了,开发简单方便

xml与注解整合开发 :推荐最佳实践

xml管理Bean

注解完成属性注入

使用过程中, 可以不用扫描,扫描是为了类上的注解

- 基于Java类进行配置

  • 编写一个实体类,Dog
package pojo;

import org.springframework.stereotype.Component;

@Component  //将这个类标注为Spring的一个组件,放到容器中!
public class Dog {
    public String name = "dog";
}
  • 编写一个MyConfig配置类
package controller;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import pojo.Dog;

@Configuration  //代表这是一个配置类
public class MyConfig {

    @Bean //通过方法注册一个bean,这里的返回值就Bean的类型,方法名就是bean的id!
    public Dog dog(){
        return new Dog();
    }

}
  • 测试
    @Test
    public void test1() {
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
        Dog dog = (Dog) annotationConfigApplicationContext.getBean("dog");
        System.out.println(dog.name);
    }

7、静态代理

角色分析:

抽象角色 : 一般使用接口或者抽象类来实现
真实角色 : 被代理的角色
代理角色 : 代理真实角色 ; 代理真实角色后 , 一般会做一些附属的操作 .
客户 : 使用代理角色来进行一些操作 .

- 代码实现(demo01)

抽象角色

//抽象角色:租房
public interface Rent {
    public void rent();
}

真实角色

//真实角色: 房东,房东要出租房子
public class Host implements Rent{
    public void rent() {
        System.out.println("房屋出租");
    }
}

代理角色

//代理角色:中介
public class Proxy implements Rent {
 
    private Host host;
    public Proxy() { }
    public Proxy(Host host) {
        this.host = host;
    }
 
    //租房
    public void rent(){
        seeHouse();
        host.rent();
        fare();
    }
    //看房
    public void seeHouse(){
        System.out.println("带房客看房");
    }
    //收中介费
    public void fare(){
        System.out.println("收中介费");
    }
}

客户

//客户类,一般客户都会去找代理!
public class Client {
    public static void main(String[] args) {
        //房东要租房
        Host host = new Host();
        //中介帮助房东
        Proxy proxy = new Proxy(host);
 
        //你去找中介!
        proxy.rent();
    }
}

结论:

在这个过程中,你直接接触的就是中介,就如同现实生活中的样子,你看不到房东,但是你依旧租到了房东的房子通过代理,这就是所谓的代理模式

- 代码实现(demo02)

创建一个抽象角色

//抽象角色:增删改查业务
public interface UserService {
    void add();
    void delete();
    void update();
    void query();
}

真实对象

//真实对象,完成增删改查操作的人
public class UserServiceImpl implements UserService {
 
    public void add() {
        System.out.println("增加了一个用户");
    }
 
    public void delete() {
        System.out.println("删除了一个用户");
    }
 
    public void update() {
        System.out.println("更新了一个用户");
    }
 
    public void query() {
        System.out.println("查询了一个用户");
    }
}

代理角色

//代理角色,在这里面增加日志的实现
public class UserServiceProxy implements UserService {
    private UserServiceImpl userService;
 
    public void setUserService(UserServiceImpl userService) {
        this.userService = userService;
    }
 
    public void add() {
        log("add");
        userService.add();
    }
 
    public void delete() {
        log("delete");
        userService.delete();
    }
 
    public void update() {
        log("update");
        userService.update();
    }
 
    public void query() {
        log("query");
        userService.query();
    }
 
    public void log(String msg){
        System.out.println("执行了"+msg+"方法");
    }
 
}

测试

package demo02;

import org.junit.jupiter.api.Test;

public class Client {

    @Test
    public void test() {
        //真实业务
        UserServiceImpl userService = new UserServiceImpl();
        //代理类
        UserServiceProxy proxy = new UserServiceProxy();
        //使用代理类实现日志功能!
        proxy.setUserService(userService);

        proxy.add();
    }
}

8、动态代理

- 代码实现(demo03)

Rent

package demo03;

//抽象角色:租房
public interface Rent {
    public void rent();
}

Host

package demo03;

//真实角色: 房东,房东要出租房子
public class Host implements Rent {
    public void rent() {
        System.out.println("房屋出租");
    }
}

ProxyInvocationHandler

package demo03;

import org.springframework.cglib.proxy.InvocationHandler;
import org.springframework.cglib.proxy.Proxy;

import java.lang.reflect.Method;

public class ProxyInvocationHandler implements InvocationHandler {
    private Rent rent;

    public void setRent(Rent rent) {
        this.rent = rent;
    }

    //生成代理类,重点是第二个参数,获取要代理的抽象角色!之前都是一个角色,现在可以代理一类角色
    public Object getProxy() {
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                rent.getClass().getInterfaces(), this);
    }

    // proxy : 代理类 method : 代理类的调用处理程序的方法对象.
    // 处理代理实例上的方法调用并返回结果
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        seeHouse();
        //核心:本质利用反射实现!
        Object result = method.invoke(rent, args);
        fare();
        return result;
    }

    //看房
    public void seeHouse() {
        System.out.println("带房客看房");
    }

    //收中介费
    public void fare() {
        System.out.println("收中介费");
    }

}

Client

package demo03;

import org.junit.jupiter.api.Test;

//租客
public class Client {
    @Test
    public void test() {
        //真实角色
        Host host = new Host();
        //代理实例的调用处理程序
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        pih.setRent(host); //将真实角色放置进去!
        Rent proxy = (Rent) pih.getProxy(); //动态生成对应的代理类!
        proxy.rent();
    }

}

- 代码实现(demo04再demo02的基础上)

ProxyInvocationHandler

package demo04;

import org.springframework.cglib.proxy.InvocationHandler;
import org.springframework.cglib.proxy.Proxy;

import java.lang.reflect.Method;

public class ProxyInvocationHandler implements InvocationHandler {
    private Object target;

    public void setTarget(Object target) {
        this.target = target;
    }

    //生成代理类
    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                target.getClass().getInterfaces(),this);
    }

    // proxy : 代理类
    // method : 代理类的调用处理程序的方法对象.
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        log(method.getName());
        Object result = method.invoke(target, args);
        return result;
    }

    public void log(String methodName){
        System.out.println("执行了"+methodName+"方法");
    }

}

Test

package demo04;

import org.junit.jupiter.api.Test;

public class MyTest {
    @Test
    public void test() {
        //真实对象
        UserServiceImpl userService = new UserServiceImpl();
        //代理对象的调用处理程序
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        pih.setTarget(userService); //设置要代理的对象
        UserService proxy = (UserService) pih.getProxy(); //动态生成代理类!
        proxy.delete();
    }
}

9、AOP

- 导入依赖

<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.4</version>
</dependency>

- 方式一:
业务接口和实现类

package service;

public interface UserService {

    public void add();

    public void delete();

    public void update();

    public void search();

}

package service;

public class UserServiceImpl implements UserService{

    @Override
    public void add() {
        System.out.println("增加用户");
    }

    @Override
    public void delete() {
        System.out.println("删除用户");
    }

    @Override
    public void update() {
        System.out.println("更新用户");
    }

    @Override
    public void search() {
        System.out.println("查询用户");
    }
}

一个前置增强 一个后置增强

package log;

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

public class Log implements MethodBeforeAdvice {

    //method : 要执行的目标对象的方法
    //objects : 被调用的方法的参数
    //Object : 目标对象
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println( o.getClass().getName() + "的" + method.getName() + "方法被执行了");
    }
}

package log;

import org.springframework.aop.AfterReturningAdvice;

import java.lang.reflect.Method;

public class AfterLog implements AfterReturningAdvice {
    //returnValue 返回值
    //method被调用的方法
    //args 被调用的方法的对象的参数
    //target 被调用的目标对象
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("执行了" + target.getClass().getName()
                +"的"+method.getName()+"方法,"
                +"返回值:"+returnValue);
    }
}

编写配置文件beans.xml

<?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"
       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">
 
    <!--注册bean-->
    <bean id="userService" class="service.UserServiceImpl"/>
    <bean id="log" class="clog.Log"/>
    <bean id="afterLog" class="log.AfterLog"/>
    <!--aop的配置-->
    <aop:config>
        <!--切入点  expression:表达式匹配要执行的方法-->
        <aop:pointcut id="pointcut" expression="execution(* service.UserServiceImpl.*(..))"/>
        <!--执行环绕; advice-ref执行方法 . pointcut-ref切入点-->
        <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
    </aop:config>
</beans>

测试

import org.junit.jupiter.api.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import service.UserService;

public class MyTest {
    @Test
    public void test() {
        ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("beans.xml");
        UserService userService = (UserService) classPathXmlApplicationContext.getBean("userService");
        userService.search();
    }
}

- 方法二:
目标业务类不变依旧是userServiceImpl
切入类

package pointcut;

public class DiyPointcut {

    public void before(){
        System.out.println("---------方法执行前---------");
    }
    public void after(){
        System.out.println("---------方法执行后---------");
    }

}

配置beans.xml

<?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"
       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">

    <!--第二种方式自定义实现-->
    <!--注册bean-->
    <bean id="diy" class="pointcut.DiyPointcut"/>
    <!--aop的配置-->
    <aop:config>
        <!--第二种方式:使用AOP的标签实现-->
        <aop:aspect ref="diy">
            <aop:pointcut id="diyPonitcut" expression="execution(* service.UserServiceImpl.*(..))"/>
            <aop:before pointcut-ref="diyPonitcut" method="before"/>
            <aop:after pointcut-ref="diyPonitcut" method="after"/>
        </aop:aspect>
    </aop:config>
    </beans>

测试

- 方式三:

使用注解实现

注解实现的增强类

package pointcut;


import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class AnnotationPointcut {
    @Before("execution(* service.UserServiceImpl.*(..))")
    public void before() {
        System.out.println("---------方法执行前---------");
    }

    @After("execution(* service.UserServiceImpl.*(..))")
    public void after() {
        System.out.println("---------方法执行后---------");
    }

    @Around("execution(* service.UserServiceImpl.*(..))")
    public void around(ProceedingJoinPoint jp) throws Throwable {
        System.out.println("环绕前");
        System.out.println("签名:" + jp.getSignature());
        //执行目标方法proceed
        Object proceed = jp.proceed();
        System.out.println("环绕后");
        System.out.println(proceed);
    }
}

配置beans.xml

<?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"
       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">

    <!--第三种方式:注解实现-->
    <bean id="annotationPointcut" class="pointcut.AnnotationPointcut"/>
    <aop:aspectj-autoproxy/>

    <!--
        通过aop命名空间的<aop:aspectj-autoproxy/>声明自动为spring容器中那些配置@aspectJ切面的bean创建代理,织入切面。当然,spring
        在内部依旧采用AnnotationAwareAspectJAutoProxyCreator进行自动代理的创建工作,但具体实现的细节已经被<aop:aspectj-autoproxy/>隐藏起来了

        <aop:aspectj-autoproxy/>有一个proxy-target-class属性,默认为false,表示使用jdk动态代理织入增强,当配为
        <aop:aspectj-autoproxy poxy-target-class="true"/>
        时,表示使用CGLib动态代理技术织入增强。不过即使proxy-target-class设置为false,如果目标类没有声明接口,则spring将自动使用CGLib动态代理。
    -->
</beans>

测试

10、整合MyBatis

回顾

- 导入相关依赖

<dependencies>
        <!--        Spring相关-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.12</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.3.12</version>
        </dependency>

        <!--        spring整合mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.6</version>
        </dependency>

        <!--        Lombok  减少get/set方法-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.22</version>
        </dependency>

        <!--        测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>5.8.1</version>
            <scope>compile</scope>
        </dependency>

        <dependency>
            <groupId>javax.annotation</groupId>
            <artifactId>javax.annotation-api</artifactId>
            <version>1.3.2</version>
        </dependency>

        <!--        aspectJ AOP 织入器-->
        <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.7</version>
        </dependency>

        <!--        mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.7</version>
        </dependency>

        <!--        mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.25</version>
        </dependency>


    </dependencies>
    
    <!--配置Maven静态资源过滤问题!-->
    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>

- 编写实体类 User

package pojo;


import lombok.Data;

@Data
public class User {
    private int id;  //id
    private String name;   //姓名
    private String pwd;   //密码
}

- 编写mybatis配置文件 mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

    <typeAliases>
        <package name="pojo"/>
    </typeAliases>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=utf8"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="mapper/UserMapper.xml"/>
    </mappers>
</configuration>

- 编写实体接口

package mapper;

import pojo.User;

import java.util.List;

public interface UserMapper {
    public List<User> selectUser();
}

- 对应的mapper映射文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="mapper.UserMapper">

    <select id="selectUser" resultType="User">
        select *
        from user
    </select>

</mapper>

- 编写工具类
(可写可不写,后面test中写也可以)

package utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

public class MybatisUtils {
    static SqlSessionFactory sqlSessionFactory = null;
    static {
        try {
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static SqlSession getSqlSession() {
        return sqlSessionFactory.openSession();
    }
}

- 测试

import mapper.UserMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import pojo.User;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class MyTest {

    @Test
/*    public void selectUser() {
        //1.获取SqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        //2.执行SQL
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = mapper.selectUser();
        for (User user : userList) {
            System.out.println(user);
        }
        //关闭sqlSession
        sqlSession.close();
    }*/

    public void selectUser() throws IOException {

        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();

        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        List<User> userList = mapper.selectUser();
        for (User user : userList) {
            System.out.println(user);
        }

        sqlSession.close();
    }
}

回顾完后

- 整合方法一:

- 导入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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--配置数据源:数据源有非常多,可以使用第三方的,也可使使用Spring的-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url"
                  value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=utf8"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean>

    <!--配置SqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <!--关联Mybatis-->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <property name="mapperLocations" value="classpath:mapper/*.xml"/>
    </bean>

    <!--注册sqlSessionTemplate , 关联sqlSessionFactory-->
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <!--利用构造器注入-->
        <constructor-arg index="0" ref="sqlSessionFactory"/>
    </bean>

    <bean id="userMapper" class="mapper.UserDaoImpl">
        <property name="sqlSession" ref="sqlSession"/>
    </bean>
</beans>

这里就可以删除mybatis-config.xml中的除了别名和设置以外的标签了。

- 创建实现类

package mapper;

import org.mybatis.spring.SqlSessionTemplate;
import pojo.User;

import java.util.List;

public class UserMapperImpl implements UserMapper {

    //sqlSession不用我们自己创建了,Spring来管理
    private SqlSessionTemplate sqlSession;

    public void setSqlSession(SqlSessionTemplate sqlSession) {
        this.sqlSession = sqlSession;
    }

    public List<User> selectUser() {
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        return mapper.selectUser();
    }
}

这里就可以删除以前mybatis中的测试代码了

重新写,如下:

@Test
    public void test2(){
        ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("beans.xml");
        UserMapper mapper = (UserMapper) classPathXmlApplicationContext.getBean("userMapper");
        List<User> user = mapper.selectUser();
        System.out.println(user);
    }

- 整合方法二:

将上面写的UserDaoImpl修改一下

public class UserDaoImpl extends SqlSessionDaoSupport implements UserMapper {
    public List<User> selectUser() {
        UserMapper mapper = getSqlSession().getMapper(UserMapper.class);
        return mapper.selectUser();
    }
}

修改bean的配置

    <bean id="userMapper" class="mapper.UserMapperImpl">
        <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
    </bean>

测试完成。

11、声明式事务

  • 就是把一系列的动作当成一个独立的工作单元,这些动作要么全部完成,要么全部不起作用

事务四个属性ACID

原子性(atomicity)

事务是原子性操作,由一系列动作组成,事务的原子性确保动作要么全部完成,要么完全不起作用

一致性(consistency)

一旦所有事务动作完成,事务就要被提交。数据和资源处于一种满足业务规则的一致性状态中

隔离性(isolation)

可能多个事务会同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏

持久性(durability)

事务一旦完成,无论系统发生什么错误,结果都不会受到影响。通常情况下,事务的结果被写到持久化存储器中

新建一个整合了mybatis的maven Spring 项目

拷贝上面案例的代码(UserMapper,UserMapper.xml,UserMapperImpl,User,applicationContext.xml,beans.xml,mybatis-config.xml,MyTest

给UserMapper接口新增两个方法,删除和增加用户

//添加一个用户
int addUser(User user);
 
//根据id删除用户
int deleteUser(int id);

UserMapper.xml

 <insert id="addUser" parameterType="com.kuang.pojo.User">
 insert into user (id,name,pwd) values (#{id},#{name},#{pwd})
 </insert>
 
 <delete id="deleteUser" parameterType="int">
 deletes from user where id = #{id}
</delete>

接口的实现类

public class UserDaoImpl extends SqlSessionDaoSupport implements UserMapper {
 
    //增加一些操作
    public List<User> selectUser() {
        User user = new User(4,"小明","123456");
        UserMapper mapper = getSqlSession().getMapper(UserMapper.class);
        mapper.addUser(user);
        mapper.deleteUser(4);
        return mapper.selectUser();
    }
 
    //新增
    public int addUser(User user) {
        UserMapper mapper = getSqlSession().getMapper(UserMapper.class);
        return mapper.addUser(user);
    }
    //删除
    public int deleteUser(int id) {
        UserMapper mapper = getSqlSession().getMapper(UserMapper.class);
        return mapper.deleteUser(id);
    }
 
}

测试

@Test
public void test2(){
    ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
    UserMapper mapper = (UserMapper) context.getBean("userDao");
    List<User> user = mapper.selectUser();
    System.out.println(user);
}

报错:sql异常,delete写错了
结果 :插入成功!

Spring中的事务管理

Spring在不同的事务管理API之上定义了一个抽象层,使得开发人员不必了解底层的事务管理API就可以使用Spring的事务管理机制。Spring支持编程式事务管理和声明式的事务管理。

编程式事务管理

将事务管理代码嵌到业务方法中来控制事务的提交和回滚

缺点:必须在每个事务操作业务逻辑中包含额外的事务管理代码

声明式事务管理

一般情况下比编程式事务好用。

将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理。

将事务管理作为横切关注点,通过aop方法模块化。Spring中通过Spring AOP框架支持声明式事务管理。

使用Spring管理事务,注意头文件的约束导入

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

JDBC事务

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
 </bean>
<!--配置事务通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <!--配置哪些方法使用什么样的事务,配置事务的传播特性-->
        <tx:method name="add" propagation="REQUIRED"/>
        <tx:method name="delete" propagation="REQUIRED"/>
        <tx:method name="update" propagation="REQUIRED"/>
        <tx:method name="search*" propagation="REQUIRED"/>
        <tx:method name="get" read-only="true"/>
        <tx:method name="*" propagation="REQUIRED"/>
    </tx:attributes>
</tx:advice>

添加aop命名空间

       xmlns:aop="http://www.springframework.org/schema/aop"

      http://www.springframework.org/schema/aop
      http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
<!--配置aop织入事务-->
<aop:config>
    <aop:pointcut id="txPointcut" expression="execution(* mapper.*.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
</aop:config>

换成正确的SQL再次测试

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值