spring

3 篇文章 0 订阅
1 篇文章 0 订阅

Spring

1.spring简介和学习信息

  1. spring官网:

https://spring.io/projects/spring-framework#learn

在这里插入图片描述

  1. githup源码地址:

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

    可以通过官网的githup图标连接过去

在这里插入图片描述

  1. maven依赖:可以直接导包spring-webmvc,因为它能自动帮我们导很多其他依赖包

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

2.spring优点

  1. spring是免费开源框架(容器)
  2. spring是轻量级的,非入侵的框架
  3. 控制反转(IOC),面向切面编程(AOP)
  4. 支持事务处理,对框架整合的支持

总结:spring是控制反转,面向切面编程的框架

3.spring入门

pojo类

package com.ting.pojo;

public class Hello {
    private String str;

    public String getStr() {
        return str;
    }

    public void setStr(String str) {
        this.str = str;
    }

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

xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--配置文件来源spring官网文档:
    https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#spring-core
    -->
    <!--传统的创建对象:
            类型 变量名 = new 对象
        spring创建对象:
            id 相当于变量名,class相当于new的那个对象,properties中的值相当于赋值
    -->
    <bean id="hello" class="com.ting.pojo.Hello">
        <!--此处的赋值是调用的Hello类中的setter方法,如果没有set方法,赋值会报错-->
        <property name="str" value="spring"/>
    </bean>

</beans>

测试类:

package com.ting.pojo;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class HelloTest {
    /**
     *
     */
    @Test
    public void Hello()throws Exception{
//        可以传入多个配置文件
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//        Hello hello = (Hello) context.getBean("hello");
        Hello hello = context.getBean("hello", Hello.class);
        System.out.println(hello);
    }

}

4.ioc创建对象

4.1使用无参构造创建对象(默认方法)

4.1.1进行添加配置文件时,idea设置spring配置文件的支持,操作如下:
在这里插入图片描述

在这里插入图片描述

设置之后,一个类被spring管理后,有提示,可以通过点击进行到配置文件中的跳转:

在这里插入图片描述

pojo类:

package com.ting.pojo;

public class User {
    private String name;

    public User() {
        System.out.println("调用了User的无参构造方法");
    }

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

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

    public String getName() {
        return name;
    }

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

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

无参构造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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--无参构造创建对象-->
    <bean id="user" class="com.ting.pojo.User">
        <property name="name" value="ting"/>
    </bean>
</beans>

无参构造测试类:

@Test
public void TestUser()throws Exception{
    // 获取容器
    ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
    // 获取user对象
    User user = context.getBean("user", User.class);
    user.show();
}

4.2有参构造(3种方式)

  1. 使用索引

    <!--有参构造,使用下标-->
    <bean id="user" class="com.ting.pojo.User">
        <constructor-arg index="0" value="use index"/>
    </bean>
    
  2. 使用类型(不推荐)

    <!--通过类型创建对象,不推荐-->
    <bean id="user" class="com.ting.pojo.User">
        <constructor-arg type="java.lang.String" value="use type"/>
    </bean>
    
  3. 使用名字(常用,推荐)

    <!--通过名称创建对象,推荐且常用-->
    <bean id="user" class="com.ting.pojo.User">
        <constructor-arg name="name" value="use name"/>
    </bean>
    

注意:spring在加载配置文件时,会将配置文件中的所有bean都进行创建对象

5.spring配置

5.1别名

alias创建bean的别名设置:

<!--alias设置别名-->
<alias name="user" alias="user2"/>

测试类中创建对象是可以用user和user2进行获取bean

5.2bean配置

<!--bean的属性
    id:唯一标识符,相当于对象名
    class:全限定名,包名+类名
    name:别名,可以用空格,逗号,分号,进行别名的分隔,能同时起多个别名
    scope:可以设置创建对象是不是单例,默认单例
-->
<bean id="user" class="com.ting.pojo.User" name="u u1,u2;u3">
    <constructor-arg name="name" value="use name"/>
</bean>

可以用u,u1,u2,u3以及user获取bean,比alias强大

5.3import

用于团队开发,将多个配置文件导入合成一个.如张三,李四,王五三个人开发三个功能使用了3个不同名字的beans.xml,可以都导入到指定的配置文件中,如:applicationContext.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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <import resource="beans.xml"/>
    <import resource="beans1.xml"/>
    <import resource="beans2.xml"/>
</beans>

6.DI依赖注入

6.1环境搭建

