Spring总结

一、Spring简介

Spring官网
  Spring框架是一个开放源代码的J2EE应用程序框架,由Rod Johnson发起,是针对bean的生命周期进行管理的轻量级容器(lightweight container)。 Spring解决了开发者在J2EE开发中遇到的许多常见的问题,提供了功能强大IOC、AOP及Web MVC等功能。Spring可以单独应用于构筑应用程序,也可以和Struts、Webwork、Tapestry等众多Web框架组合使用,并且可以与 Swing等桌面应用程序AP组合。因此, Spring不仅仅能应用于J2EE应用程序之中,也可以应用于桌面应用程序以及小应用程序之中。Spring框架主要由七部分组成,分别是 Spring Core、 Spring AOP、 Spring ORM、 Spring DAO、Spring Context、 Spring Web和 Spring Web MVC。

二、环境构建

首先根据导入一下spring-webmvc的包

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

三、IOC核心本质

首先我们编写一下对应测试的代码
com.imperfect.dao.UserDao

import com.imperfect.service.UserService;
import com.imperfect.service.UserServiceImpl;

/**
 * @author : Imperfect(lxm)
 * @Des:
 * @date : 2023/1/19  14:06
 */
public class Test {
    public static void main(String[] args) {
        UserService userService = new UserServiceImpl();
        userService.getUser();
    }
}

com.imperfect.dao.UserDaoImpl

package com.imperfect.dao;

/**
 * @author : Imperfect(lxm)
 * @Des:
 * @date : 2023/1/19  14:01
 */
public class UserDaoImpl implements UserDao {

    public void getUser() {
        System.out.println("获取用户信息");
    }
}

com.imperfect.dao.UserDaoMysqlImpl

package com.imperfect.dao;

/**
 * @author : Imperfect(lxm)
 * @Des:
 * @date : 2023/1/19  14:09
 */
public class UserDaoMysqlImpl implements UserDao{
    public void getUser() {
        System.out.println("获取Mysql用户信息");
    }
}

com.imperfect.dao.UserDaoOracleImpl

package com.imperfect.dao;

/**
 * @author : Imperfect(lxm)
 * @Des:
 * @date : 2023/1/19  14:10
 */
public class UserDaoOracleImpl implements UserDao {
    public void getUser() {
        System.out.println("获取Oracle用户信息");
    }
}

com.imperfect.service.UserService

package com.imperfect.service;

/**
 * @author : Imperfect(lxm)
 * @Des:
 * @date : 2023/1/19  14:02
 */
public interface UserService {

    public void getUser();
}

com.imperfect.service.UserServiceImpl

package com.imperfect.service;

import com.imperfect.dao.UserDao;
import com.imperfect.dao.UserDaoImpl;
import com.imperfect.dao.UserDaoMysqlImpl;
import com.imperfect.dao.UserDaoOracleImpl;

/**
 * @author : Imperfect(lxm)
 * @Des:
 * @date : 2023/1/19  14:02
 */
public class UserServiceImpl implements UserService {

    private UserDao userDao=new UserDaoImpl();
    private UserDao userDaoMysql=new UserDaoMysqlImpl();
    private UserDao userDaoOracle=new UserDaoOracleImpl();

    public void getUser() {
        userDao.getUser();
    }
}

Test测试类代码

import com.imperfect.service.UserService;
import com.imperfect.service.UserServiceImpl;

/**
 * @author : Imperfect(lxm)
 * @Des:
 * @date : 2023/1/19  14:06
 */
public class Test {
    public static void main(String[] args) {
        UserService userService = new UserServiceImpl();
        userService.getUser();
    }
}

整体项目代码结构:
在这里插入图片描述
利用我们本来Java中组合的概念,当我们需要在业务层调用Dao层的时候,往往需要在业务层中通过调用不同的Dao层从而实现对应各种业务。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

例如:这里如果我们需要调用UserDaoImpl的业务的时候,我们就需要手动修改getUser方法中对应的调用的dao层。需要调用userDaoMysql层的时候,我们就需要手动getUser方法中对应的调用的dao层。需要调用userDaoOracle层的时候,我们就需要手动getUser方法中对应的调用的dao层。

现在我们修改一下UserServiceImpl这个类
com.imperfect.service.UserServiceImpl
新增以下代码

private UserDao dao;


//利用set进行动态实现值的注入
public void setUserDao(UserDao dao){
    this.dao=dao;
}

现在我们再来编写一下测试类

