Spring 小笔记无源码

Spring

入门

git clone https://github.com/spring-projects/spring-framework

或者导入maven Spring Web MVC

<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.3.22</version>
</dependency>

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


优点

  • 免费开源框架
  • 轻量级 非入侵
  • 控制反转(IOC),面向切面编程(AOP)
  • 支持事务处理,对框架的整合支持

组成

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8pW4jvxL-1660382085165)(C:\Users\hj\AppData\Roaming\Typora\typora-user-images\image-20220808130138636.png)]

  • Spring Boot
    • 一个快速开发的脚手架
    • 基于SpringBoot可以快速的开发单个微服务
    • 约定大于配置和maven差不多
  • Spring Cloud
    • 基于SpringBoot实现

现在大多数都是用SpringBoot快速开发,盘Spring Boot需要冲Spring 和Spring MVC

弊端:发展太久了违背了原来,配置很繁琐

IOC理论推导

  1. UserDao接口
  2. UserDaoImpl实现类
  3. UserServic业务接口
  4. UserServiceImpl业务实现

如果我们更具客户的需求在UserDaoImpl添加了实现类但是我们需要在UserServiceImpl中进行我们手动更改,那么是一件非常麻烦的事情,需要我们认为主观去改变,但是如若我们在其中加入set来选定我们在UserDaoImpl中设定的方法那么我们就不用主动的去人为修改,而是因为选择而变动,那么我们只需要提交实现的时候将需求写上从而就可以被动的去实现不需要修改程序,降低耦合性

那么这样就是控制反转了

  1. 创建出你实现的类然后配置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="hello" class="com.hj.pojo.Hello">
        <property name="str" value="Spring"/>
    </bean>
</beans>
  1. 随后使用的时候获取所有bean然后选择使用哪个bean即可
import com.hj.pojo.Hello;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    public static void main(String[] args) {
        //获取spring的上下文对象
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        //我们的对象现在都在spring中管理,我们要用直接取就行
        Hello hello = (Hello) context.getBean("hello");
        System.out.println(hello.getStr());
    }
}

package com.hj.pojo;

import lombok.Data;
@Data
public class Hello {
    private String str;
}
//bean代码

有参构造

我们在部署xml的时候我们简单的写入bean标签是会报错的我们需要对我们的有参构造填入我们想要的数据

@Data
public class HelloT {
    private String str;
    public HelloT(String str){
        this.str=str;
        System.out.println("芜湖我叫:"+str);

    }
}

我们想要配置xml的话则需要用到标签constructor-arg对我们的参数进行选择

使用 index 进行填充:如图的str的index值为0所以引索是从0开始

<bean id="hellot" class="com.hj.pojo.HelloT">
    <constructor-arg index="0" value="wuhu"/>
</bean>

注意最好还是使用

<constructor-arg name="str" value="wuhu"/>

name value的组合 name对应的字段就是上方代码中的str

Spring配置

别名alias

<bean id="hello" class="com.hj.pojo.Hello">

</bean>

<alias name="hello" alias="wuhu"/>

在引用的时候

Hello hello = (Hello) context.getBean("hello");
Hello hello = (Hello) context.getBean("wuhu");
这两种方式都是可以的
    
    
    

Bean配置

  • id:唯一标识符也就是我们创建的对象名
  • class:我们所需要找到的类
  • name:可以起别名
    • 可以这样写 name = “wuhu sad,wu”
      • 这样可以看作有三个别名一个是wuhu 一个和是sad一个是wu
      • 分号 逗号 空格 都可以分割

import

一般用于团队开发,它可以将多哥配置文件合并成一个部分

相当于C的自定义头部文件.h文件

DI依赖注入

构造器注入

就前面Spring中提到的有参构造和无参构造

set方式注入*

  • 依赖注入:Set注入
    • 依赖:bean对象的创建依赖于容器
    • 注入:bean对象的所有属性由容器来注册

环境搭建

  1. 复杂类型
@Data
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;

}
  1. 真实测试对象
<?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="address" class="com.hj.pojo.Address"/>

    <bean id="student" class="com.hj.pojo.Student">
<!--        第一种普通方式注入-->
        <property name="name" value="hj"/>
<!--        第二种bean注入-->
        <property name="address" ref="address"/>
<!--        第三种数组注入-->
        <property name="books">
            <array>
                <value>芜湖1</value>
                <value>芜湖2</value>
                <value>芜湖3</value>
            </array>
        </property>
<!--        list注入-->
        <property name="hobbys">
            <list>
                <value>1</value>
                <value>2</value>
                <value>3</value>
            </list>
        </property>
