玄子Share - spring-framework 6.0.9 学习笔记

玄子Share - spring-framework 6.0.9 学习笔记

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UA2E1zOO-1684946000258)(./assets/spring.jpg)]

官网

官网 https://spring.io/

参考文档 https://docs.spring.io/spring-framework/reference/core/beans/factory-scopes.html

API 文档 https://docs.spring.io/spring-framework/docs/current/javadoc-api/

Maven

Spring Maven 地址 https://mvnrepository.com/artifact/org.springframework/spring-webmvc

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

运行环境

  • JDK:Java17+(Spring6 要求JDK最低版本是 Java17 需要配置好环境变量)

  • Maven:3.9+

  • Spring:6.0.9

  • 开发工具:IDEA 2023.1

IOC

ioc 是 Spring 的核心,控制反转,即为把实际调用权限交给用户

package com.xuanzi;

import com.xuanzi.dao.impl.UserDaoImplMySQL;
import com.xuanzi.dao.impl.UserDaoImplSqlServer;
import com.xuanzi.services.UserService;
import com.xuanzi.services.impl.UserServiceImpl;

public class Main {
    public static void main(String[] args) {
        UserServiceImpl userService = new UserServiceImpl();
        userService.setUserDao(new UserDaoImplMySQL());
        userService.setUserDao(new UserDaoImplSqlServer());
        userService.selectUser();
    }
}
package com.xuanzi.services.impl;

import com.xuanzi.dao.UserDao;
import com.xuanzi.entity.User;
import com.xuanzi.services.UserService;

import java.util.List;

public class UserServiceImpl implements UserService {
//    UserDao daoImplMySQL = new UserDaoImplMySQL();
//    UserDao daoImplSqlServer = new UserDaoImplSqlServer();
//    不再使用传统的 方法 固定实现,而是通过 set 方法 把这个权限交给用户
    UserDao userDao;

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

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

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

IDEA 可以直接右键新建 XML配置文件 ==> Spring 配置 可以直接生成 Spring 专属 xml 文件

alias 别名

<bean id="user" class="com.xuanzi.spring.User"/>
<alias name="user" alias="user2"/>
<!--类别名-->
  • name:对应类 ID
  • alias:别名

import 导入

<import resource="beans.xml"/>
  • import:导入外部 xml
  • resource:文件名

bean 对象创建

基础 User 类(带有,封装,构造)

package com.xuanzi.spring;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    String name;
}
package com.xuanzi.spring;

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

public class TestUser {
    @Test
    public void testUser() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
        // xml 的文件名
        User user = ac.getBean("user", User.class);
        // getBean 类名称,即 id 的名称 User.class 类的类型
        System.out.println(user);
    }
}
<?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.xuanzi.spring.User"/>
</beans>
  • bean:实例类
  • id:类名称(变量名)
  • class:类文件的全限定位置

有参构造

package com.xuanzi.spring;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    String name;

    public User(String name) {
        this.name = name;
    }
}
<bean id="user" class="com.xuanzi.spring.User">
    <constructor-arg index="0" value="玄子"/>
    <!-- 下标赋值 -->
    <constructor-arg type="java.lang.String" value="玄子"/>
    <!-- 类型赋值 -->
    <constructor-arg name="name" value="玄子"/>
    <!-- 直接通过参数名赋值 -->
</bean>
  • constructor-arg:构造函数参数
  • index:参数下标(从0开始)
  • value:参数值
  • type:参数类型
  • name:参数名称

name 别名

在 bean 标签内可以直接使用 name 属性指定别名

<bean id="user" class="com.xuanzi.spring.User" name="user2,user3"/>
  • name:类的别名(可以有多个别名,使用空格或者,分隔)

P / C 命名空间

在 beans 标签内插入下方两条属性

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

使用 IDEA 打出 xmlns: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"
       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="user2" class="com.xuanzi.spring.User" p:name="玄子"/>
        <!--    p:命名空间:属性-->
        <bean id="user3" class="com.xuanzi.spring.User" c:name="玄子"/>
        <!--    c:命名空间:构造器-->
</beans>
  • xmlns:p:属性的语法规范(property)
  • xmlns:c:构造器的语法规范(constructor)
  • p: :属性名称是name 直接设置值
  • c: :构造参数是name 直接设置值

依赖注入

set 方法注入

不论是,类或是属性都需要依赖于 set 方法进行注入,所以要提前写好 get 和 set 方法