import com.imperfect.dao.UserDaoMysqlImpl;
import com.imperfect.service.UserService;
import com.imperfect.service.UserServiceImpl;

/**
 * @author : Imperfect(lxm)
 * @Des:
 * @date : 2023/1/19  14:06
 */
public class Test {
    public static void main(String[] args) {
        UserService userService = new UserServiceImpl();
        userService.setUserDao(new UserDaoOracleImpl());
        userService.getUser();
    }
}

在这里插入图片描述
这里对程序发生了一个质的变化
相比于我们一开始写的代码
之前的业务:用户的需求可能会影响我们原来的代码,我们需要根据用户的需求去修改原代码。
现在:我们使用了一个set接口进行动态实现值的注入。
区别:之前我们程序是主动的去创建对象,控制权在程序员的手上。现在程序不再具有主动性,而是变成了被动的接收对象。
这种思想从本质上解决了问题,我们不再需要去管理对象的创建了。系统的耦合性大大降低。
这就是IOC的原型。
在这里插入图片描述
在这里插入图片描述

四、Hello,Spring

首先我们编写一下对应的代码
com.imperfect.pojo.Hello

package com.imperfect.pojo;

/**
 * @author : Imperfect(lxm)
 * @Des:
 * @date : 2023/1/19  14:42
 */
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 + '\'' +
                '}';
    }
}

src/main/resources/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="hello" class="com.imperfect.pojo.Hello">
        <property name="str" value="Spring">
        </property>
    </bean>

</beans>

根据Spring官方文档的介绍:我们可以构建ApplicationContext容器来接收对象
在这里插入图片描述

编写对应的测试类

import com.imperfect.pojo.Hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author : Imperfect(lxm)
 * @Des:
 * @date : 2023/1/19  15:03
 */
public class Test {

    public static void main(String[] args) {
        //获取Spring的上下文对象
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        //我们的对象都在Spring中管理了
        Object hello =(Hello) context.getBean("hello");
        System.out.println(hello.toString());
    }


}

测试结果
在这里插入图片描述
在这里插入图片描述

五、IOC创建对象

1、使用无参构造来创建对象

com.imperfect.pojo.Hello

  public Hello() {
        System.out.println("使用了无参构造方法");
    }

在这里插入图片描述

2、使用有参构造来创建对象

com.imperfect.pojo.Hello
增加以下代码

  public Hello(String str) {
        System.out.println("通过有参构造来创建对象");
        this.str = str;
    }

src/main/resources/beans.xml

 <!--第一种方式    通过下标赋值-->
    <bean id="hello" class="com.imperfect.pojo.Hello">
        <constructor-arg index="0" value="imperfect">
        </constructor-arg>
    </bean>

    <!--第二种方式    通过类型赋值-->
    <bean id="hello" class="com.imperfect.pojo.Hello">
        <constructor-arg type="java.lang.String" value="imperfect">
        </constructor-arg>
    </bean>

    <!--    第三种方式 直接通过参数名来赋值-->
    <bean id="hello" class="com.imperfect.pojo.Hello">
        <constructor-arg name="str" value="imperfect">
        </constructor-arg>
    </bean>

在这里插入图片描述

六、依赖注入之Set注入

首先我们构建一下测试的环境
com.imperfect.pojo.Address

package com.imperfect.pojo;

/**
 * @author : Imperfect(lxm)
 * @Des:
 * @date : 2023/1/19  15:46
 */
public class Address {


    private String adddress;

    public String getAdddress() {
        return adddress;
    }

    public void setAdddress(String adddress) {
        this.adddress = adddress;
    }

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

com.imperfect.pojo.Student

package com.imperfect.pojo;

import java.util.*;

/**
 * @author : Imperfect(lxm)
 * @Des:
 * @date : 2023/1/19  15:46
 */
public class Student {
    private String name;
    private Address address;
    private String[] books;
    private List<String> hobbys;
    private Map<String,String> card;
    private Set<String> games;
    private String wife;
    private Properties info;

    public String getName() {
        return name;
    }

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

    public Address getAddress() {
        return address;
    }

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

    public String[] getBooks() {
        return books;
    }

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

    public List<String> getHobbys() {
        return hobbys;
    }

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

    public Map<String, String> getCard() {
        return card;
    }

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

    public Set<String> getGames() {
        return games;
    }

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

    public String getWife() {
        return wife;
    }

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