<!--        map注入-->
        <property name="card">
            <map>
                <entry key="身份证" value="1"/>
                <entry key="银行卡" value="2"/>
            </map>
        </property>
<!--        set注入-->
        <property name="games">
            <set>
                <value>LOL</value>
                <value>COC</value>
                <value>BOB</value>
            </set>
        </property>
        <property name="wife">
            <null></null>
        </property>
<!--        properties注入-->
        <property name="info">
            <props>
                <prop key="学号">10086</prop>
                <prop key="性别"></prop>
            </props>
        </property>
    </bean>


</beans>
Student(name=hj, address=Address(address=null), books=[芜湖1, 芜湖2, 芜湖3], hobbys=[1, 2, 3], card={身份证=1, 银行卡=2}, games=[LOL, COC, BOB], wife=null, info={学号=10086, 性别=男})

输出结果

小结:

  • 普通方式注入value
  • bean注入ref
  • 数组注入需要借助property标签然后里里面的array value
  • list注入 同上list value
  • map注入 同上map entry(key value)
  • set注入 同上 set value
  • properties注入 同上 props prop(key)

拓展方式注入

user类

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

}

P标签

在xml配置文件中写入

 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">
<!--    p命名法则,简单的可以这样-->
    <bean id="user" class="com.hj.pojo.User" p:name="芜湖" p:age="18"/>


</beans>

我们可以见到导入之后可以见到user中的属性可以用p:来引用

也有C命名空间

C命名法用的是有参构造和无参构造对其参数进行设置

但是需要导入

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

Bean的作用域

ScopeDescription
singleton(默认)将每个 Spring IoC 容器的单个 bean 定义范围限定为单个对象实例。
prototype将单个 bean 定义的作用域限定为任意数量的对象实例。
request将单个 bean 定义的范围限定为单个 HTTP 请求的生命周期。也就是说,每个 HTTP 请求都有一个在单个 bean 定义后面创建的 bean 实例。仅在可感知网络的 Spring ApplicationContext中有效。
session将单个 bean 定义的范围限定为 HTTP Session的生命周期。仅在可感知网络的 Spring ApplicationContext上下文中有效。
application将单个 bean 定义的范围限定为ServletContext的生命周期。仅在可感知网络的 Spring ApplicationContext上下文中有效。
websocket将单个 bean 定义的范围限定为WebSocket的生命周期。仅在可感知网络的 Spring ApplicationContext上下文中有效。
  1. 代理模式(Spring默认)
    • scope = “singleton”
  2. 原型模式:每次从容器get的时候都会产生一个新的对象
    • scope = “prototype”
  3. 其余的都是web中的作用域只能在web中使用

Bean的自动装配

  • 自动装配:属性不由人为搞是Spring妈祖bean依赖一种方式
  • Spring会在上下文中自动寻找,并自动给bean装配属性

在Spring中有三种自动装配方式

  1. xml中显示的(前面写的)
  2. java中显示配置
  3. 隐式自动装配bean(必要)

测试

  1. 环境搭建

    • 一个人有两个宠物

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4JKnm5q6-1660382085166)(C:\Users\hj\AppData\Roaming\Typora\typora-user-images\image-20220809204433632.png)]

自动装配

ByName
    <bean id="cat" class="com.hj.pojo.Cat"/>
    <bean id="dog" class="com.hj.pojo.Dog"/>
<!--    byName: 会自动在容器上下文查找和自己set的指相匹配的bean的id-->
    <bean id="people" class="com.hj.pojo.people" autowire="byName">
        <property name="name" value="芜湖"/>
    </bean>
ByType
    <bean  class="com.hj.pojo.Cat"/>
    <bean  class="com.hj.pojo.Dog"/>
<!--    byName: 会自动在容器上下文查找和自己set的指相匹配的bean的id
        byType: 匹配相同属性字段只能保证全局唯一的时候使用如若我还有一个id为dog111就不行
-->
    <bean id="people" class="com.hj.pojo.people" autowire="byType">
        <property name="name" value="芜湖"/>
    </bean>

可以不写name

小结

  • byName保证所有bean的id唯一并且bean需要和自动注入的属性的set方法的值一致
  • byType 需要保证所有bean的唯一,和需要自动配置的属性类型一样

使用注解实现自动装配

  1. 需要导入约束

  2. 配置注解的支持

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

</beans>

context:annotation-config/需要写入这个

xmlns:context=“http://www.springframework.org/schema/context”

@Autowired的用法

示例@Autowired

首先配置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:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       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="cat" class="com.hj.pojo.Cat"/>
    <bean id="dog" class="com.hj.pojo.Dog"/>
