Spring

Spring

雏形:interface 21

理念:化简现有技术

依赖:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>6.0.9</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>6.0.9</version>
</dependency>

特点:IoC和AOP,支持事务

IoC

控制反转

  • 化主动为被动
  • 不用去主动创建对象,而是被动接收对象
  • 从程序员控制接口实现类转变为用户控制接口实现类的创建
  • 说白了,就是一个接口有多个实现类,在下一层调用接口时,给接口设置一个set方法,然后我们可以根据需要的实现类new一下之后赋给set

HelloSpring

public class Hello {
    private String name;

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

    public void show(){
        System.out.println("Hello, " + 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就是java对象 , 由Spring创建和管理-->
    <bean id="hello" class="com.lu.pojo.Hello">
        <property name="name" value="lct"/>
    </bean>

</beans>

测试

public static void main(String[] args) {
    ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
    Hello hello = (Hello) context.getBean("hello");
    hello.show();
    System.out.println(hello.getName());
}

IoC创建对象

  • 在配置文件加载的时候,其管理的对象都已经初始化了
  • 默认走无参构造
  • 如果走有参构造不改为对应的形式,则会报错

对象

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);
    }
}

无参构造

<?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="com.lu.pojo.User">
        <property name="name" value="LCT"/>
    </bean>

</beans>

有参构造

<?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="com.lu.pojo.User">
        <constructor-arg index="0" value="lct"/>
    </bean>

    <bean id="user" class="com.lu.pojo.User">
        <constructor-arg name="name" value="lct"/>
    </bean>

</beans>

测试

public static void main(String[] args) {
    ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
    User user = (User) context.getBean("user");
    user.show();
}

Spring配置

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

    <bean id="user" class="com.lu.pojo.User">
        <constructor-arg index="0" value="lct"/>
    </bean>

    <alias name="user" alias="uu"/>

</beans>

bean

<!--
   id 是bean的标识符,要唯一,如果没有配置id,name就是默认标识符
   如果配置id,又配置了name,那么name是别名
   name可以设置多个别名,可以用逗号,分号,空格隔开
   如果不配置id和name,可以根据applicationContext.getBean(.class)获取对象;

class是bean的全限定名=包名+类名
-->
<bean id="user" name="uu1 uu2, uu3; uu4" class="com.lu.pojo.User">
    <constructor-arg index="0" value="lct"/>
</bean>
public static void main(String[] args) {
    ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
    for (int i = 1; i <= 4; i++) {
        String name = "uu" + i;
        User user = (User) context.getBean(name);
        user.show();
    }
}

import

  • 引入多个配置
<import resource="{path}/beans.xml"/>

DI依赖注入

对象

Address.java

public class Address {

    private String address;

    public String getAddress() {
        return address;
    }

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

Student.java

import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

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 String getName() {
        return name;
    }

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

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

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

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

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

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

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

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

    public void show(){
        System.out.println("name="+ name
                + ",address="+ address.getAddress()
                + ",books="
        );
        for (String book:books){
            System.out.print("<<"+book+">>\t");
        }
        System.out.println("\n爱好:"+hobbys);
        System.out.println("card:"+card);
        System.out.println("games:"+games);
        System.out.println("wife:"+wife);
        System.out.println("info:"+info);
    }
}

set注入

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="addr" class="com.lu.pojo.Address">
        <property name="address" value="suzhou"/>
    </bean>

    <bean id="student" class="com.lu.pojo.Student">
        <property name="name" value="lct"/>
        <property name="address" ref="addr"/>
        <property name="books">
            <array>
                <value>西游记</value>
                <value>红楼梦</value>
                <value>水浒传</value>
            </array>
        </property>
        <property name="hobbys">
            <list>
                <value>Play</value>
                <value>Code</value>
                <value>Sleep</value>
            </list>
        </property>
        <property name="card">
            <map>
                <entry key="post" value="12364185610"/>
                <entry key="construct" value="8946841560"/>
            </map>
        </property>
        <property name="games">
            <set>
                <value>LOL</value>
                <value>COC</value>
                <value>GTA</value>
                <value>LOL</value>
            </set>
        </property>
        <property name="wife">
            <null/>
        </property>
        <property name="info">
            <props>
                <prop key="学号">1231656</prop>
                <prop key="性别"></prop>
                <prop key="姓名">lct</prop>
            </props>
        </property>
    </bean>
</beans>

测试

public static void main(String[] args) {
    ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
    Student student = (Student) context.getBean("student");
    student.show();
}

结果
img

命名空间注入

对象

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

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

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

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

p

  • 走无参构造
  • 导入约束:xmlns:p="http://www.springframework.org/schema/p"
<?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:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="user" class="com.lu.pojo.User" p:name="lct" p:age="18"/>