    public Properties getInfo() {
        return info;
    }

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

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", address=" + address +
                ", books=" + Arrays.toString(books) +
                ", hobbys=" + hobbys +
                ", card=" + card +
                ", games=" + games +
                ", wife='" + wife + '\'' +
                ", info=" + info +
                '}';
    }
}

src/main/resources/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="address" class="com.imperfect.pojo.Address">
        <property name="adddress" value="广州"></property>
    </bean>
    <bean id="student" class="com.imperfect.pojo.Student">
        <!--            第一种普通值的注入-->
        <property name="name" value="imperfect"></property>
        <!--            第二种bean的注入-->
        <property name="address" ref="address"></property>
        <property name="books">
            <array>
                <value>红楼梦</value>
                <value>西游记</value>
                <value>水浒传</value>
            </array>
        </property>
        <property name="hobbys">
            <list>
                <value>听歌</value>
                <value>看电影</value>
            </list>
        </property>
        <property name="card">
            <map>
                <entry key="身份证" value="123132312123"></entry>
                <entry key="银行卡" value="1231322322123"></entry>
            </map>
        </property>

        <property name="games">
            <set>
                <value>英雄联盟</value>
                <value>王者荣耀</value>
            </set>
        </property>

        <property name="wife">
            <null/>
        </property>

        <property name="info">
            <props>
                <prop key="学号">123123</prop>
                <prop key="姓名">imperfect</prop>

            </props>
        </property>

    </bean>

</beans>

MyTest

import javafx.application.Application;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author : Imperfect(lxm)
 * @Des:
 * @date : 2023/1/19  15:50
 */
public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context =new ClassPathXmlApplicationContext("beans.xml");
        Object student = context.getBean("student");
        System.out.println(student.toString());
    }
}

测试结果:
在这里插入图片描述

七、Bean作用域

根据Spring官方文档的介绍
在这里插入图片描述

1、单例模式(Spring默认机制)

在这里插入图片描述
关于单例模式后续会另外出一篇文章来进行详细讲解

2、原型模式

每次从容器中get的时候都会产生一个新对象

<bean id="student" class="com.imperfect.pojo.Student" scope="prototype">

在这里插入图片描述

3、其余的request、session、application,这个只能在Web开发中使用

八、Bean的自动装配

自动装配是Spring满足bean依赖的一种方式
Spring会在上下文自动寻找,并自动给bean装配属性

首先先编写对应的测试代码
com.imperfect.pojo.Cat

package com.imperfect.pojo;

/**
 * @author : Imperfect(lxm)
 * @Des:
 * @date : 2023/1/19  16:34
 */
public class Cat {
    public void shout(){
        System.out.println("miao");
    }
}

com.imperfect.pojo.Dog

package com.imperfect.pojo;

/**
 * @author : Imperfect(lxm)
 * @Des:
 * @date : 2023/1/19  16:34
 */
public class Dog {

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

com.imperfect.pojo.Person

package com.imperfect.pojo;

/**
 * @author : Imperfect(lxm)
 * @Des:
 * @date : 2023/1/19  16:34
 */
public class Person {

    private Cat cat;
    private Dog dog;
    private String name;

    public Cat getCat() {
        return cat;
    }

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

    public Dog getDog() {
        return dog;
    }

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

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "Person{" +
                "cat=" + cat +
                ", dog=" + dog +
                ", name='" + name + '\'' +
                '}';
    }
}

src/main/resources/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="cat" class="com.imperfect.pojo.Cat"></bean>
    <bean id="dog" class="com.imperfect.pojo.Dog"></bean>
    <!--    会自动在容器上下文中查找,和自己set方法名字对应的bean-->
    <bean id="person" class="com.imperfect.pojo.Person" autowire="byName">
    <property name="name" value="imperfect"></property>
</bean>
</beans>

编写测试类

import com.imperfect.pojo.Person;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author : Imperfect(lxm)
 * @Des:
 * @date : 2023/1/19  16:38
 */
public class MyTest {
    @Test
    public void test1(){
        ApplicationContext context =new ClassPathXmlApplicationContext("beans.xml");
        Person person = (Person) context.getBean("person");
        person.getCat().shout();
        person.getDog().shout();
    }
}

执行结果如下:
在这里插入图片描述

九、使用注解开发

1、声明Bean的注解

