欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Spring学习笔记

程序员文章站 2022-06-09 20:28:55
Spring学习笔记(一)Spring概念Spring是开源的轻量级框架Spring的核心主要有两部分Aop:面向切面编程,扩展功能不需要修改源代码IoC:控制反转,比如有一个类,在类里面有一个方法(不是静态方法),我们如果要调用该类里的方法,就需要创建该类的对象,使用对象来调用方法,创建类对象的过程,是使用new的方式。 使用了Spring之后,创建类对象的过程,则需要交给Spring了。Spring是一站式框架Spring在JavaEE的每一层都提供了不同的解决方案...

Spring学习笔记

1.spring

◆目的:解决企业应用开发的复杂性

◆功能:使用基本的JavaBean代替EJB,并提供了更多的企业应用功能

◆范围:任何Java应用

Spring是一个轻量级控制反转(IoC)和面向切面(AOP)的容器框架。

下载地址:https://repo.spring.io/release/org/springframework/spring/

1.2.准备

1.创建项目

2导入依赖

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

         <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
         <dependency>
             <groupId>org.springframework</groupId>
             <artifactId>spring-jdbc</artifactId>
             <version>5.2.0.RELEASE</version>
         </dependency>

2.IOC设计思想(控制反转)

***自己的理解不深,可能有些方面理解错误 **

●**谁控制谁,控制什么:**传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对 象的创建;谁控制谁?,当然是IoC 容器控制了对象;控制什么?,那就是主要控制了外部资源获取(不只是对象包括比如文件等)。

  • 为何是反转:没有 IoC 的时候我们都是在自己对象中主动去创建被依赖的对象,这是正转。但是有了 IoC 后,所依赖的对象直接由 IoC 容器创建后注入到被注入的对象中,依赖的对象由原来的主动获取变成被动接受,所以是反转。
  • 哪些方面反转了:所依赖对象的获取被反转了。

比如

数据访问层(dao)中:各种对象(各种信息,用于客户需求),如下假设: 类1,类2中便是各种用户的需求,等待客户的服务人员(员工,程序员,…)拿出为客户服务,即各种业务

/*
userdao接口
 */
public interface userdao {
    void getuserdao();


}
=====================================================================
   /*
   
各种类,继承于userdao并需要实现其方法
 */ 
    //类1:
    public class userImpote implements userdao {

    public void getuserdao() {
        System.out.println("获取第一个用户");
    }


}
----------------------------------------------------------------
//类2
public class userImpote1 implements userdao {
    @Override
    public void getuserdao() {
        System.out.println("获取第二个用户");
    }

}
    

业务层(service)中:类1中客户如果要获取信息(第一用户或者第二用户),每次都要从新nwe个对象,即( userdao user=new userImpote1(););;类2(IOC思想)中则是IoC是有专门一个容器来创建这些对象,此容器中有各种依赖对象,由原来的主动new对象变成现在的被动接受依赖对象(对象全部存放在

   private userdao user;
    public void getuserdao(userdao user) {
     this.user=user;
  }

)因此控制反转了,即由Ioc容器来控制对 象的创建,依赖的对象由原来的主动获取变成被动接受。

/*
userservice接口
 */
 public interface userservice {
    void getuserdao1();
}

================================================================
  /*
类1:需要自己主动获取数据 new userImpote1,
 */  
public class userserviceImpote implements userservice{
    userdao user=new userImpote1();
    @Override
    public void getuserdao1() {
        user.getuserdao();
    }
}
----------------------------------------------
      /*
类2:IOC
 */ 
    public class userserviceImpote implements userservice{
    private userdao user;
    public void getuserdao(userdao user) {
     this.user=user;
  }

    @Override
    public void getuserdao1() {
        user.getuserdao();
    }
}

测试(用户):测试1中用户要获取dao层信息,每次都需要service层中从新new个对象;

测试2中用户要获取dao层信息,只需要service层中类2自动创建对应的对象