</beans>

c

  • 走有参构造
  • 导入约束:xmlns:c="http://www.springframework.org/schema/c"
<?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:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="user" class="com.lu.pojo.User" c:name="lct" c:age="18"/>

</beans>

测试

public static void main(String[] args) {
    ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
    User user = (User) context.getBean("user");
    System.out.println(user);
}

bean作用域

Singleton

也就是只new一次对象,之后getBean的都直接获取第一次new的对象

Prototype

原型模式也就是在之后的getBean时重新new一个对象

Request

每次HTTP请求都会创建一个新的bean,bean只在request内有效

Session

一个HTTP Session一个bean

bean的自动装配

针对一个自定义对象的属性中有别的自定义对象

测试环境

public class User {
    private Cat cat;
    private Dog dog;
    private String name;

    public Cat getCat() {
        return cat;
    }

    public Dog getDog() {
        return dog;
    }

    public String getName() {
        return name;
    }

    public void setCat(Cat cat) {
        this.cat = cat;
    }

    public void setDog(Dog dog) {
        this.dog = dog;
    }

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

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

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

byName

  • 根据bean_id匹配属性变量名
  • 会自动匹配对象中与未装配的set方法同名的bean_id
  • 缺点是set方法后跟随的变量名一定要和bean_id名字相同
<?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="Dog"/>
    <bean id="cat" class="Cat"/>

    <bean id="user" class="User" autowire="byName">
        <property name="name" value="lct"/>
    </bean>
</beans>

byType

  • 会自动匹配对象中与未装配的set方法同类型的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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="dog" class="Dog"/>
    <bean id="cat" class="Cat"/>

    <bean id="user" class="User" autowire="byType">
        <property name="name" value="lct"/>
    </bean>
</beans>

Autowired

  • 导入约束
    • xmlns:context="http://www.springframework.org/schema/context"
    • http://www.springframework.org/schema/context
    • http://www.springframework.org/schema/context/spring-context.xsd
  • 开启注解支持:<context:annotation-config/>
  • 可在属性上用,也可以在set方法上用
  • 写了Autowired可以不用set方法
  • 使用了Autowired的属性需要在xml中配置了bean且符合byName规范
public class User {
    @Autowired
    private Cat cat;
    @Autowired
    private Dog dog;
    private String name;

    public Cat getCat() {
        return cat;
    }

    public Dog getDog() {
        return dog;
    }

    public String getName() {
        return name;
    }
}
<?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/>

    <bean id="dog" class="Dog"/>
    <bean id="cat" class="Cat"/>
    <bean id="user" class="User"/>

</beans>

属性值为null

@Nullable@Autowired(required = false)

Qualifier

  • Autowired识别失败
    • 存在多个Dog类的bean且名字都有一定程度的自定义
  • 则可以通过Qualifier显示定义bean_id匹配
@Autowired
@Qualifier(value = "dog22")
private Dog dog;
<bean id="dog22" class="Dog"/>
<bean id="dog2333" class="Dog"/>

Resource

没import出来,不知道为啥

测试

public static void main(String[] args) {
    ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
    User user = (User) context.getBean("user");
    user.getCat().shout();
    user.getDog().shout();
}

注解开发

@Component 		# 配置了一个bean
@Value("lct") # 为bean的property配了值
@Repository		# 配置了一个bean(dao)
@Service			# 配置了一个bean(service)
@Controller		# 配置了一个bean(controller)
@Scope("") 		# 配置bean的作用域

使用Java配置Spring

@Configuration
public class MyConfig {
    @Bean
    public User user() {
        return new User();
    }
}
  • @Configuration代表它为一个配置文件
  • @ComponentScan("")可以扫描包
  • @Import(.class)添加别的配置类
  • @Bean代表注册了一个bean,它的id就为方法名

测试

public static void main(String[] args) {
    ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
    User user = (User) context.getBean("user");
    System.out.println(user.getName());
}

AOP

img

代理模式

保证真实角色操作的前提下,处理公共操作

静态代理