  1. pojo类

    package com.ting.pojo;
    // 需要get和set方法,自己补充
    public class Address {
        private String address;
    }
    
    package com.ting.pojo;
    
    import java.util.*;
    // 需要get和set方法,自己补充
    public class Student {
        private String name;
        private Address address;
        private String[] books;
        private List<String> hobbys;
        private Map<String, String> card;
        private Set<String> games;
        private String wife;
        private Properties info;
    }
    
  2. beans.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd">
    	<!--简单注入-->
        <bean id="student" class="com.ting.pojo.Student">
            <property name="name" value="ting"/>
        </bean>
    </beans>
    
  3. 测试类

    @Test
    public void testDI()throws Exception{
        ApplicationContext context = new ClassPathXmlApplicationContext(&quot;beans.xml&quot;);
        Student student = context.getBean(&quot;student&quot;, Student.class);
        System.out.println(student.getName());
    }
    

6.2各种类型的set注入(重点)

<bean id="address" class="com.ting.pojo.Address">
    <property name="address" value="北京"/>
</bean>

<bean id="student" class="com.ting.pojo.Student">
    <!--简单注入-->
    <property name="name" value="ting"/>
    <!--引用注入-->
    <property name="address" ref="address"/>
    <!--数组-->
    <property name="books">
        <array>
            <value>三国</value>
            <value>红楼</value>
        </array>
    </property>
    <!--list-->
    <property name="hobbys">
        <list>
            <value>抽烟</value>
            <value>喝酒</value>
            <value>烫头</value>
        </list>
    </property>
    <!--map-->
    <property name="card">
        <map>
            <entry key="身份证" value="11111122222233333344"/>
            <entry key="银行卡" value="5556667889900067784"/>
        </map>
    </property>
    <!--set-->
    <property name="games">
        <set>
            <value>LOL</value>
            <value>BOB</value>
        </set>
    </property>
    <!--properties-->
    <property name="info">
        <props>
            <prop key="学号">1121821</prop>
            <prop key="姓名">ting</prop>
            <prop key="性别"></prop>
        </props>
    </property>
    <!--null-->
    <property name="wife">
        <null/>
    </property>
</bean>

测试类和结果:

@Test
public void testDI()throws Exception{
    ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
    Student student = context.getBean("student", Student.class);
    System.out.println(student);
    /*
    结果:
    Student{
    name='ting', 
    address=Address{address='北京'}, 
    books=[三国, 红楼], 
    hobbys=[抽烟, 喝酒, 烫头], 
    card={身份证=11111122222233333344, 
    银行卡=5556667889900067784}, 
    games=[LOL, BOB], 
    wife='null', 
    info={学号=1121821, 性别=男, 姓名=ting}}
     */
}

6.3其他注入方式

  1. c命名空间和p命名空间注入

    pojo类:

    c命名空间相当于构造方法注入,使用时需要声明有参构造和无参构造

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

    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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <!--p命名空间注入-->
        <bean id="user" class="com.ting.pojo.User" p:name="张三" p:age="23"/>
        <!--c命名空间注入-->
        <bean id="user2" class="com.ting.pojo.User" c:name="李四" c:age="24"/>
    </beans>
    

    测试类:

    @Test
    public void test2() {
        ApplicationContext context = new ClassPathXmlApplicationContext("userbeans.xml");
        // p命名空间注入
        User user = context.getBean("user", User.class);
        System.out.println(user);
        // c命名空间注入
        User user2 = context.getBean("user2", User.class);
        System.out.println(user2);
    }
    

    注意:p和c命名空间不能直接使用,需要导入约束

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

6.4构造器注入

参考前面讲解4.2有参构造

6.5bean的作用域

在这里插入图片描述

  1. 单例模式(spring的默认机制)

    <bean id="user" class="com.ting.pojo.User" p:name="张三" p:age="23" scope="singleton"/>
    
  2. 原型模式:每次get的时候都会获取一个新对象

    <bean id="user" class="com.ting.pojo.User" p:name="张三" p:age="23" scope="prototype"/>
    