<!--    byName: 会自动在容器上下文查找和自己set的指相匹配的bean的id
        byType: 匹配相同属性字段只能保证全局唯一的时候使用如若我还有一个id为dog111就不行
-->
    <bean id="people" class="com.hj.pojo.people"></bean>


</beans>
  1. xmlns:context="http://www.springframework.org/schema/context"导入

  2. ​ http://www.springframework.org/schema/context
    ​ http://www.springframework.org/schema/context/spring-context.xsd导入

  3. <context:annotation-config/>
    

​ 写入标签,开启注解支持

  1. @Data
    public class people {
        @Autowired
        private Dog dog;
        @Autowired
        private Cat cat;
        private String name;
    }
    
    

​ 在我们需要自动写入的bean上一行写入@Autowired即可

甚至set方法也可以不写入,前提是我们的自动装配在IOC(Spring)容器中存在且符合byName名称

  • @Nullable

    • 字段标记了这个字段 可以让这个为空
    • public void test(@Nullable String name)
  • @Autowired(required = false)

    • 定义了这个属性为false说明这个对象可以为null否则不允许为空
  • @Autowired可以配合@Qualifier使用

    • @Autowired
      @Qualifier(value="dog666")
      private Dog dog;
      
    • 通过@Qualifier指定我们xml定义的bean的id与其对应实现byName的匹配

  • @Resouce

    • 名字不一样按时类型唯一,用这个可以对bean配对也可以实现自动装配

    • @Resource(name = "dog666")
      
      如果xml中放置的bean文件过多但是用了大多数同样的bean但名字同
      一般用于指向
      

小结:

@Resouce和@Autowired

  • 都可以用来自动装配,都可以放在属性字段上
  • @Autowired通过byType实现,必须要求这个对象存在
  • @Resouce默认通过byName实现,如果找不到名字,则通过 byType实现
  • 执行顺序不同

使用注解开发

Spring4以后,使用注解开发,就必须保证aop的包导入

导入context注入

  • bean
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
    <!--    指定要扫描的包,在这包下的注解就会生效-->
    <context:component-scan base-package="com.hj.controller"/>
    <!--    开启注解支持-->
    <context:annotation-config/>

</beans>
  • 属性如何注入
@Component
public class User {
//    相当于<property name = "name" value="wuhu"/>
    @Value("芜湖")
    public String name ;

}
  • 衍生注解

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

  1. dao [@Repository]
  2. service [@Service]
  3. controller[@Controller]

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

  • 自动装配
- @Resouce
- @Autowired
  - 两个用于自动装配
- @Qualifier
  - 配合@Autowired使用
  • 作用域

@Component

@Value

@Scope

小结

xml更万能,适用于仍和场合,维护简单方便

注解只能在自己的类上,维护相对复杂

xml用来管理bean

注解只负责管理注入的属性

我们使用的过程中只需要注意一个问题必须让注解生效

<context:component-scan base-package="com.hj"/>
<!--    开启注解支持-->
<context:annotation-config/>

使用Java方式配置Spring

不用xml配置

JavaConfig是Spring的一个子项目

@Data
@Component
//这一步就是这个项目被Spring接管
public class User {
    @Value("wuhu")
    private String name;


}
@Configuration
@ComponentScan("com.hj.pojo")
//这个也会Spring容器托管,注册到容器中,这个代表这个是一个配置类
public class HjConfig {

    @Bean
    //相当于我们之前写的一个bean id默认为我们的方法名
    public User getUser(){
        return new User();
    }



}

引用的时候我们就不能使用CPXL

@Test
public void text1(){
    ApplicationContext context = new AnnotationConfigApplicationContext(HjConfig.class);
    User getUser = context.getBean("getUser", User.class);
    System.out.println(getUser.getName());
}

我们就只能使用AnnotationConfigApplicationContext来创建容器

代理模式

静态代理

  • 抽象角色:一般使用接口或者抽象类解决
  • 真实角色:被代理的角色
  • 代理角色:代理真实校色,代理真实角色后我们一般会做一些属性操作
  • 客户:访问代理对象的人

代码步骤

  1. 接口
//租房接口
public interface Rent {
    public void rent();
}
  1. 真实角色

    //房东
    public class Host implements Rent {
        public void rent() {
            System.out.println("房东出粗");
        }
    }
    
  2. 代理角色

package com.hj.dao;

import lombok.Data;

@Data
//中介
public class Proxy implements Rent{

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

    public void rent() {
        host.rent();
        seeHouse();
        hetong();
        fare();
    }

//    看房
    public void seeHouse(){
        System.out.println("带你看房");
    }
//    收费
    public void fare(){
        System.out.println("收中介费");
    }

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

}
  1. 客户