  • 抽象角色:一般使用接口或抽象类实现(出租房屋
  • 真实角色:被代理的角色(房东,想要出租房屋,但不想处理公共事务,如看房签合同)
  • 代理角色:代理真实角色并配备附属操作(想帮房东出租房屋同时处理相关的公共事务)
  • 客户:访问代理对象的人(我找不到房东租房,所以找中介完成)

好处:

  1. 真实角色的操作更纯粹,不用关注一些公共操作
  2. 公共操作交给代理角色,分工明确
  3. 公共操作的业务发生扩展或者变化时,方便集中管理

缺点:

  1. 一个真实角色就会产生一个代理角色

动态代理

  • 代理类是自动生成的
  • 一个动态代理可以代理多个类,代理的是接口!
  • 相关的类
    • Proxy
    • InvocationHandler

样例

UserService.java(抽象角色)

public interface UserService {
    void add();
    void delete();
    void update();
    void query();
}

UserServiceImpl.java(真实角色)

public class UserServiceImpl implements UserService {
    @Override
    public void add() {
        System.out.println("add了一个用户");
    }

    @Override
    public void delete() {
        System.out.println("delete了一个用户");
    }

    @Override
    public void update() {
        System.out.println("update了一个用户");
    }

    @Override
    public void query() {
        System.out.println("query了一个用户");
    }
}

ProxyInvocationHandler.java(代理角色)

public class ProxyInvocationHandler implements InvocationHandler {
    private Object object;

    public void setObject(Object object) {
        this.object = object;
    }

    public Object getProxy() {
        return Proxy.newProxyInstance(object.getClass().getClassLoader(),
                object.getClass().getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        log(method.getName());
        Object res = method.invoke(object, args);
        return res;
    }

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

Client.java(客户)

public class Client {
    public static void main(String[] args) {
        UserServiceImpl service = new UserServiceImpl();
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        pih.setObject(service);
        UserService proxy = (UserService) pih.getProxy();
        proxy.add();
        proxy.delete();
        proxy.update();
        proxy.query();
    }
}

AOP实现

依赖:

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.19</version>
    <scope>runtime</scope>
</dependency>

导入约束:

  • xmlns:aop="http://www.springframework.org/schema/aop"
  • http://www.springframework.org/schema/aop
  • http://www.springframework.org/schema/aop/spring-aop.xsd

环境

UserService.java & UserServiceImpl.java

public interface UserService {
    void add();
    void delete();
    void update();
    void query();
}

public class UserServiceImpl implements UserService{
    @Override
    public void add() {
        System.out.println("add");
    }

    @Override
    public void delete() {
        System.out.println("delete");
    }

    @Override
    public void update() {
        System.out.println("update");
    }

    @Override
    public void query() {
        System.out.println("query");
    }
}

方式一

  • 使用Spring实现

Log.java & AfterLog.java

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

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("[debug]" + target.getClass().getName() +" 的 "+method.getName()+" 方法, " +"返回值: "+returnValue);
    }
}

applicationContext.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="com.lu.service.UserServiceImpl"/>
    <bean id="log" class="com.lu.log.Log"/>
    <bean id="afterLog" class="com.lu.log.AfterLog"/>

    <!--aop的配置-->
    <aop:config>
        <!--切入点 expression:表达式匹配要执行的方法-->
        <aop:pointcut id="pointcut" expression="execution(* com.lu.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>

方式二

  • 自定义类实现AOP

DiyPointCut.java

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

applicationContext.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="com.lu.service.UserServiceImpl"/>
    <bean id="diy" class="com.lu.diy.DiyPointCut"/>

    <!--aop的配置-->
    <aop:config>
        <!--第二种方式:使用AOP的标签实现-->
        <aop:aspect ref="diy">
            <aop:pointcut id="diypt" expression="execution(* com.lu.service.UserServiceImpl.*(..))"/>
            <aop:before method="before" pointcut-ref="diypt"/>
            <aop:after method="after" pointcut-ref="diypt"/>
        </aop:aspect>
    </aop:config>
</beans>

方式三

  • 注解实现AOP

AnnotationPointCut.java

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

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

    @Around("execution(* com.lu.service.UserServiceImpl.*(..))")
    public void around(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("环绕前");
        System.out.println("签名: " + pjp.getSignature());
        //执行目标方法proceed
        Object proceed = pjp.proceed();
        System.out.println("环绕后");
        System.out.println(proceed);
    }
}
<?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="com.lu.service.UserServiceImpl"/>

    <bean id="apt" class="com.lu.diy.AnnotationPointCut"/>
    <aop:aspectj-autoproxy/>
</beans>

测试

MyTest.java

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        // 代理类代理的是接口
        UserService userService = context.getBean("userService", UserService.class);
        userService.add();
        userService.delete();
        userService.update();
        userService.query();
    }
}

整合Mybatis

依赖:

<!--mybatis-->
<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <version>8.0.32</version>
</dependency>
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.7</version>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>RELEASE</version>
</dependency>
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>3.0.2</version>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.24</version>
</dependency>

环境

User.java

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private int id;
    private String name;
    private String pwd;
}

Mybatis回顾