接下来都使用这个 User 类演示(这里使用了lombok)三个注解包含了,有参构造,无参构造,以及所有属性的 get 和 set 方法

package com.xuanzi.spring;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

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

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private String name;
    private String wife;
    private Address address;
    private String[] books;
    private List<String> hobbies;
    private Set<String> games;
    private Map<String, String> cards;
    private Properties info;

    public User(String name) {
        this.name = name;
    }
}
package com.xuanzi.spring;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Address {
    String address;
}
<bean id="user" class="com.xuanzi.spring.User"></beans>

基本数据类型

<property name="name" value="玄子"/>
  • name:属性名称
  • value:属性值

引用数据类型

User 类中的 Address 是别的类属性引用类型

<bean id="address" class="com.xuanzi.spring.Address">
    <property name="address" value="漯河"/>
</bean>
<property name="address" ref="address"/>
  • name:属性名
  • ref:引用数据类型
  • 这里 ref 的值即为 Address 类 bean 的 id 值

array

<property name="books">
    <array>
        <value>红楼梦</value>
        <value>三国演义</value>
        <value>水浒传</value>
    </array>
</property>
  • array:数组类型
  • value:属性值
  • 顺序即为下标

list

<property name="hobbies">
    <list>
        <value></value>
        <value></value>
        <value>rap</value>
        <value>篮球</value>
    </list>
</property>
  • list:集合类型
  • value:属性值
  • 顺序即为下标

map

<property name="cards">
    <map>
        <entry key="身份证" value="23131323141"/>
        <entry key="手机号" value="5453453454"/>
        <entry key="学号" value="534534634634"/>
    </map>
</property>
  • map:类型
  • entry:键值对
  • key:键
  • value:值

set

<property name="games">
    <set>
        <value>aa</value>
        <value>bb</value>
        <value>cc</value>
        <value>dd</value>
    </set>
</property>
  • set:set 集合
  • value:值

null

属性值为空

<property name="wife" value=""/>
<property name="wife">
    <null/>
</property>
  • 可直接设置 value 为"" 表示字符串的空值
  • 如果表示为 null 可直接使用 <null/>标签

props

配置 可有多个 类似于 map

<property name="info">
    <props>
        <prop key="身高">180</prop>
        <prop key="体重">130</prop>
    </props>
</property>
  • props:配置表示多个
  • prop:单个配置
  • key:键
  • 值写在标签里面

这个属于特殊类型 类似于 Mybatis 连接数据的 property 配置

<dataSource type="POOLED">
    <property name="driver" value="${driver}"/>
    <property name="url" value="${url}"/>
    <property name="username" value="${username}"/>
    <property name="password" value="${password}"/>
</dataSource>

bean 作用域

范围描述
singleton(默认)对于每个 Spring IoC 容器,将单个 bean 定义限定为单个对象实例。
prototype将单个 bean 定义的范围限定为任意数量的对象实例。
request将单个 bean 定义的范围限定为单个 HTTP 请求的生命周期。也就是说,每个 HTTP 请求都有自己的 bean 实例,该实例是在单个 bean 定义的基础上创建的。仅在 web 感知Spring 的上下文中有效。ApplicationContext
session将单个 bean 定义的范围限定为 HTTP 的生命周期。仅在 web 感知 Spring 的上下文中有效。Session ApplicationContext
applicatio将单个 bean 定义的范围限定为的生命周期。仅在支持 web 的 Spring 的上下文中有效。ServletContext ApplicationContext
nwebsocket将单个 bean 定义的范围限定为的生命周期。仅在支持 web 的 Spring 的上下文中有效。WebSocket ApplicationContext

单例模式

不管创建几个对象始终指向一个对象

<bean id="user" class="com.xuanzi.spring.User" p:name="玄子"/>
  • 默认即为 单例模式

原型模式

每次创建对象,都会产生一个新的对象

<bean id="user" class="com.xuanzi.spring.User" p:name="玄子" scope="prototype"/>
<!-- 原型模式 -->
  • scope:范围
  • prototype:原型模式

其他

其他的 request,session,applicatio,nwebsocket 这些只能在 web 开发中使用

自动装配

package com.xuanzi.spring;

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