  3. 其余的request,session,application这些只能在web开发中使用

7.bean的自动装配

spring在上下文中自动寻找,并自动给bean装配

spring的自动转配有三种:

  • xml中显示装配
  • java中显示配置
  • 隐式的自动装配(重点)

7.1测试

xml显式配置:

<bean id="cat" class="com.ting.pojo.Cat"/>
<bean id="dog" class="com.ting.pojo.Dog"/>
<bean id="people" class="com.ting.pojo.People">
    <property name="name" value="zhangsan"/>
    <property name="cat" ref="cat"/>
    <property name="dog" ref="dog"/>
</bean>

7.2byName和byType

<bean id="cat" class="com.ting.pojo.Cat"/>
<bean id="dog" class="com.ting.pojo.Dog"/>
<!--
byName:会自动在容器上下文查找和自己对象set方法后面的值相对应的beanid
byType:会自动在容器上下文查找和自己对象属性类型相同的bean
-->
<bean id="people" class="com.ting.pojo.People" autowire="byName">
    <property name="name" value="zhangsan"/>
</bean>
<bean id="people2" class="com.ting.pojo.People" autowire="byType">
    <property name="name" value="zhangsan"/>
</bean>

小结:

  1. byName:需要保证所有bean的id唯一,并且bean需要和自动注入的id和set方法的参数一致
  2. byType:需要保证所有bean的class唯一,并且bean需要和自动注入的属性类型一致

7.3使用注解装配

使用解的注意事项:

  1. 需要导入约束

    xmlns:context="http://www.springframework.org/schema/context"
    http://www.springframework.org/schema/context
    https://www.springframework.org/schema/beans/spring-context.xsd
    
  2. 需要开启注解的支持

    <context:annotation-config/>
    

整体xml:

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

    <context:annotation-config/>

</beans>
@Autowired:自动装配
  1. @Autowired可以用在属性上,也可以用在set方法上

  2. 如果自动装配的属性在ioc容器中存在,且符合byName的规则,使用@Autowired可以不用写set方法

  3. @Autowired注解内容:

    public @interface Autowired {
        boolean required() default true;
    }
    

    注意:如果显示定义了required为false,说明这个对象可以为null,否则不允许为空

    @Autowired(required = false)

  4. 如果装配环境比较复杂,不能通过@Autowired注解指定唯一的对象进行装配,我们可以通过@Qualifier(value = “xml中配置的beanid”)来进行唯一装配

    public class People {
        @Autowired
        @Qualifier(value = "cat11")
        private Cat cat;
        @Autowired
        @Qualifier(value = "dog11")
        private Dog dog;
        private String name;
    }
    
    <bean id="cat" class="com.ting.pojo.Cat"/>
    <bean id="cat11" class="com.ting.pojo.Cat"/>
    <bean id="dog11" class="com.ting.pojo.Dog"/>
    <bean id="dog" class="com.ting.pojo.Dog"/>
    
  5. @Resource(功能强大,但是使用较少)

    1. java原生的注解,也能用于自动装配,会根据名字或者class进行自动装配

    2. @Resource(name = “cat11”)可以通过name直接beanid实现唯一装配

      public class People {
      //    @Autowired
      //    @Qualifier(value = "cat11")
          @Resource(name = "cat11")
          private Cat cat;
          @Autowired
          @Qualifier(value = "dog11")
          private Dog dog;
          private String name;
      }
      

小结:

@Resource和@Autowired区别:

  1. 在这里插入图片描述
@Nullable:为空
  1. 标了这个注解数据这个字段可以为null,且不会报错

8.使用注解开发

  1. spring4之后想要使用注解,必须导入aop依赖包,在导入webmvc时能自动导入,如果注解不能使用可以查看这个包是否存在

在这里插入图片描述

  1. 使用直接需要导入context约束和开启注解支持

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            https://www.springframework.org/schema/context/spring-context.xsd">
    	<!--开启注解的包扫描,会扫描包下的注解-->
        <context:component-scan base-package="com.ting"/>
        <context:annotation-config/>
    
    </beans>
    

bean注入

以下几个注解功能相同:

表示这个bean交给spring管理,是spring的一个组件,相当于配置文件中的<bean id="user" class="com.ting.pojo.User">