package com.hj.dao;

public class Client {
    public static void main(String[] args) {
        //房东要租房子
        Host host = new Host();
        //中介帮房东租房子,但是代理角色一般有附属操作
        Proxy proxy = new Proxy(host);
        //不用面对房东直接面对中介就可以
        proxy.rent();
    }
}

代理模式的好处

  • 可以是正式角色的操作更纯粹
  • 公共业务就交给了代理角色 实现业务的分工
  • 公共业务发生拓展的时候方便集中管理

缺点

  • 一个正式角色就会产生一个代理角色,若多个就翻倍

AOP的实现

纵向开发的横向添加

动态代理

  • 动态代理和静态代理角色一样
  • 动态代理的代理是动态生成的不是我们直接写好的
  • 两大类: 基于接口的动态代理,基于类的动态代理
    • 基于接口—jdk动态代理【这里学的是这个】
    • 基于类:cglib
    • java字节码实现:javasist

需要了解两个类:

Proxy 代理

InvocationHandler 调用处理程序

@Data
//我们会用这个类自动生成代理
public class PorxyInvocationHandler implements InvocationHandler {

    //被代理的接口
    private Rent rent;


    //Proxy实现生成代理
    public Object getProxy(){
        Object o = Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(), this);
        return o;
    }

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


    //处理代理实列 并返回结果,所以最终处理是在这里,把我们需要放进去的类放入即可
    //动态代理的本质就是通过反射的机制实现
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        seeHouse();
        Object invoke = method.invoke(rent, args);

        return invoke;
    }


}
  1. 首先需要去实现InvocationHandler接口里面的invoke方法
  2. 写入一个属性,这个属性是我们作为的接口
  3. 写入set方法将属性赋予实际值
  4. Proxy实现生成代理需要用到Proxy.newProxyInstance
public Object getProxy(){
    Object o = Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(), this);
    return o;
}

含义:获取当前类,要实现的接口,在这里

然后去实现invoke方法

//处理代理实列 并返回结果,所以最终处理是在这里,把我们需要放进去的类放入即可
//动态代理的本质就是通过反射的机制实现
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    seeHouse();
    Object invoke = method.invoke(rent, args);
    return invoke;
}

通过反射可以实现

其中method这个反射我们可以通过它来获取到rent的其他方法

动态代理的好处

  • 一个动态代理的是一个接口,一般就是对应的一类业务
  • 一个动态代理类可以代理多个类,只要是实现了同一个接口就可以实现了

AOP

先导入xml依赖

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

方式一

使用Spring的API接口MethodBeforeAdvice

需要实现before方法

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

我们可以看到这便是通过实现methodBeforAdvice来实现实例化,所以也是个动态的过程

配置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: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="userService" class="com.hj.service.UserServiceImpl"/>
    <bean id="log" class="com.hj.log.Log"/>
    <bean id="afterLog" class="com.hj.log.AfterLog"/>

<!--    配置aop的配置文件-->
<!--    需要导入aop的约束-->
<!--    方式一 使用原生接口-->
    <aop:config>
<!--        切入点 pointcut  expression表达式 execution(要执行的位置 ) -->
        <aop:pointcut id="pointcut" expression="execution(* com.hj.service.UserServiceImpl.*(..))"/>
<!--        执行环绕增加-->
        <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
<!--        上一行的意思是,将log这个类里面的方法切入到pointcut中-->
        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
    </aop:config>

</beans>

配置aop需要记得我们需要配置好aop的约束

上面的地址模仿着来就行了,需要着重注意的是

aop:config 这个是对其进行设置申明

aop:advisor 插入,将一个类插入到pointcut-ref所填写的类中

这里完成的操作就是将log类穿插到UserServiceImpl中,因为log类需要用到

第二种方式【用到切面 aop:aspect】

    <bean id="diy" class="com.hj.diy.DiyPointCut"/>
    
	<aop:config>
<!--        自定义切面 然后ref要引入的类-->
        <aop:aspect ref="diy">
<!--            然后切入点-->
<!--            execution()
                    第一个*是指返回类型*就是所有类型
                    然后是包名(我们要指向的类)
                    第二个*指所有类-->
            <aop:pointcut id="point" expression="execution(* com.hj.service.UserServiceImpl.*(..))"/>
<!--            然后通知-->
            <aop:before method="before" pointcut-ref="point"/>
            <aop:after method="after" pointcut-ref="point"/>
        </aop:aspect>
    </aop:config>

首先我们自定义的类需要插入的类先注册了,然后对aop进行创建一个切面一个操作