在类上加上这些注解后,Spring启动后会自动初始化这些类,生成对应的实例对象
  @Controller:在展现层使用(MVC->SpringMVC)
  @Service:业务逻辑是服务层(service)使用
  @ Repository:数据访问层(dao)使用
  @Component:组件没有明确的角色 前面的四个实质上没有什么区别
注:在SpringMVC中@Controller被赋予了特殊的功能,不能倍其他的注解代替
  @Bean:注解声明当前的方法返回的是一个Bean,这个Bean的类型是对应的方法返回值类型,Bean的名称默认是方法名,也可以自定义:@Bean(name=“自定义名称”)

2、注入Bean的注解

在属性或setter方法上加上这些注解(@Resource、@Autowired),Spring会自动的按照Bean类型(type)或Bean名称(name)进行装配组合Bean
  @Resource:
  默认按 byName 自动注入,由J2EE提供。
   @Resource装配顺序  
   (1). 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常;  
  (2). 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常;  
  (3). 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常;  
   (4). 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;
  (5).@Resource的作用相当于@Autowired,只不过@Autowired按byType自动注入。
  @ Autowired:
  注解是按类型装配依赖对象,默认情况下它要求依赖对象必须存在,如果允许null值,可以设置它required属性为false。如果我们想使用按名称装配,可以结合@Qualifier注解(指定Bean的名称)一起使用。

3、初始化配置

@Configuration: 在类上加上这个注解,表明当前的类时个配置类,这个类中可能存在0个或多个@Bean
  @ComponentScan: 扫描包注解,这个注解会扫描指定的包下所有的加有@Controller;@Repository;@Component;@service注解的类,然后初始化成Bean

十、使用java的方式配置Spring

完全不适用Spring的xml,全权交给java来进行控制
首先我们先构建一下对应的环境
com.imperfect.config.MyConfig

package com.imperfect.config;

import com.imperfect.pojo.User;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author : Imperfect(lxm)
 * @Des:
 * @date : 2023/1/20  9:58
 */
@Configuration
public class MyConfig {

    @Bean
    public User getUser(){
        return new User();
    }
}

com.imperfect.pojo.User

package com.imperfect.pojo;

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

/**
 * @author : Imperfect(lxm)
 * @Des:
 * @date : 2023/1/20  9:57
 */
@Component
public class User {

    @Value("imperfect")
    private String name;
    private String address;

    public String getName() {
        return name;
    }

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

    public String getAddress() {
        return address;
    }

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

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

编写测试类

import com.imperfect.config.MyConfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @author : Imperfect(lxm)
 * @Des:
 * @date : 2023/1/20  10:11
 */
public class Test {
    public static void main(String[] args) {
        ApplicationContext context=new AnnotationConfigApplicationContext(MyConfig.class);
        Object getUser = context.getBean("getUser");
        System.out.println(getUser.toString());
    }
}

测试结果
在这里插入图片描述
@Configuraion代表这是一个配置类,就和我们之前看的beans.xml一样
这个也会被Spring容器托管,注册到容器中,因为它本来就是一个@Component

十一、静态代理

1、什么是静态代理?

  两个对象之间的操作不直接进行,通过第三方进行代理来实现。就比如说房客租房子这件事情,租房的两个对象是房客和房东,静态代理便是,在房客和房东之间多了一个角色,这便是中介,代理便是中介,现在租房这件事情便是房客和中介,以及中介和房东之间的事情,房客不直接和房东进行租房的操作。

2、编写代码

com/imperfect/demo01/Process.java

package com.imperfect.demo01;

/**
 * @author : Imperfect(lxm)
 * @Des:
 * @date : 2023/1/20  15:31
 */
public interface Process {
    public void charge ();
}

代理类:com/imperfect/demo01/Proxy.java

package com.imperfect.demo01;

/**
 * @author : Imperfect(lxm)
 * @Des:
 * @date : 2023/1/20  15:33
 */
public class Proxy implements Process {

    Customer customer;

    public void setCustomer(Customer customer){
        this.customer=customer;
    }

    public void charge() {
        customer.charge();
    }
}

被代理类:com/imperfect/demo01/Customer.java

package com.imperfect.demo01;

import org.springframework.context.annotation.Profile;

import java.lang.annotation.Annotation;

/**
 * @author : Imperfect(lxm)
 * @Des:
 * @date : 2023/1/20  15:32
 */
public class Customer implements Process {