  • @Component:通用注解
  • @Controller:用于controller层
  • @Service::用于service层
  • @Repository:用于dao层

属性注入

@Value:用于属性值的注入相当于配置文件中的<property name="name" value="zhangsan"/>

自动装配注解(参考7.3)

作用域注解

@Scope("prototype")  //作用域注解,用于bean

小结:

xml和注解的优缺点:

  • xml更万能,便于维护,适用于所有场景
  • 注解只适用于自己的类,维护相对复杂

最佳实践:

  • 注解用于完成属性的注入
  • xml用于管理bean

注解应用时需要注意:

想要注解生效,必须开启注解的支持,如果用包扫描的方式,需要注意扫描的包路径

<!--开启注解的包扫描,会扫描包下的注解-->
<context:component-scan base-package="com.ting"/>
<!--开启注解的支持-->
<context:annotation-config/>

9.使用javaConfig配置类方式配置spring

这种是纯java的配置方式,全部使用注解,不再使用xml配置文件,这种方式在springboot中随处可见

pojo类

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

@Data
@Component
public class User {
    @Value("zhangsan")
    private String name;
}

主配置类

package com.ting.config;

import com.ting.pojo.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管理
//标志这个类是一个配置类,相当于beans.xml配置文件
@Configuration
@ComponentScan("com.ting.pojo") // 包扫描
@Import(MyConfig2.class) // 引入其他的配置类
public class MyConfig {
    // 注册一个bean,就相当于配置文件中的一个bean
    // 方法名相当于xml中的id属性,返回值相当于xml中的class属性
    @Bean
    public User getUser() {
        // 返回要注入的bean对象
        return new User();
    }
}

引用配置类

package com.ting.config;

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

@Configuration
public class MyConfig2 {
    @Bean
    public String testConfig() {
        return "测试@Import()注解";
    }
}

测试类:

import com.ting.config.MyConfig;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class MyTest {
    @Test
    public void test01() {
        //如果完全用配置类的方式去做,需要用AnnotationConfigApplicationContext来获取上线文,通过bean对象加载
        ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
//        User user = (User) context.getBean("getUser");
        String user = (String) context.getBean("testConfig");
        System.out.println(user);
    }
}

注意:

如果完全用配置类的方式去做,需要用AnnotationConfigApplicationContext来获取上线文,通过bean对象加载

10.代理模式

在这里插入图片描述

10.1静态代理

角色分析:

  • 抽象角色: 一般会使用接口或者抽象类来解决
  • 真实角色: 被代理的角色
  • 代理角色: 代理真实角色,代理真实角色后会做一些附属操作
  • 客户:使用的人

代码开发步骤:

接口编写

public interface Rent {
    void rent();
}

真实角色

public class Host implements Rent {
    public void rent() {
        System.out.println("房东出租房子");
    }
}

代理角色

public class Proxy implements Rent {

    private Host host;

    public Proxy() {
    }

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

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

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

    public void hetong() {
        System.out.println("中介和你签合同");
    }

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

客户测试

public class Client {
    public static void main(String[] args) {
        Proxy proxy = new Proxy(new Host());
        proxy.rent();
    }
}

代理模式的好处:

  • 可以使真实角色更纯粹,不用关注一些公共的业务
  • 公共业务交给代理角色,实现业务的分工
  • 公共业务发生扩展的时候,方便集中管理

缺点:

  • 一个真实角色,产生一个代理角色,代码量翻倍,开发效率低下

10.2动态代理

  • 动态代理和静态代理的角色相同
  • 动态代理的的代理类是动态生成的
  • 动态代理分两大类:基于接口和基于类的
    • 基于接口:jdk动态代理
    • 基于类:cglib
    • java字节码实现:javasist

需要了解两个类:

Proxy:代理类
InvocationHandler:调用处理程序

接口:

package com.ting.demo_03;

public interface Rent {
    void rent();
}

实体类:

package com.ting.demo_03;

public class Host implements Rent {
    public void rent() {
        System.out.println("房东出租房子");
    }
}

代理是处理类(通用的):

package com.ting.demo_03;

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

public class ProxyInvocationHandler implements InvocationHandler {
	// 代理处理的角色
    private Object target;
	// 设置代理处理角色,供下方获取代理类使用
    void setTarget(Object target) {
        this.target = target;
    }