//测试1
public class mytest {
    public static void main(String[] args) {
        userservice users=new userserviceImpote();
        users.getuserdao1();
    }
}
-----------------------------------------
//测试2
    public class mytest {
    public static void main(String[] args) {
        userservice users=new userserviceImpote();
        ((userserviceImpote) users).getuserdao(new userImpote1());
        users.getuserdao1();
        
    }
}

3.利用spring配置文件获取

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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
<!--
以下是创建对象,userImpote userImpote=new userImpote();
id=变量名,xlass= nwe userImpote
-->
 <bean id="userImpote" class="com.gongfang.dao.userImpote"/>
    <bean id="userImpote1" class="com.gongfang.dao.userImpote1"/>
    
    <bean id="userserviceImpote" class="com.gongfang.service.userserviceImpote">
        <!-- 
下面通过setUser注入方法获取 userImpote
  private userdao user;
    public void setUser(userdao user) {
     this.user=user;
    }
 -->
        <property name="user" ref="userImpote"/>
    </bean>

</beans>

测试:

public class mytest1 {
    public static void main(String[] args) {
        //获取ApplicationContext对象拿到容器,获得spring配置文件
        ApplicationContext context = new ClassPathXmlApplicationContext("sp.xml");
        //通过获得配置文件中的ben获得 userserviceImpote方法,此方法通过set注入对象
        userserviceImpote userserviceImpote= (userserviceImpote) context.getBean("userserviceImpote");
        userserviceImpote.getuserdao1();
    }
}

*注意:spring官方是通过ApplicationContext对象拿到容器

   ApplicationContext context = new ClassPathXmlApplicationContext("spring配置文件");

4.ioc创建对象方式

constructor-arg:通过构造函数注入。 则property:通过setxx方法注入。

  • 通过set方法注入

    <bean id="hello" class="com.gongfang.dao.helloword">
          <property name="str" value="HelloSpring"/>
      </bean>
    
  • 默认使用无参构造创建对象

  • 使用有参构造函数创建对象

    • 使用参数名赋值:

      
      <bean id="hello" class="com.gongfang.dao.helloword">
            <constructor-arg name="str" value="HelloSpring"/>
        </bean>
      
    • 使用索引下标赋值:

       <bean id="hello" class="com.gongfang.dao.helloword">
              <constructor-arg index="0" value="HelloSpring"/>
          </bean>
      
    • 类型赋值:

      <bean id="hello" class="com.gongfang.dao.helloword">
              <constructor-arg type="java.lang.String" value="HelloSpring"/>
          </bean>
      

5.Sping配置(applicationContext1.xml)

5.1.别名

    <bean id="hello" class="com.gongfang.dao.helloword">
        <constructor-arg index="0" value="HelloSpring"/>
    </bean>

    <!--别名,可以通过别名获取-->
    <alias name="hello" alias="myhello"/>

5.2.ben配置

<!--
Helloword hello = new helloword();
id="变量名hello",class="new helloword()",name="别名(此别名比 alias 强大,可以设置多个别名能用 ", 空格 ;"区分开)"
-->
<bean id="hello" class="com.gongfang.dao.helloword" name="a,b c;d">
    
    <!-- constructor-arg 根据构造函数注入 ,name ="helloword中的变量名",value="值" -->
    <constructor-arg name="str" value="HelloSpring"/>
  
    <!-- 
   property 根据set注入
    < property name="str" value="HelloSpring"/>
    -->
    
</bean>

5.3.import

合并多个人的配置文件为一个

 <import resource="applicationContext1.xml"/>
    <import resource="applicationContext2.xml"/>
    <import resource="applicationContext3.xml"/>

6.依赖注入(DI)

6.1.构造器注入

6.2.属性注入

string ,string[] ,List ,map ,set ,……

官方文档:(7.4.2)

https://www.docs4dev.com/docs/zh/spring-framework/4.3.21.RELEASE/reference/beans.html#beans-collection-elements