    public void charge() {
        System.out.println("Customer1需要控诉");
    }
}

测试类:com/imperfect/demo01/Test.java

package com.imperfect.demo01;

/**
 * @author : Imperfect(lxm)
 * @Des:
 * @date : 2023/1/20  15:36
 */
public class Test {
    public static void main(String[] args) {
        Customer customer=new Customer();
        Proxy proxy=new Proxy();
        proxy.setCustomer(customer);
        proxy.charge();
    }
}

测试结果:
在这里插入图片描述

十二、动态代理

1、什么是动态代理?

  动态代理指的是:在程序的执行过程中,使用jdk的反射机制,创建代理对象,并动态的指定代理的目标类

动态代理的实现方式常用有两种:

  • 使用JDK代理
  • 通过CDLIB代理

jdk动态代理
jdk动态代理是基于Java的反射机制实现的,使用jdk反射包下的Proxy和InvocationHandler实现代理对象的动态创建

2、编写代码

com/imperfect/demo02/Process.java

package com.imperfect.demo02;

/**
 * @author : Imperfect(lxm)
 * @Des:
 * @date : 2023/1/20  15:48
 */
public interface Process {
     void charge();
}

动态代理类:com/imperfect/demo02/DynamicProxyHandler.java

package com.imperfect.demo02;


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

/**
 * @author : Imperfect(lxm)
 * @Des:
 * @date : 2023/1/20  15:49
 */
public class DynamicProxyHandler implements InvocationHandler {
    private Object object;

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

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        return method.invoke(object, args);

        //return method.invoke(object, method);
       // return result;
    }

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


}

被代理对象Customer1:com/imperfect/demo02/Customer1.java

package com.imperfect.demo02;

/**
 * @author : Imperfect(lxm)
 * @Des:
 * @date : 2023/1/20  15:48
 */
public class Customer1 implements Process {

    public void charge() {
        System.out.println("Customer1需要控诉");
    }
}

被代理对象Customer2:com/imperfect/demo02/Customer2.java

package com.imperfect.demo02;

/**
 * @author : Imperfect(lxm)
 * @Des:
 * @date : 2023/1/20  15:49
 */
public class Customer2 implements Process {
    public void charge() {
        System.out.println("Customer2需要控诉");
    }
}

测试类:com/imperfect/demo02/Test.java

package com.imperfect.demo02;

/**
 * @author : Imperfect(lxm)
 * @Des:
 * @date : 2023/1/20  15:52
 */
public class Test {
    public static void main(String[] args) {
        Customer1 customer1=new Customer1();
        DynamicProxyHandler dynamicProxyHandler=new DynamicProxyHandler();
        dynamicProxyHandler.setProxy(customer1);
        Process proxy = (Process)dynamicProxyHandler.getProxy();
        proxy.charge();
    }
}

十三、注解实现AOP

在创建AOP之前我们需要先导入一下相对应AOP的jar包

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

1、编写代码

我们首先自定义一个注解com/imperfect/Annotation/MethodDetail.java

package com.imperfect.Annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MethodDetail {
}

编写一个切面AOP
com/imperfect/Aop/MethodDetailAop.java

package com.imperfect.Aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class MethodDetailAop {
    @Around("@annotation(com.imperfect.Annotation.MethodDetail)")
    public void escapeAround(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("执行方法前");
        Object proceed = null;
        proceed = joinPoint.proceed(joinPoint.getArgs());
        System.out.println("执行方法后");

    }
}

编写一个需要被代理的接口com/imperfect/Service/UserService.java

package com.imperfect.Service;

import org.springframework.stereotype.Component;

@Component
public interface UserService {

    public void add();
    public void save();
    public void update();
}

编写一个具体的实现类
com/imperfect/Service/UserServiceImpl.java

package com.imperfect.Service;

import com.imperfect.Annotation.MethodDetail;
import org.springframework.stereotype.Component;

@Component()
public class UserServiceImpl implements UserService{
    @MethodDetail
    public void add() {
        System.out.println("执行添加方法");
    }

    public void save() {
        System.out.println("执行保存方法");

    }

    public void update() {
        System.out.println("执行修改方法");

    }
}

编写测试代码
Test.java

import com.imperfect.Service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
        UserService userServiceImpl = (UserService) context.getBean("userServiceImpl");
        userServiceImpl.add();

    }
}

测试结果:
在这里插入图片描述

十四、Spring整合MyBatis

首先我们需要先导入整合时所需要的jar包

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>Spring</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>spring-09-myBatis</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.4</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.2</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.10</version>
        </dependency>
    </dependencies>
</project>