    // 获取代理对象实例
    Object getProxy() {
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }

    // 处理代理实例,并返回结果
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 采用反射的invoke()方法,调用被代理类的方法
        Object result = method.invoke(target, args);

        return result;
    }
}

客户端:

package com.ting.demo_03;

public class Client {
    public static void main(String[] args) {
        // 真实角色
        Host host = new Host();
        // 代理类处理角色
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        // 设置代理那个角色
        pih.setTarget(host);
        // 获取代理角色
        Rent proxy = (Rent) pih.getProxy();

        proxy.rent();
    }
}

11. AOP

11.1aop的常用词:

在这里插入图片描述

11.2spring使用aop

spring使用aop必须导入织入的包

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.5</version>
</dependency>

11.3spring aop的使用方式

方式一:使用spring API接口
  1. 编写接口

    package com.ting.service;
    
    public interface UserService {
        void add();
        void delete();
        void update();
        void select();
    }
    
  2. 编写实现类

    package com.ting.service;
    
    public class UserServiceImpl implements UserService {
        public void add() {
            System.out.println("添加一个用户");
        }
    
        public void delete() {
            System.out.println("删除一个用户");
        }
    
        public void update() {
            System.out.println("更新一个用户");
        }
    
        public void select() {
            System.out.println("查询一个用户");
        }
    }
    
  3. 编写增强类

    前置日志:

    package com.ting.log;
    
    import org.springframework.aop.MethodBeforeAdvice;
    
    import java.lang.reflect.Method;
    
    public class BeforeLog implements MethodBeforeAdvice {
    
        // method 要执行目标对象的方法
        // objects 需要出入的参数,即args
        // o 传入的目标对象
        // before的源码:void before(Method method, Object[] args, @Nullable Object target)
        public void before(Method method, Object[] objects, Object o) throws Throwable {
            System.out.println(method.getClass().getName() + "执行了" + method.getName() + "方法" );
        }
    }
    

    后置日志:

    package com.ting.log;
    
    import org.springframework.aop.AfterReturningAdvice;
    
    import java.lang.reflect.Method;
    
    public class AfterLog implements AfterReturningAdvice {
    
        // returnValue方法返回值
        public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
            System.out.println(method.getName() + "被执行了,返回值是:" + returnValue);
        }
    }
    
  4. 将实现类和增强类在配置文件中注册,编写配置文件进行aop的切入

    在进行aop配置编写的时候必须先导入aop的约束:

    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"
           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 id="userService" class="com.ting.service.UserServiceImpl"/>
        <bean id="afterLog" class="com.ting.log.AfterLog"/>
        <bean id="beforeLog" class="com.ting.log.BeforeLog"/>
    
        <!--添加aop配置:添加配置前必须新增aop的约束
            xmlns:aop="http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop
            https://www.springframework.org/schema/aop/spring-aop.xsd
        -->
        <aop:config>
            <!--配置切点,可以配置多个-->
            <aop:pointcut id="pointcut" expression="execution(* com.ting.service.UserServiceImpl.*(..))"/>
            <!--配置通知(前置)-->
            <aop:advisor advice-ref="beforeLog" pointcut-ref="pointcut"/>
            <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
        </aop:config>
    </beans>
    
  5. 编写测试类,获取上下文进行aop测试

    import com.ting.service.UserService;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class MyTest {
        public static void main(String[] args) {
            // 获取容器
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
            UserService userService = (UserService) context.getBean("userService");
            userService.add();
        }
    }
    
方式二:自定义类实现aop
  1. 自定义增强类

    package com.ting.div;
    
    public class DivLog {
        public void beforeLog() {
            System.out.println("========切入到方法之前执行===========");
        }
    
        public void afterLog() {
            System.out.println("========切入到方法之后执行===========");
        }
    }
    
  2. 编写配置文件,将增强类作为切面,各个方法对应切入到各切点中

    <!--方式二:自定义类进行aop-->
    <!--在spring注册自定义的增强类-->
    <bean id="div" class="com.ting.div.DivLog"/>
    <aop:config>
        <!--配置切点-->
        <aop:pointcut id="pointcut" expression="execution(* com.ting.service.UserServiceImpl.*(..))"/>
        <!--配置切面-->
        <aop:aspect ref="div">
            <aop:before method="beforeLog" pointcut-ref="pointcut"/>
            <aop:after method="afterLog" pointcut-ref="pointcut"/>
        </aop:aspect>
    </aop:config>
    