public class TestUser {
    @Test
    public void testUser() {
        ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
        User user = ac.getBean("user", User.class);
//        User user2 = ac.getBean("user3", User.class);
//        System.out.println(user.hashCode());
//        System.out.println(user2.hashCode());
//        System.out.println(user==user2);
        user.getXiaoHong().say();
        user.getXiaoMing().say();
    }
}
package com.xuanzi.spring;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    String name;
    XiaoHong xiaoHong;
    XiaoMing xiaoMing;

    public User(String name) {
        this.name = name;
    }
}
package com.xuanzi.spring;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class XiaoHong {
    String name;

    public void say() {
        System.out.println(this.name + ":说话了");
    }
}
package com.xuanzi.spring;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class XiaoMing {
    String name;

    public void say() {
        System.out.println(this.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: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.xuanzi.spring.User" autowire="byType">
        <property name="name" value=""/>
        <!--        <property name="xiaoHong" ref="xiaoHong"/>-->
        <!--        <property name="xiaoMing" ref="xiaoMing"/>-->
    </bean>
    <bean id="xiaoHong" class="com.xuanzi.spring.XiaoHong" p:name="小红"/>
    <bean id="xiaoMing" class="com.xuanzi.spring.XiaoMing" p:name="小明"/>
</beans>
  • autowire:自动装配
  • byType:需要保证所有的 bean 的 class 唯一,并且这个 bean 需要和自动注入的属性类型一致
  • byName:需要保证所有的 bean 的 id 唯一,并且这个 bean 需要和自动注入的属性的 set 方法值一致

注解自动装配

需要提前引入,命名空间与约束

xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/context"
xsi:schemaLocation="https://www.springframework.org/schema/context/spring-context.xsd"
<context:annotation-config/>

IDEA 可以只打最后面的标签 会自动补全命名空间

<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>
package com.xuanzi.spring;

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

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    
    String name;
    @Autowired
    @Qualifier("xiaoHong2")
    XiaoHong xiaoHong;
    @Autowired(required = false)
    XiaoMing xiaoMing;

    public User(String name) {
        this.name = name;
    }
}
  • @Autowired:使用这个注解 可忽略 set 方法
    • 当注入在IoC容器中该类型只有一个时,就通过byType进行装配
    • 当注入容器存在多个同一类型的对象时,就是根据byName进行装配
  • @Qualifier( ):相当于预设指定唯一 bean id,里面填写对应 bean id
  • @Nullable:属性可为 null
  • @Autowired(required = false):与 @Nullable 一样允许属性为 null
public @interface Autowired {
    boolean required() default true;
}

使用注解开发

同样需要引入 命名空间与约束

<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>
<context:component-scan base-package="com.xuanzi.entity"/>
<!-- 扫描包下的所有类(组件),生效注解
package com.xuanzi.entity;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Component
public class User {
    @Value("玄子")
    String name;
}

  • @Component:组件(生效配置)等于 bean 标签
  • @Value( ):属性值,等于 property 标签 set 方法上的 value 高于属性

衍生注解

@Component 有几个衍生注解,我们在web开发中,会按照mvc三层架构分层!

  • dao【@Repository】
  • service【@Service】
  • controller【@Controller】

这四个注解功能都是一样的,都是代表将某个类注册到Spring中,装配 Bean

作用域注解

@Scope("singleton")
public class User {
    @Value("玄子")
    String name;
}
  • @Scope:作用域,prototype 原型模式

xml与注解:

  • xml更加万能,适用于任何场合!维护简单方便。
  • 注解不是自己类使用不了,维护相对复杂!

xml 与注解最佳实践:

  • xml用来管理bean;
  • 注解只负责完成属性的注入;
  • 我们在使用的过程中,只需要注意一个问题:必须让注解生效,就需要开启注解的支持

使用 java 配置 Spring

package com.xuanzi.config;

import com.xuanzi.entity.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
// 被注册到 Spring 容器中 @Component 本身就是一个 组件
@ComponentScan("com.xuanzi.entity")
// 扫描包
@Import(BeanConfig2.class)
// 导入其他 配置文件
public class BeanConfig {
    
//    相当于 bean 标签 方法名相当于 id 返回值相当于 class
    public User user() {
        return new User();
    }
}
  • @Configuration:表示当前类为配置文件;相当于beans.xml
  • @ComponentScan(“com.xuanzi.entity”):扫描包下的类,生效注解;相当于<context:component-scan base-package="com.xuanzi.entity"/>
  • @Import(BeanConfig2.class):导入其他配置文件;相当于<import resource="applicationContext.xml"/>
  • @Bean:表示当前类被注册到 Spring 容器中;相当于<bean class="com.xuanzi.entity.User" id="user"/>
    • 方法名相当于 id
    • 返回值相当于 class

代理模式

静态代理

package com.xuanzi.spring;

public interface Rent {
    //    租房接口
     void rent();
}
package com.xuanzi.spring;

public class Host implements Rent {
    @Override
    public void rent() {
        System.out.println("房东租房子");
    }
//    房东 被代理

}
package com.xuanzi.spring;

public class Proxy implements Rent {
    // 代理 中介
    Host host;

    public Proxy(Host host) {
        this.host = host;
    }

    public Proxy() {
    }

    @Override
    public void rent() {
        setHouse();
        host.rent();
        heTong();
    }

    public void setHouse() {
        System.out.println("看房子");
    }

    public void heTong() {
        System.out.println("签合同");
    }

}
package com.xuanzi;


import com.xuanzi.spring.Host;
import com.xuanzi.spring.Proxy;

public class Main {
    public static void main(String[] args) {
        Host host = new Host();
//        host.rent();
        Proxy proxy = new Proxy(host);
        proxy.rent();
    }
}
  • 接口
  • 真实角色
  • 代理角色
  • 客户端访问代理角色

动态代理

package com.xuanzi.xuanzi_2;

public interface Rent {
    //    租房接口
     void rent();
}
package com.xuanzi.xuanzi_2;

public class Client {
    //    客户
    public static void main(String[] args) {
        Host host = new Host();
//        真实角色
        ProxyInvocationHandler proxy = new ProxyInvocationHandler();
//        代理角色现在没有
        proxy.setRent(host);
//        设置代理角色
        Rent proxy1 = (Rent) proxy.getProxy();
//       动态生成
        proxy1.rent();
    }
}
package com.xuanzi.xuanzi_2;

public class Host implements Rent {
    @Override
    public void rent() {
        System.out.println("房东租房子");
    }
//    房东 被代理

}
package com.xuanzi.xuanzi_2;

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

public class ProxyInvocationHandler implements InvocationHandler {
    //    实现 代理调用处理器
    Rent rent;

    //被代理的接口
    public Object getProxy() {
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(), this);
    }
//    生成得到代理类

    public void setRent(Rent rent) {
        this.rent = rent;
    }
//    set 传参

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        seehouse();
        return method.invoke(rent, args);
    }

    // 生成代理示例 返回结果
    public void seehouse() {
        System.out.println("中介带看房子");
    }
}
package com.xuanzi.xuanzi_2;

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