aop:aspect ref=“diy” 然后就创建了一个我们申明的bean切面,然后一样的先找到我们想切入的包,指向后 又有标签aop before 就是在执行point之前需要执行的方法同理适用于after

方式三【使用注解】

首先xml中配置标签有效扫描

    <aop:aspectj-autoproxy proxy-target-class="false"/>
    <context:annotation-config/>
    <context:component-scan base-package="com.hj"/>

java代码

@Component
@Aspect
//标注这个面是个切面
public class Annotation {
    @Before("execution(* com.hj.service.UserServiceImpl.*(..))")
    public void befor(){
        System.out.println("执行前");
    }

    @After("execution(* com.hj.service.UserServiceImpl.*(..))")
    public void after(){
        System.out.println("执行后");
    }
    //在环绕增强中我们可以给定一个参数代表我们要获取处理切入的点
    @Around("execution(* com.hj.service.UserServiceImpl.*(..))")
    public void around(ProceedingJoinPoint point) throws Throwable {
        System.out.println("环绕前");
        //获得签名
        System.out.println(point.getSignature());
        //执行方法
        Object proceed = point.proceed();
        System.out.println("环绕后");
    }
}

我们需要注意execution表达

<!--                    第一个*是指返回类型*就是所有类型-->
<!--                    然后是包名(我们要指向的类)-->
<!--                    第二个*指所有类-->
<!--                    括号里面..指的是所有类型输入-->

整合Mybatis

  1. 导入jar包

    • junit
    • mybatis
    • mysql
    • spring
    • aop
    • mybatis-spring
  2. 配置文件

  3. 测试

MybatisSpring

  1. 安装

    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>2.0.7</version>
    </dependency>
    
  2. 要和 Spring 一起使用 MyBatis,需要在 Spring 应用上下文中定义至少两样东西:一个 SqlSessionFactory 和至少一个数据映射器类。

    在 MyBatis-Spring 中,可使用 SqlSessionFactoryBean来创建 SqlSessionFactory。 要配置这个工厂 bean,只需要把下面代码放在 Spring 的 XML 配置文件中:

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
      <property name="dataSource" ref="dataSource" />
    </bean>
    
@Configuration
public class MyBatisConfig {
  @Bean
  public SqlSessionFactory sqlSessionFactory() throws Exception {
    SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
    factoryBean.setDataSource(dataSource());
    return factoryBean.getObject();
  }
}
  1. 加入映射

    <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
      <property name="mapperInterface" value="org.mybatis.spring.sample.mapper.UserMapper" />
      <property name="sqlSessionFactory" ref="sqlSessionFactory" />
    </bean>
    

我的实例配置

  1. 编写数据源

    <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=false&amp;useUnicode=true&amp;characterEncoding=utf-8"/>
        <property name="username" value="root"/>
        <property name="password" value="123456789ww"/>
    </bean>
    
  2. 写入sqlSessionFactory

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <property name="mapperLocations" value="classpath:com/hj/dao/*.xml"/>
    </bean>
    
  3. 给接口添加实现类(SqlSessionTemplate)

    @Data
    public class UserMapperImpl implements UserMapper{
    
        private SqlSessionTemplate sqlSession;
    
        @Override
        public List<User> selectUser() {
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            return mapper.selectUser();
        }
    }
    
    
  4. 测试

具体看我的spring-10-mybatis源码

第二种实现方式,但是注意需要写入set方法所以标签@Data解决就行了

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

声明事务

也就那样,我这里使用到了AOP进行对事务的操作当然也可以使用注解@Transactional

@Transactional
@Data
public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper{

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

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

    @Override
    public int delectUser(int id) {
        return getSqlSession().getMapper(UserMapper.class).delectUser(id);
    }
}

就这样用

这里使用到了mybatis SqlSession的第二种,所以看起来比较容易

正常配置Transactional

       xmlns:tx="http://www.springframework.org/schema/tx"
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/context/tx.xsd

先将约束先导入

    <tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--        给方法配置事务-->
<!--        配置事务的传播性new propagation= -->
        <tx:attributes>
            <tx:method name="add" propagation="REQUIRED"/>
            <tx:method name="delete" propagation="REQUIRED"/>
            <tx:method name="updata" propagation="REQUIRED"/>
            <tx:method name="query" read-only="true"/>
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>
<!--    配置事务切入-->
    <aop:config>
        <aop:pointcut id="txPointcur" expression="execution(* com.hj.dao.UserMapper.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcur"/>
    </aop:config>

配置事务

但是个人感觉注解就行了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

艾米莉亚小汉堡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值