6.1.p,c 命令注入(扩展)

官方解释(7.4.2)

https://www.docs4dev.com/docs/zh/spring-framework/4.3.21.RELEASE/reference/beans.html#beans-p-namespace

注意:p:set属性来注入的;c:构造器来注入的,所以对象需要导入有参和无参构造器;都需要导入各自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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

        <bean id="hello" class="com.gongfang.dao.helloword1" p:name="宋江" p:age="10"/>
</beans>

2.

  <!--约束-->
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:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">
<!--
        <bean id="hello" class="com.gongfang.dao.helloword1" p:name="宋江" p:age="18"/>
        -->
        <bean id="hello" class="com.gongfang.dao.helloword2" c:name="宋江" c:age="18"/>
</beans>

7.自动装配

1.byname: 查找容器中和自己对象set后面对应的ben,id=“对象set后面的值”

 autowire="byName"
  1. autowire: 查找容器中和自己对象属性相同的ben,只需要class=""一致
 autowire="byType"

8.注解实现自动装配

约束支持

<?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>
  • **@Autowired ????*在属性和set上都可以使用,可以不用编写set方法,Autowired默认先按byType,如果发现找到多个bean,则,又按照byName方式比对,如果还有多个,则报出异常。

    public class pople {
        @Autowired
        private miao miao;
        @Autowired
        @Nullable
        private dog dog;
        private String name;
    
  • @Nullable: 被标记的字段可以为null

  • @Qualifier(value =“xxx”): 当@Autowired 比较复杂,无法通过一个@Autowired 来装配完成时可以使用此注解来配合@Autowired 使用,指定一个唯一的bean对象

  @Autowired
    @Qualifier(value ="miao11")
    private miao miao;
        <bean id="miao11" class="miao"/>
        <bean id="miao" class="miao"/>
  • @Resource: 默认按 byName自动注入,如果找不到再按byType找bean,如果还是找不到则抛异常,无论按byName还是byType如果找到多个,则抛异常。
public class pople {
    @Resource
    private miao miao;
    @Resource
    private dog dog;
    private String name;
  • ……

9.使用注解开发

参考博客:https://www.cnblogs.com/hdfzj/articles/12401077.html

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"
    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:component-scan base-package=""/>

2.注解

属性注入:

  • @Component: 标注Spring管理的Bean,使用@Component注解在一个类上,表示将此类标记为Spring容器中的一个Bean。

  • **@component:**相当于

     <property name="" value=""/>
    
  • 衍生注解:web中按三层架构分层

    • dao @Repository
    • service @service
    • controller @controller

功能相同,按照类注册bean

9.2.@Configuration

其中:@Configuration = spring配置文件;

@Bean及下代码 等价于:

<bean id="xxx" class="xxx">
...
</bean>

@Component 等价于

 <property name="xxx" value="xxx"/>

@Value("") 等价于下面 value=""

  <property name="str" value="HelloSpring"/>

@Component
public class helloword3 {
    private String name;

    public String getName() {
        return name;
    }
@Value("孙悟空")
    public void setName(String name) {
        this.name = name;
    }

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

@Configuration
public class hello3user {
    @Bean
    public helloword3 getuser(){
        return new helloword3();
    }
}

测试

@Test
    public <hellword3> void testhello3(){
        ApplicationContext user = new AnnotationConfigApplicationContext(hello3user.class);
        hellword3 getuser = (hellword3) user.getBean("getuser");
        System.out.println(getuser);
    }

10.代理模式

10.1静态代理

Spring学习笔记

分析:

抽象角色:一般使用接口或抽象类解决

真实角色:被代理的角色

代理角色:代理真实角色

客户:访问代理对象的人

简单案例:租房

抽象角色(房):一个租房接口,用于他人租房

//租房
public interface fang {
    public void zufang();
}

真是角色(房东):房东要租房,实现其租房接口

//房东要租房
public class fangdong implements fang {
    @Override
    public void zufang() {
        System.out.println("我要出租房");
    }
}

代理角色(中介):房东只想租房,把租房繁琐的事交给中介,中介帮助客户完成租房,从中抽取一定的报酬,(代码:中介需要拿到房东,并拿到租房,才能去租房)

//中介
//要租房就要实现租房接口
public class zhongjie implements fang{
    //拿到房东(没有房东就没有租房的任务)
    private fangdong fangdong;

    public zhongjie() {
    }

    public zhongjie(com.gongfang.demo01.fangdong fangdong) {
        this.fangdong = fangdong;
    }

    @Override
    public void zufang() {
        //房东租房
        fangdong.zufang();
    }
}

客户(要租房人):

public class my {
    public static void main(String[] args) {
        //房东要租房
        fangdong fangdong=new fangdong();
        //找中介,让中介帮房东租房
        zhongjie zhongjie=new zhongjie(fangdong);
        //自己要租房直接面对中介
        zhongjie.zufang();
    }
}

结果:

Spring学习笔记

优点:

1.使操作业务时不用关注一些公共业务

2.公共业务交给代理,使业务分工

3.方便集中管理

缺点:

一个公共业务就会产生一个代理,使代码量容易增加,降低了开发效率

10.2.动态代理

动态代理,代理接口

1.接口

2.真实用户(房东)

3.自动生成代理类(要实现 InvocationHandler 接口)

//此类自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler {


    //代理的接口
    //   private Object teager;
    private fang fang;


    
    //  public void setTeager(Object teager) {
      //  this.teager = teager;
   // }
    public void setFang(com.gongfang.demo02.fang fang) {
        this.fang = fang;
    }

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

    
    //处理代理实例并返回结果
    //    @Override
   // public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

      //  Object invoke = method.invoke(teager, args);

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

        Object invoke = method.invoke(fang, args);

        return invoke;
    }


}

4.客户

public class client {
    public static void main(String[] args) {
        //真实角色
        fangdong fangdong=new fangdong();
        //代理角色
        ProxyInvocationHandler pir   = new ProxyInvocationHandler();
        pir.setFang(fangdong);
		//动态代理代理的是接口,所以返回类型需是接口
        fang proxy = (fang) pir.getProxy();

         proxy.zufang();

    }
}

11.spring AOP(面向切面编程)

思想:面向切面编程

AOP 领域中的特性术语:

  • 通知(Advice): AOP 框架中的增强处理。通知描述了切面何时执行以及如何执行增强处理。
  • 连接点(join point): 连接点表示应用执行过程中能够插入切面的一个点,这个点可以是方法的调用、异常的抛出。在 Spring AOP 中,连接点总是方法的调用。
  • 切点(PointCut): 可以插入增强处理的连接点。
  • 切面(Aspect): 切面是通知和切点的结合。
  • 引入(Introduction):引入允许我们向现有的类添加新的方法或者属性。
  • 织入(Weaving): 将增强处理添加到目标对象中,并创建一个被增强的对象,这个过程就是织入。

11.1.准备

1.导入依赖

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

2.导入AOP约束,sping配置文件

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

 

</beans>

3.接口及角色

public interface user {
     void add() ;
     void  delet();
     void inster();
     void  select();


}


================================================================

public class user1 implements user {
    @Override
    public void add() {
        System.out.println("增加了个用户");
    }

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

    @Override
    public void inster() {
        System.out.println("改变了个用户");
    }

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

4.日志

//前置日志
public class Log implements MethodBeforeAdvice {



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

===========================================================================

//后置日志
public class Log1 implements AfterReturningAdvice {

    //o  返回值
    //o1  目标对象
    @Override
    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
    System.out.println("执行了"+method.getName()+"方法,返回结果为"+o);
    }
}

11.2.AOP实现方法1

  • 使用API接口
<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd
         http://www.springframework.org/schema/aop
         https://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--注册bean-->
    <bean id="user1" class="com.gongfang.dao.user1"/>
    <bean id="log" class="com.gongfang.LOG.Log"/>
    <bean id="log1" class="com.gongfang.LOG.Log1"/>

    <!--配置AOP ,导入AOP约束-->
    <aop:config>
        <!--切入点 , execution(要执行的位置)-->
        <aop:pointcut id="pointcut" expression="execution(* com.gongfang.dao.user1.* (..))"/>
        
        <!--执行环绕增加-->
        <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
        <aop:advisor advice-ref="log1" pointcut-ref="pointcut"/>

    </aop:config>



</beans>

测试:

public class testaop {

    public static void main(String[] args) {
      ApplicationContext test = new ClassPathXmlApplicationContext("applicationContext1.xml");

      //动态代理代理的是接口,所以返回类型需是接口
        user user = (user) test.getBean("user1");
        user.add();

    }


}

结果:

Spring学习笔记

11.3.AOP实现方法2

  • 自定义方法

1.随便写个类,写些方法

public class rest {
    public void befer(){
        System.out.println("方法执行前");
    }

    public void arfer(){
        System.out.println("方法执行后");


    }
}

2.spring配置文件

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

    <!--注册bean-->
    <bean id="user1" class="com.gongfang.dao.user1"/>
    <bean id="log" class="com.gongfang.LOG.Log"/>
    <bean id="log1" class="com.gongfang.LOG.Log1"/>

<!--  方式二:自定义类-->
    <!--注册bean-->
    <bean id="res" class="com.gongfang.rest.rest"/>
    
   <aop:config>
 <!--      自定义切面,ref:要引用的类-->
        <aop:aspect ref="res">
               <!--切入点-->
   <aop:pointcut id="pointcut" expression="execution(* com.gongfang.dao.user1.*(..))"/>
    <!--通知-->
            <aop:before method="befer" pointcut-ref="pointcut"/>
            <aop:after method="arfer" pointcut-ref="pointcut"/>
        </aop:aspect>


   </aop:config>

</beans>

11.4.AOP实现方法3

  • 使用注解实现

1、开启aop注解的自动代理

< aop:aspectj-autoproxy/>

2.指定要扫描的包

<context:component-scan base-package=“com.gongfang”/>

3、 AspectJ的AOP的注解:

  • @Component: 标注Spring管理的Bean,使用@Component注解在一个类上,表示将此类标记为Spring容器中的一个Bean

  • @Aspect:定义切面类的注解

  • @Pointcut:定义切入点的注解

  • 通知类型:
    @Before:前置通知
    @AfterReturing:后置通知
    @Around:环绕通知
    @After:最终通知
    @AfterThrowing:异常抛出通知.

实验:

接口

public interface user {
     void add() ;
     void  delet();
     void inster();
     void  select();


}

目标实现类接口

// 标注Spring管理的Bean,使用@Component注解在一个类上,表示将此类标记为Spring容器中的一个Bean。
@Component
public class user1 implements user {
    @Override
    public void add() {
        System.out.println("增加了个用户");
    }

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

    @Override
    public void inster() {
        System.out.println("改变了个用户");
    }

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

applicationContext1.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"
       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/aop
         https://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context
         https://www.springframework.org/schema/context/spring-context.xsd
">
 <!--   指定要扫描的包-->
    <context:component-scan base-package="com.gongfang"/>
<!--开启注解-->
 <aop:aspectj-autoproxy/>

</beans>

日志,切面类

// 标注Spring管理的Bean,使用@Component注解在一个类上,表示将此类标记为Spring容器中的一个Bean。
@Component
//@Aspect 切面类
@Aspect
public class log {

    // @Before 通知 ;execution()切入点
    @Before("execution(* com.gongfang.dao.user1.*(..))")
    public void befor(){
        System.out.println("方法执行前");
    }

    @After("execution(* com.gongfang.dao.user1.*(..))")
    public void aftre(){
        System.out.println("方法执行后");
    }

}

12.整合mybatis

**官方中文文档:**http://mybatis.org/spring/zh/getting-started.html

1,什么是 MyBatis-Spring?

MyBatis-Spring 会帮助你将 MyBatis 代码无缝地整合到 Spring 中。它将允许 MyBatis 参与到 Spring 的事务管理之中,创建映射器 mapper 和 SqlSession 并注入到 bean 中,以及将 Mybatis 的异常转换为 Spring 的 DataAccessException。 最终,可以做到应用代码不依赖于 MyBatis,Spring 或 MyBatis-Spring。

注意:

MyBatis-Spring 需要以下版本:

MyBatis-Spring MyBatis Spring Framework Spring Batch Java
2.0 3.5+ 5.0+ 4.0+ Java 8+
1.3 3.4+ 3.2.2+ 2.1+ Java 6+

12.1.准备:

1.导入要使用的依赖

<dependencies>

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

        <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.0.RELEASE</version>
        </dependency>
    <!--junit-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.1</version>
        </dependency>
    <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.21</version>
        </dependency>
    <!--mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.3</version>
        </dependency>

        <!--aop织入-->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.5</version>
        </dependency>

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

12.2.操作mybatis

1.查看mybatis学习笔记

连接数据库—–>编写实体类——-》编写mapper接口—–》构建 SqlSessionFactory——-》mapper.xml文件—–》mybatis核心配置文件——测试

构建SqlSessionFactory:


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 MybastisUtils {
      private static SqlSessionFactory sqlSessionFactory;

        static {
            try {
                //获取 SqlSessionFactory对象
                String resource = "mybatis-config.xml";
                InputStream inputStream = Resources.getResourceAsStream(resource);
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        //获取SqlSession实例
        //SqlSession包含了面向数据库执行的所有方法
        public static SqlSession gteSqlSession(){
            SqlSession sqlSession= sqlSessionFactory.openSession();
            return sqlSession;
        }
    }

2.mapper.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">
<!--绑定一个定一个对应的dao/mapper接口-->
<mapper namespace="">


</mapper>

3.mybatis核心配置文件及sql文件:db.properties:

<!--sql文件:db.properties-->
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/person?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone =UTC
username=root
password=123456

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

    <!--引入一个外部配置文件-->
    <properties resource="db.properties"/>
    <!--给实体类起别名-->
    <typeAliases>
        <typeAlias type="com.gongfang.User.Student1" alias="student1"/>
    </typeAliases>
    <!-- 环境:配置mybatis的环境 -->
    <environments default="development">
        <!-- 环境变量:可以配置多个环境变量,比如使用多数据源时,就需要配置多个环境变量 -->
        <environment id="development">
            <!-- 事务管理器 -->
            <transactionManager type="JDBC"></transactionManager>
            <!-- 数据源 -->
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="com/gongfang/mapper/mapper.xml"/>
    </mappers>
</configuration>

12.3.mybatis-spring 实现方式1

1.接口

package com.gongfang.mapper;
import com.gongfang.User.Student1;

import java.util.List;

public interface sqlmapper {
    public List<Student1> getStudent1();


}

2.mapper.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">
<!--绑定一个定一个对应的dao/mapper接口-->
<mapper namespace="com.gongfang.mapper.sqlmapper">
 <cache eviction="FIFO" flushInterval="6000" size="512" readOnly="true"/>
 <select id="getStudent1" resultType="student1">
SELECT * from student1
 </select>

</mapper>

目标实现类:

package com.gongfang.mapper;

import com.gongfang.User.Student1;
import org.mybatis.spring.SqlSessionTemplate;

import java.util.List;

//目标实现类
public class sqlmapperimp implements sqlmapper {

                private SqlSessionTemplate sqlSession;

    public void setSqlSession(SqlSessionTemplate sqlSession) {
        this.sqlSession = sqlSession;
    }
	
    //好比mybatis中的测试
    @Override
    public List<Student1> getStudent1() {
        sqlmapper mapper = sqlSession.getMapper(sqlmapper.class);

        return mapper.getStudent1();
    }
}

实体类:

package com.gongfang.User;


import lombok.Data;
import lombok.ToString;

@Data

public class Student1 {
    private int id;
    private String name;
    private char sex;

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

mybati配置文件 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>
        <typeAlias type="com.gongfang.User.Student1" alias="student1"/>
    </typeAliases>

</configuration>

spring配置文件,用于和mybatis建立连接:

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

    
    <!--mybatis中的数据库连接问件-->
    <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/person?useUnicode=true&amp;characterEncoding=utf-8&amp;useSSL=true&amp;serverTimezone =UTC"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
    </bean>

   <!-- sqlSessionFactory:用于spring整合mybatis,与mybatis建立连接-->
    <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/gongfang/mapper/*.xml"/>
    </bean>


    <!--SqlSessionTemplate:就是mybatis中的sqlSession文件-->
    <bean id="Template" class="org.mybatis.spring.SqlSessionTemplate">
        <!--只能用构造方法注入sqlSessionFactory,因为SqlSessionTemplate没有set方法-->
        <constructor-arg index="0" ref="sqlSessionFactory"/>
    </bean>

    <!--注册bean-->
    <bean id="sqmaip" class="com.gongfang.mapper.sqlmapperimp">
        <property name="sqlSession" ref="Template"/>
    </bean>
</beans>

测试:

public class testsqlmapper {

    @Test
    public void getStudent1() {
        ApplicationContext res = new ClassPathXmlApplicationContext("spring-dao.xml");
        //代理接口
        sqlmapper sqmaip = (sqlmapper) res.getBean("sqmaip");
		//打印
        List<Student1> student1 = sqmaip.getStudent1();
        for (Student1 s:
             student1) {
            System.out.println(s);
        }

    }

    }

结果:

Spring学习笔记

13.事务

  • ACID原则:原子性,一致性,持久性,隔离性(幻读,脏读,不可重复读)

13.1.课前案例

这里我们来添加个用户同时删除这个添加的用户,一同执行,专门把删除用户的SQL语言写错,让程序最后执行会发现程序报错,但奇怪的是用户添加进去了,但没有删除,所以就造成了不一致性

1.数据表实体类

@Data

public class Student1 {
    private int id;
    private String name;
    private char sex;

    public Student1() {
    }

    public Student1(int id, String name, char sex) {
        this.id = id;
        this.name = name;
        this.sex = sex;
    }

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

2.mybatis的mapper接口

import com.gongfang.User.Student1;

import java.util.List;

public interface sqlmapper {
    //查询全部用户
    public List<Student1> getStudent1();

    //插入用户
    public int adduser(Student1 name);

    //删除用户
    public int deleteuser(int id);


}

3.mapper.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">
<!--绑定一个定一个对应的dao/mapper接口-->
<mapper namespace="com.gongfang.mapper.sqlmapper">
 <cache eviction="FIFO" flushInterval="6000" size="512" readOnly="true"/>

 <select id="getStudent1" resultType="student1">
SELECT * from student1
 </select>

 <insert id="adduser" parameterType="Student1">
  insert into student1(id,name,sex) values (#{id},#{name},#{sex})
 </insert>
<!--这里专门把  delete 错写成   deletes -->
 <delete id="deleteuser" parameterType="int">
  deletes from student1 where id=#{id}
 </delete>

</mapper>

4.目标实现类

import com.gongfang.User.Student1;
import org.apache.ibatis.session.SqlSession;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.support.SqlSessionDaoSupport;

import java.util.List;

//目标实现类
public class sqlmapperimp extends SqlSessionDaoSupport implements sqlmapper {



    @Override
   // 这里执行增加,删除,查询
    public List<Student1> getStudent1() {

Student1 s=new Student1(8,"太始",'男');
        SqlSession sqlSession = getSqlSession();
        sqlmapper mapper = sqlSession.getMapper(sqlmapper.class);
        mapper.adduser(s);
        mapper.deleteuser(8);


        return mapper.getStudent1();
    }

    @Override
    public int adduser(Student1 name) {
        SqlSession sqlSession = getSqlSession();
        sqlmapper mapper = sqlSession.getMapper(sqlmapper.class);
        return mapper.adduser(name);
    }

    @Override
    public int deleteuser(int id) {
        SqlSession sqlSession = getSqlSession();
        sqlmapper mapper = sqlSession.getMapper(sqlmapper.class);
        return mapper.deleteuser(id);
    }
}

5.mybatis文件

<?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>
        <typeAlias type="com.gongfang.User.Student1" alias="student1"/>
    </typeAliases>

</configuration>

6.Spring配置文件

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

    <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/person?useUnicode=true&amp;characterEncoding=utf-8&amp;useSSL=true&amp;serverTimezone =UTC"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
    </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/gongfang/mapper/*.xml"/>
    </bean>


    <!--SqlSessionTemplate:就是使用的sqlSession-->
    <bean id="Template" class="org.mybatis.spring.SqlSessionTemplate">
        <!--只能用构造方法注入sqlSessionFactory,因为SqlSessionTemplate没有set方法-->
        <constructor-arg index="0" ref="sqlSessionFactory"/>
    </bean>

    <bean id="sqmaip" class="com.gongfang.mapper.sqlmapperimp">
   <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
    </bean>
 
</beans>

7.测试:

import com.gongfang.User.Student1;
import com.gongfang.mapper.sqlmapper;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.List;

public class testsqlmapper {

    @Test
    public void getStudent1() {
        ApplicationContext res = new ClassPathXmlApplicationContext("spring-dao.xml");
        sqlmapper sqmaip = (sqlmapper) res.getBean("sqmaip");

        List<Student1> student1 = sqmaip.getStudent1();
        for (Student1 s:
             student1) {
            System.out.println(s);
        }

    }

    }

8.结果:

结果运行报错,但 “太始” 被添加到了数据表中

13.2.开启事务

1.spring中开启事务

   <!--开启事务-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
       <property name="dataSource" ref="dataSource"/>
    </bean>

2.导入 tx 支持与 aop 支持

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

3.大体

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

    <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/person?useUnicode=true&amp;characterEncoding=utf-8&amp;useSSL=true&amp;serverTimezone =UTC"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
    </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/gongfang/mapper/*.xml"/>
    </bean>


    <!--SqlSessionTemplate:就是使用的sqlSession-->
    <bean id="Template" class="org.mybatis.spring.SqlSessionTemplate">
        <!--只能用构造方法注入sqlSessionFactory,因为SqlSessionTemplate没有set方法-->
        <constructor-arg index="0" ref="sqlSessionFactory"/>
    </bean>

    <bean id="sqmaip" class="com.gongfang.mapper.sqlmapperimp">
   <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
    </bean>

<!-- =======================================================================================-->
    <!--开启事务-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
       <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--结合aop事务织入,配置事务类-->
    <tx:advice id="txadvice" transaction-manager="transactionManager">
        <!--给方法配置事务-->
        <tx:attributes>
        <!--    <tx:method name="add" propagation="REQUIRED"/>
            <tx:method name="delete" propagation="REQUIRED"/>
            <tx:method name="updete" propagation="REQUIRED"/>
            <tx:method name="query" read-only="true"/>-->
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>

    <!--配置事务切入-->
    <aop:config>
        <aop:pointcut id="pointcut" expression="execution(* com.gongfang.mapper.*.*(..))"/>
        <aop:advisor advice-ref="txadvice" pointcut-ref="pointcut"/>

    </aop:config>

</beans>


4.结果:

程旭报错,用户没被添加数据表中,完成了一致性

14.总结spring

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

spring是一个轻量级的 控制反转,面向切面编程的框架

本文地址:https://blog.csdn.net/weixin_46311020/article/details/111616138