UserMapper.java

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

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="com.lu.pojo"/>
    </typeAliases>
  	<environments default="development">
       <environment id="development">
           <transactionManager type="JDBC"/>
           <dataSource type="POOLED">
               <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
               <property name="url" value="jdbc:mysql://localhost:3306/mybatis?autoReconnect=true&amp;useUnicode=true&amp;characterEncoding=utf8&amp;serverTimezone=GMT%2B8"/>
               <property name="username" value="root"/>
               <property name="password" value="lu123"/>
           </dataSource>
       </environment>
   </environments>

   <mappers>
       <package name="UserMapper.xml"/>
   </mappers>
</configuration>

UserMapper.xml

<?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="com.lu.dao.UserMapper">
    <select id="selectUser" resultType="user">
        select * from mybatis.user
    </select>
</mapper>

MyTest.java

@Test
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-Mybatis

applicationContext.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">

    <!--配置数据源:数据源有非常多,可以使用第三方的,也可使使用Spring的-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mybatis?autoReconnect=true&amp;useUnicode=true&amp;characterEncoding=utf8&amp;serverTimezone=GMT%2B8"/>
        <property name="username" value="root"/>
        <property name="password" value="lu123"/>
    </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:com/lu/dao/*.xml"/>
    </bean>

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

    <bean id="userMapper" class="com.lu.dao.UserMapperImpl">
        <property name="sqlSession" ref="sqlSession"/>
    </bean>
</beans>

UserMapperImpl.java

public class UserMapperImpl implements UserMapper{
    private SqlSessionTemplate sqlSession;

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

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

SqlSessionDaoSupport

applicationContext.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">

    <!--配置数据源:数据源有非常多,可以使用第三方的,也可使使用Spring的-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mybatis?autoReconnect=true&amp;useUnicode=true&amp;characterEncoding=utf8&amp;serverTimezone=GMT%2B8"/>
        <property name="username" value="root"/>
        <property name="password" value="lu123"/>
    </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:com/lu/dao/*.xml"/>
    </bean>

    <bean id="userMapper" class="com.lu.dao.UserMapperSupport">
        <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
    </bean>
</beans>

UserMapperSupport.java

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

测试

MyTest.java

@Test
public void spring_mybatis() {
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
    System.out.println(userMapper.selectUser());
}

Spring事务

声明式事务

  • AOP横切到项目中,不影响原有代码

环境

UserMapper.java

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

    void addUser(User user);

    void deleteUser(int id);
}

UserMapperSupport.java

public class UserMapperSupport extends SqlSessionDaoSupport implements UserMapper{
    @Override
    public List<User> selectUser() {
        UserMapper mapper = getSqlSession().getMapper(UserMapper.class);
        mapper.addUser(new User(6, "kk", "hh"));
        mapper.deleteUser(6);
        return mapper.selectUser();
    }

    @Override
    public void addUser(User user) {
        getSqlSession().getMapper(UserMapper.class).addUser(user);
    }

    @Override
    public void deleteUser(int id) {
        getSqlSession().getMapper(UserMapper.class).deleteUser(id);
    }
}

未处理事务

UserMapper.xml

<?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="com.lu.dao.UserMapper">
    <select id="selectUser" resultType="user">
        select * from mybatis.user
    </select>
    <insert id="addUser" parameterType="user">
        insert into mybatis.user values (#{id},#{name},#{pwd})
    </insert>

    <delete id="deleteUser" parameterType="int">
        deletes from user where id = #{id}
    </delete>
</mapper>
  • delete语句存在问题

测试

@Test
public void spring_mybatis() {
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
    System.out.println(userMapper.selectUser());
}
  • 结果会发现,delete执行失败退出程序
  • 但add却成功执行了
  • 我们希望,只要流程中的一环出了问题,那其他环上的操作也不能成功

声明式事务

导入约束:

  • xmlns:tx="http://www.springframework.org/schema/tx"
  • http://www.springframework.org/schema/tx
  • http://www.springframework.org/schema/tx/spring-tx.xsd

applicationContext.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:tx="http://www.springframework.org/schema/tx"
       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
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!--配置数据源:数据源有非常多,可以使用第三方的,也可使使用Spring的-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://43.142.235.221:3310/mybatis?autoReconnect=true&amp;useUnicode=true&amp;characterEncoding=utf8&amp;serverTimezone=GMT%2B8"/>
        <property name="username" value="root"/>
        <property name="password" value="lu123"/>
    </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:com/lu/dao/*.xml"/>
    </bean>

    <bean id="userMapper" class="com.lu.dao.UserMapperSupport">
        <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
    </bean>

    <!--配置声明式事务-->
    <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="query" read-only="true"/>
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>
    <aop:config>
        <aop:pointcut id="txPointCut" expression="execution(* com.lu.dao.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
    </aop:config>
</beans>
  • 此时经过测试可以发现,由于delete语句出现问题,add语句同样没有生效
  • 因此事务配置成功
posted @   James-Allen  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端
点击右上角即可分享
微信分享提示