public class ProxyTemplate implements InvocationHandler {
    //    实现 调用 代理处理器
    Object target;

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


    public void setRent(Object target) {
        this.target = target;
        //    set 传参
    }


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        return method.invoke(target, args);
        // 生成代理示例 返回结果
    }
}

AOP

里面用的命名空间都可以使用 IDEA 自动导入

方式一

package com.xuanzi.service;

public class UserServiceImpl implements UserService{
    @Override
    public void addUser() {
        System.out.println("执行添加");
    }

    @Override
    public void delUser() {
        System.out.println("执行删除");
    }

    @Override
    public void updUser() {
        System.out.println("执行修改");
    }

    @Override
    public void selUser() {
        System.out.println("执行查询");
    }
}
package com.xuanzi;

import org.springframework.aop.AfterReturningAdvice;

import java.lang.reflect.Method;

public class LogAfter implements AfterReturningAdvice {
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println(target.getClass().getName() + "的" + method.getName() + "被执行了,返回了" + returnValue);
    }
}

package com.xuanzi;

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

public class LogBefore implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println(target.getClass().getName() + "的" + method.getName() + "被执行了");
    }
}
<bean class="com.xuanzi.service.UserServiceImpl" id="service"/>
<bean class="com.xuanzi.LogBefore" id="logBefore"/>
<bean class="com.xuanzi.LogAfter" id="logAfter"/>
<aop:config>
    <aop:pointcut id="pointcut" expression="execution(* com.xuanzi.service.UserServiceImpl.*(..))"/>
    <aop:advisor advice-ref="logAfter" pointcut-ref="pointcut"/>
    <aop:advisor advice-ref="logBefore" pointcut-ref="pointcut"/>
</aop:config>

方式二

package com.xuanzi;

public class LogDiy {
    public  void before(){
        System.out.println("方法执行前");
    }
    public  void after(){
        System.out.println("方法执行后");
    }
}
<bean class="com.xuanzi.LogDiy" id="logCustom"/>
<aop:config>
    <aop:aspect ref="logCustom">
        <aop:pointcut id="pointcut" expression="execution(* com.xuanzi.service.UserServiceImpl.*(..))"/>
        <aop:after method="after" pointcut-ref="pointcut"/>
        <aop:before method="before" pointcut-ref="pointcut"/>
    </aop:aspect>