  3. 接口,实现类,测试类和方式一中相同

方式三:使用注解实现AOP
  1. 在配置文件中开启aop的注解支持

    <!--方式三:使用注解进行过aop-->
        <!--开启aop注解支持-->
        <aop:aspectj-autoproxy/>
    	<!--将自定义的增强类,注册到spring容器中,也可以用下面spring的注解方法向spring容器注册-->
        <bean id="annotionDiv" class="com.ting.div.AnnotionDiv"/>
        <!--开启spring的注解支持-->
    <!--    <context:annotation-config/>-->
    <!--    <context:component-scan base-package="com.ting"/>-->
    
  2. 自定义一个增强类,用注解@Aspect标注为切面

  3. 编写对应的方法,分别将对应的切点导入,例如:@Before(“execution(* com.ting.service.UserServiceImpl.*(…))”)

    package com.ting.div;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.springframework.stereotype.Component;
    
    // 方式三,使用注解方式实现AOP
    @Aspect // 此注解将这个类标记成切面
    @Component //将这个类交给spring管理
    public class AnnotionDiv {
        @Before("execution(* com.ting.service.UserServiceImpl.*(..))")
        public void before() {
            System.out.println("****方法执行前****");
        }
    
        @After("execution(* com.ting.service.UserServiceImpl.*(..))")
        public void after() {
            System.out.println("*****方法执行后******");
        }
    
        // 环绕通知,可以传入一个参数作为一个连接点,用于方法的执行
        @Around("execution(* com.ting.service.UserServiceImpl.*(..))")
        public void around(ProceedingJoinPoint jp) throws Throwable {
            System.out.println("*************环绕通知**************");
            System.out.println("环绕前");
            // 方法执行
            System.out.println(jp.getSignature()); // 获取方法签名
            Object proceed = jp.proceed();
            System.out.println("环绕后");
        }
    }
    
  4. 执行测试方法

    测试结果:

在这里插入图片描述

12.spring整合mybatis

12.1整合步骤

  • 导入依赖jar包
    • junit
    • mybatis
    • mysql
    • spring相关
    • aop织入
    • mybatis-spring
  • 编写配置文件
  • 测试

12.2回顾mybatis

  1. 编写实体类

    package com.ting.pojo;
    
    import lombok.Data;
    
    @Data
    public class User {
        private int id;
        private String name;
        private String pwd;
    }
    
  2. 编写核心配置文件

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    
    <!--核心配置文件-->
    <configuration>
        <typeAliases>
            <package name="com.ting"/>
        </typeAliases>
    
        <environments default="test">
            <environment id="test">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                    <property name="url"
                              value="jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&amp;useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
                    <property name="username" value="root"/>
                    <property name="password" value="root"/>
                </dataSource>
            </environment>
        </environments>
        <mappers>
            <mapper resource="com/ting/mapper/UserMapper.xml"/>
        </mappers>
    </configuration>
    
  3. 编写接口和接口的xml配置文件

    package com.ting.mapper;
    
    import com.ting.pojo.User;
    
    import java.util.List;
    
    public interface UserMapper {
        List<User> selectUser();
    }
    
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <mapper namespace="com.ting.mapper.UserMapper">
        <select id="selectUser" resultType="user">
            select * from mybatis.user
        </select>
    </mapper>
    
  4. 将接口的xml注册到核心配置文件中

    在这里插入图片描述

  5. 编写测试类

    import com.ting.mapper.UserMapper;
    import com.ting.pojo.User;
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    import org.junit.Test;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    
    
    public class MyTest {
        @Test
        public void test01() throws IOException {
            String resources = "mybatis-config.xml";
            InputStream in = Resources.getResourceAsStream(resources);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
            SqlSession sqlSession = sqlSessionFactory.openSession();
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            List<User> users = mapper.selectUser();
            for (User user : users) {
                System.out.println(user);
            }
        }
    }
    

12.3spring和mybatis整合

方式一:

pom文件版本

<dependencies>
   		<dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.18</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.6</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.5</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.6</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.3.9</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.9</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.10</version>
        </dependency>
    </dependencies>
    <!--在builder中配置资源,防止找不到-->
    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>
  1. 在spring-dao.xml配置文件中配置数据源,取代mybatis配置的数据源