编写pojo类:com/imperfect/pojo/User.java

package com.imperfect.pojo;

import jdk.nashorn.internal.objects.annotations.Constructor;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

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

com/imperfect/mapper/UserMapper.java

package com.imperfect.mapper;

import com.imperfect.pojo.User;

import java.util.List;


public interface UserMapper {

    public List<User> selectAll();

}

Mapper/UserMapper.xml

<?xml version="1.0" encoding="UTF8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.imperfect.mapper.UserMapper">


<select id="selectAll" resultType="com.imperfect.pojo.User">
    select * from user;
</select>

</mapper>

com/imperfect/mapper/UserMapperImpl.java

package com.imperfect.mapper;

import com.imperfect.pojo.User;
import org.mybatis.spring.SqlSessionTemplate;

import java.util.List;

public class UserMapperImpl implements UserMapper {

    private SqlSessionTemplate sqlSessionTemplate;

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

    public List<User> selectAll() {
        UserMapper mapper = sqlSessionTemplate.getMapper(UserMapper.class);
        return mapper.selectAll();
    }
}

applicationContext.xml

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

    <!--   使用Spring数据源来替换MyBatis-->
    <bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url"
                  value="jdbc:mysql://数据库地址以及数据库?userUnicode=true&amp;characterEncoding=utf8&amp;useSSL=false"/>
        <property name="username" value="账号"/>
        <property name="password" value="密码"/>
    </bean>

    <!--    sqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="datasource"/>
        <!--    绑定mybatis配置文件-->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
    </bean>
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg index="0" ref="sqlSessionFactory"/>
    </bean>
    <bean id="userMapper" class="com.imperfect.mapper.UserMapperImpl">
        <property name="sqlSessionTemplate" ref="sqlSession"/>
    </bean>
</beans>

mybatis-config.xml

<?xml version="1.0" encoding="UTF8"?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>

    <!--每一个mapper.xml都需要在mybatis配置文件中注册-->
    <mappers>
        <mapper resource="Mapper/UserMapper.xml"/>
    </mappers>
</configuration>

编写测试类
Test.java

import com.imperfect.mapper.UserMapper;
import com.imperfect.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.IOException;
import java.util.List;

public class Test {
    @org.junit.jupiter.api.Test
    public void Test() throws IOException {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserMapper userMapper = (UserMapper) context.getBean("userMapper");
        List<User> users = userMapper.selectAll();
        for (User user : users) {
            System.out.println(user.toString());
        }
    }
}

测试结果如下
在这里插入图片描述

十五、声明式事务

1、简介

Spring支持编程式事务管理和声明式事务管理两种方式。

  其中声明式注解是建立在AOP之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过基于@Transactional注解的方式),便可以将事务规则应用到业务逻辑中。

  显然声明式事务管理要优于编程式事务管理,这正是spring倡导的非侵入式的开发方式。声明式事务管理使业务代码不受污染,一个普通的POJO对象,只要加上注解就可以获得完全的事务支持。和编程式事务相比,声明式事务唯一不足地方是,后者的最细粒度只能作用到方法级别,无法做到像编程式事务那样可以作用到代码块级别。但是即便有这样的需求,也存在很多变通的方法,比如,可以将需要进行事务管理的代码块独立为方法等等。

  声明式事务管理也有两种常用的方式,一种是基于tx和aop名字空间的xml配置文件,另一种就是基于@Transactional注解。显然基于注解的方式更简单易用,更清爽。

2、编写代码

首先我们在Spring的application.xml配置文件中配置一下声明式事务,并且打开通过注解的方式控制事务。

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

    <!--    使用注解来进行驱动-->
    <tx:annotation-driven/>

编写对应的mapper.xml

<insert id="insert" parameterType="com.imperfect.pojo.User">
        insert into user values(#{id},#{password},#{name})
    </insert>

    <delete id="delete" parameterType="int">
        deletes from user where id={#id}
    </delete>

其中的delete语句为错误的语句,我们特意地去造成SQL的错误,从而导致程序出错,看一下事务会不会提交。
编写对应的业务代码

@Transactional
public List<User> selectAll() {
    User user = new User("5", "im", "love");
    insert(user);
    delete(4);
    return sqlSessionTemplate.getMapper(UserMapper.class).selectAll();
}

执行结果如下:
在这里插入图片描述
在这里插入图片描述
代码出现报错,并且第一个新增用户的业务操作也没有提交,保证了事务的ACID原则。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值