</aop:config>

注解

package com.xuanzi;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
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 LogAnnotate {
    @Before("execution(* com.xuanzi.service.UserServiceImpl.*(..))")
    public void before() {
        System.out.println("方法执行前");
    }

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

    @Around("execution(* com.xuanzi.service.UserServiceImpl.*(..))")
    public void around(ProceedingJoinPoint point) throws Throwable {
        System.out.println("环绕前");
        Object proceed = point.proceed();
        Signature signature = point.getSignature();
        System.out.println(signature);
        System.out.println("环绕后");
    }
}

<bean class="com.xuanzi.LogAnnotate" id="logAnnotate"/>
<aop:aspectj-autoproxy/>

整合 Mybatis

依赖

    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.26</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>6.0.9</version>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.10.0-M1</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.13</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.33</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.20.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.20.0</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.19</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>3.0.2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>6.0.9</version>
        </dependency>
    </dependencies>

方式一

package com.xuanzi.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.ibatis.type.Alias;

@Alias("patient")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Patient {

    private int patientId;
    private String password;
    private String birthDate;
    private String gender;
    private String patientName;
    private String phoneNum;
    private String email;
    private String identityNum;
    private String address;

}
package com.xuanzi.mapper;

import com.xuanzi.entity.Patient;

import java.util.List;

public interface PatientMapper {

    List<Patient> selectpatient();
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xuanzi.mapper.PatientMapper">
    <select id="selectpatient" resultType="patient">
        select *
        from hospital.patient;
    </select>
</mapper>
package com.xuanzi.mapper;

import com.xuanzi.entity.Patient;
import org.mybatis.spring.SqlSessionTemplate;

import java.util.List;

public class PatientMapperImpl implements PatientMapper {

    SqlSessionTemplate sqlSessionTemplate;

    public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
        this.sqlSessionTemplate = sqlSessionTemplate;
    }

    @Override
    public List<Patient> selectpatient() {
        PatientMapper patientMapper = sqlSessionTemplate.getMapper(PatientMapper.class);
        return patientMapper.selectpatient();
    }
}
<?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">
    <import resource="spring-mapper.xml"/>

    <bean id="patientManager" class="com.xuanzi.mapper.PatientMapperImpl">
        <property name="sqlSessionTemplate" ref="sqlSessionTemplate"/>
    </bean>
</beans>
dataSource=org.springframework.jdbc.datasource.DriverManagerDataSource
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/hospital?useUnicode=TRUE&characterEncoding=UTF-8&serverTimezone=GMT-8
username=root
password=root
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <typeAliases>
        <package name="com.xuanzi.entity"/>
    </typeAliases>