    在这里插入图片描述

  2. 在spring-dao.xml配置文件中配置sqlSessionFactory

    在这里插入图片描述

  3. 在spring-dao.xml配置文件中配置sqlSessionTemplate,替代sqlSession

    在这里插入图片描述

    完整的spring-dao.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">
    
        <!--引入数据源,替代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/mybatis?serverTimezone=UTC&amp;useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
            <property name="username" value="root"/>
            <property name="password" value="root"/>
        </bean>
    
        <!--sqlSessionFactory创建-->
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <!--加载数据源-->
            <property name="dataSource" ref="dataSource"/>
            <!--装配mybatis的配置文件,spring可以完全取代mybatis的配置-->
            <property name="configLocation" value="classpath:mybatis-config.xml"/>
            <!--加载mapper的配置文件-->
            <property name="mapperLocations" value="classpath:com/ting/mapper/*.xml"/>
        </bean>
        <!--通过spring的SqlSessionTemplate创建sqlsession,
        由于没有set方法,需要使用构造方法将sqlSessionFactory注入到SqlSessionTemplate中-->
        <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
            <constructor-arg index="0" ref="sqlSessionFactory"/>
        </bean>
    
    </beans>
    
  4. 创建接口实现类,用来进行进行接口方法的实现

    package com.ting.mapper;
    
    import com.ting.pojo.User;
    import org.mybatis.spring.SqlSessionTemplate;
    
    import java.util.List;
    
    public class UserMapperImpl implements UserMapper {
    
        private SqlSessionTemplate sqlSession;
    
        public void setSqlSession(SqlSessionTemplate sqlSession) {
            this.sqlSession = sqlSession;
        }
    
        public List<User> selectUser() {
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            return mapper.selectUser();
        }
    }
    
  5. 在applicationContext.xml中引入spring-dao.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">
    
        <import resource="spring-dao.xml"/>
        <bean id="userMapper" class="com.ting.mapper.UserMapperImpl">
            <property name="sqlSession" ref="sqlSession"/>
        </bean>
    
    </beans>
    
  6. 测试,应用sping的配置文件,调用接口的方法实现

    @Test
    public void test02() {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
        for (User user : userMapper.selectUser()) {
            System.out.println(user);
        }
    }
    
方式二(简化):

实现类需要继承SqlSessionDaoSupport类,继承之后可以使用getSqlSession()方法来获取sqlSession,进行响应的操作.

接口实现类:

package com.ting.mapper;

import com.ting.pojo.User;
import org.apache.ibatis.session.SqlSession;
import org.mybatis.spring.support.SqlSessionDaoSupport;

import java.util.List;

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

spirng核心配置文件注册的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: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">

    <import resource="spring-dao.xml"/>
    <bean id="userMapper" class="com.ting.mapper.UserMapperImpl">
        <property name="sqlSession" ref="sqlSession"/>
    </bean>

    <!--通过继承SqlSessionDaoSupport来进行mybatis的整合-->
    <bean id="userMapper2" class="com.ting.mapper.UserMapperImpl2">
        <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
    </bean>
</beans>

因为sqlSession可以通过继承SqlSessionDaoSupport类来获取,索引spring-dao.xml的配置文件中,都不需要注册sqlSession的bean

在这里插入图片描述

13.声明式事务

声明式事务主要使用的是spring的aop进行事务的切入,对不同的方法进行增加事务,保证数据的一致性,具体操作是修改spring-dao.xml的配置文件,增加事务的使用和aop的事务切入

  1. 使用事务,需要先增加事务的约束

    xmlns:tx="http://www.springframework.org/schema/tx"
    http://www.springframework.org/schema/tx
    https://www.springframework.org/schema/tx/spring-tx.xsd
    
  2. 配置中增加事务管理,引入数据源

    <!--配置声明式事务-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    
  3. 配置事务的通知,通过aop的织入方式将事务织入到不同的方法中