</configuration>
<?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 https://www.springframework.org/schema/context/spring-context.xsd">
    <context:property-placeholder location="classpath:database.properties"/>
    <!--    DataSource-->
    <bean id="dataSource" class="${dataSource}">
        <property name="driverClassName" value="${driverClassName}"/>
        <property name="url" value="${url}"/>
        <property name="username" value="${username}"/>
        <property name="password" value="${password}"/>
    </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/xuanzi/mapper/*.xml"/>
    </bean>
    <!--    sqlSessionTemplate-->
    <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg name="sqlSessionFactory" ref="sqlsessionFactory"/>
    </bean>
</beans>
import com.xuanzi.entity.Patient;
import com.xuanzi.mapper.PatientMapper;
import com.xuanzi.mapper.PatientMapperImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.List;

public class Main {
    public static void main(String[] args) {
//        SqlSession sqlSession = MybatisUtil.getSqlSession();
//        PatientMapper patientMapper = sqlSession.getMapper(PatientMapper.class);
//        for (Patient patient : patientMapper.selectpatient()) {
//            System.out.println(patient);
//        }
//        sqlSession.close();

        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        PatientMapper patientMapper = context.getBean("patientManager", PatientMapper.class);
        List<Patient> selectpatient = patientMapper.selectpatient();
        for (Patient patient : selectpatient) {
            System.out.println(patient);
        }
    }
}

方式二

package com.xuanzi.mapper;

import com.xuanzi.entity.Patient;
import org.apache.ibatis.session.SqlSession;
import org.mybatis.spring.support.SqlSessionDaoSupport;

import java.util.List;

public class PatientMapperImpl2 extends SqlSessionDaoSupport implements PatientMapper {
    @Override
    public List<Patient> selectpatient() {
        SqlSession sqlSession = getSqlSession();
        PatientMapper patientMapper = sqlSession.getMapper(PatientMapper.class);
        return patientMapper.selectpatient();
    }
}
<?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">
    <import resource="spring-mapper.xml"/>

    <bean id="patientManager2" class="com.xuanzi.mapper.PatientMapperImpl2">
        <property name="sqlSessionFactory" ref="sqlsessionFactory"/>
    </bean>
</beans>

import com.xuanzi.entity.Patient;
import com.xuanzi.mapper.PatientMapper;
import com.xuanzi.mapper.PatientMapperImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.List;

public class Main {
    public static void main(String[] args) {
//        SqlSession sqlSession = MybatisUtil.getSqlSession();
//        PatientMapper patientMapper = sqlSession.getMapper(PatientMapper.class);
//        for (Patient patient : patientMapper.selectpatient()) {
//            System.out.println(patient);
//        }
//        sqlSession.close();

        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        PatientMapper patientMapper = context.getBean("patientManager", PatientMapper.class);
        List<Patient> selectpatient = patientMapper.selectpatient();
        for (Patient patient : selectpatient) {
            System.out.println(patient);
        }
    }
}import com.xuanzi.entity.Patient;
import com.xuanzi.mapper.PatientMapper;
import com.xuanzi.mapper.PatientMapperImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.List;

public class Main {
    public static void main(String[] args) {
//        SqlSession sqlSession = MybatisUtil.getSqlSession();
//        PatientMapper patientMapper = sqlSession.getMapper(PatientMapper.class);
//        for (Patient patient : patientMapper.selectpatient()) {
//            System.out.println(patient);
//        }
//        sqlSession.close();

        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        PatientMapper patientMapper = context.getBean("patientManager2", PatientMapper.class);
        List<Patient> selectpatient = patientMapper.selectpatient();
        for (Patient patient : selectpatient) {
            System.out.println(patient);
        }
    }
}

声明式事务

里面用的命名空间都可以使用 IDEA 自动导入

<!--    配置声明式事务-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <constructor-arg name="dataSource" ref="dataSource"/>
</bean>
<!--    结合AOP实现事务织入-->
<tx:advice id="advice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="selectpatient" propagation="REQUIRED"/>
    </tx:attributes>
</tx:advice>
<!--    设置切入-->
<aop:config>
    <aop:pointcut id="po" expression="execution(* com.xuanzi.mapper..*.*(..))"/>
    <aop:advisor advice-ref="advice" pointcut-ref="po"/>
</aop:config>
package com.xuanzi.mapper;

import com.xuanzi.entity.Patient;
import com.xuanzi.entity.Test;

import java.util.List;

public interface PatientMapper {

    List<Patient> selectpatient();

    int insertTest(Test test);

    int deleteTestByTestId(int testId);
}

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xuanzi.mapper.PatientMapper">
    <insert id="insertTest" parameterType="test">
        insert into hospital.test (val)
        values (#{val})
    </insert>
    <delete id="deleteTestByTestId" parameterType="int">
        delete
        from hospital.test
        where TestID = #{testID}
    </delete>
    <select id="selectpatient" resultType="patient">
        select *
        from hospital.patient;
    </select>
</mapper>
package com.xuanzi.mapper;

import com.xuanzi.entity.Patient;
import com.xuanzi.entity.Test;
import org.apache.ibatis.session.SqlSession;
import org.mybatis.spring.support.SqlSessionDaoSupport;

import java.util.List;

public class PatientMapperImpl2 extends SqlSessionDaoSupport implements PatientMapper {
    @Override
    public List<Patient> selectpatient() {
        SqlSession sqlSession = getSqlSession();

        Test test = new Test("233");
        int i = 2;
        insertTest(test);
        deleteTestByTestId(i);

        PatientMapper patientMapper = sqlSession.getMapper(PatientMapper.class);
        return patientMapper.selectpatient();
    }

    @Override
    public int insertTest(Test test) {
        return getSqlSession().getMapper(PatientMapper.class).insertTest(test);
    }


    @Override
    public int deleteTestByTestId(int testId) {
        return getSqlSession().getMapper(PatientMapper.class).deleteTestByTestId(testId);
    }
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值