    <!--结合sprin的aop织入-->
        <!--配置事务通知-->
        <tx:advice id="txAdvice" transaction-manager="transactionManager">
            <!--给方法配置事务-->
            <!--配置事务的传播特性:propagation,默认是"REQUIRED",一般使用默认值就行,代表存在事务的时候使用,不存在事务时创建事务-->
            <tx:attributes>
                <tx:method name="*" propagation="REQUIRED"/>
                <tx:method name="add*" propagation="REQUIRED"/>
                <tx:method name="delete*" propagation="REQUIRED"/>
                <tx:method name="update*" propagation="REQUIRED"/>
                <tx:method name="select*" propagation="REQUIRED"/>
            </tx:attributes>
        </tx:advice>
    
  4. 通过spring的aop配置切点,将事务切入

    <!--配置aop切入事务-->
    <aop:config>
        <aop:pointcut id="txPointCut" expression="execution(* com.ting.mapper.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
    </aop:config>
    
  5. 进行测试

    public class MyTest {
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
            UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
            for (User user : userMapper.selectUser()) {
                System.out.println(user);
            }
        }
    }
    
  6. 完整的spirng-dao.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"
           xmlns:tx="http://www.springframework.org/schema/tx"
           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
            http://www.springframework.org/schema/tx
            https://www.springframework.org/schema/tx/spring-tx.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/mybatis?serverTimezone=UTC&amp;useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
            <property name="username" value="root"/>
            <property name="password" value="root"/>
        </bean>
    
        <!--sqlSessionFactory创建-->
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <!--加载数据源-->
            <property name="dataSource" ref="dataSource"/>
            <!--装配mybatis的配置文件,spring可以完全取代mybatis的配置-->
            <property name="configLocation" value="classpath:mybatis-config.xml"/>
            <!--加载mapper的配置文件-->
            <property name="mapperLocations" value="classpath:com/ting/mapper/*.xml"/>
        </bean>
    
        <!--配置声明式事务-->
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource"/>
        </bean>
    
        <!--结合sprin的aop织入-->
        <!--配置事务通知-->
        <tx:advice id="txAdvice" transaction-manager="transactionManager">
            <!--给方法配置事务-->
            <!--配置事务的传播特性:propagation,默认是"REQUIRED",一般使用默认值就行,代表存在事务的时候使用,不存在事务时创建事务-->
            <tx:attributes>
                <tx:method name="*" propagation="REQUIRED"/>
                <tx:method name="add*" propagation="REQUIRED"/>
                <tx:method name="delete*" propagation="REQUIRED"/>
                <tx:method name="update*" propagation="REQUIRED"/>
                <tx:method name="select*" propagation="REQUIRED"/>
            </tx:attributes>
        </tx:advice>
        <!--配置aop切入事务-->
        <aop:config>
            <aop:pointcut id="txPointCut" expression="execution(* com.ting.mapper.*.*(..))"/>
            <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
        </aop:config>
    </beans>
    
   <!--sqlSessionFactory创建-->
   <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
       <!--加载数据源-->
       <property name="dataSource" ref="dataSource"/>
       <!--装配mybatis的配置文件,spring可以完全取代mybatis的配置-->
       <property name="configLocation" value="classpath:mybatis-config.xml"/>
       <!--加载mapper的配置文件-->
       <property name="mapperLocations" value="classpath:com/ting/mapper/*.xml"/>
   </bean>

   <!--配置声明式事务-->
   <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
       <property name="dataSource" ref="dataSource"/>
   </bean>

   <!--结合sprin的aop织入-->
   <!--配置事务通知-->
   <tx:advice id="txAdvice" transaction-manager="transactionManager">
       <!--给方法配置事务-->
       <!--配置事务的传播特性:propagation,默认是"REQUIRED",一般使用默认值就行,代表存在事务的时候使用,不存在事务时创建事务-->
       <tx:attributes>
           <tx:method name="*" propagation="REQUIRED"/>
           <tx:method name="add*" propagation="REQUIRED"/>
           <tx:method name="delete*" propagation="REQUIRED"/>
           <tx:method name="update*" propagation="REQUIRED"/>
           <tx:method name="select*" propagation="REQUIRED"/>
       </tx:attributes>
   </tx:advice>
   <!--配置aop切入事务-->
   <aop:config>
       <aop:pointcut id="txPointCut" expression="execution(* com.ting.mapper.*.*(..))"/>
       <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
   </aop:config>
```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值