Spring

Spring5

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

Spring是一个轻量级的控制反转(IOC)和面向切面编程(AOP)的框架

IOC理论推导

传统方式:

  1. UserDao接口
package com.sgl.dao;

public interface UserDao {
    void getUser();
}
  1. UserDaoImpl、UserMysqlImpl、UserOracleImpl实现类
package com.sgl.dao;

public class UserDaoImpl implements UserDao{
    @Override
    public void getUser() {
        System.out.println("默认获取用户数据");
    }
}
package com.sgl.dao;

public class UserMysqlImpl implements UserDao{
    @Override
    public void getUser() {
        System.out.println("Mysql获取用户数据");
    }
}
package com.sgl.dao;

public class UserOracleImpl implements UserDao{
    @Override
    public void getUser() {
        System.out.println("Oracle获取用户数据");
    }
}
  1. UserService业务接口
package com.sgl.service;

public interface UserService {
    void getUser();
}
  1. UserServiceImpl业务实现
package com.sgl.service;

import com.sgl.dao.UserDao;
import com.sgl.dao.UserDaoImpl;
import com.sgl.dao.UserMysqlImpl;
import com.sgl.dao.UserOracleImpl;

public class UserServiceImpl implements UserService{

    //只能一个一个实现
    private UserDao userDao = new UserDaoImpl();
    //private UserDao userDao = new UserMysqlImpl();
    //private UserDao userDao = new UserOracleImpl();

    @Override
    public void getUser() {
        userDao.getUser();

    }
}

测试:

import com.sgl.service.UserService;
import com.sgl.service.UserServiceImpl;

public class MyTest {
    public static void main(String[] args) {
        //用户实际调用的是业务层,dao层不需要解除
        UserService userService = new UserServiceImpl();

        userService.getUser();
    }
}
/*
结果:
	默认获取用户数据  UserServiceImpl业务对应的是 private UserDao userDao = new UserDaoImpl();
	Mysql获取用户数据  UserServiceImpl业务对应的是 private UserDao userDao = new UserMysqlImpl();
	Oracle获取用户数据  UserServiceImpl业务对应的是 private UserDao userDao = new UserOracleImpl();
*/

IOC理论原型:

利用set进行动态实现的注入 修改UserServiceImpl如下:

  1. UserServiceImpl业务实现
package com.sgl.service;

import com.sgl.dao.UserDao;

public class UserServiceImpl implements UserService{

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

    @Override
    public void getUser() {
        userDao.getUser();

    }
}

测试:

import com.sgl.dao.UserDaoImpl;
import com.sgl.dao.UserMysqlImpl;
import com.sgl.dao.UserOracleImpl;
import com.sgl.service.UserService;
import com.sgl.service.UserServiceImpl;

public class MyTest {
    public static void main(String[] args) {
        //用户实际调用的是业务层,dao层不需要解除
        UserService userService = new UserServiceImpl();

        ((UserServiceImpl) userService).setUserDao(new UserDaoImpl());
        //((UserServiceImpl) userService).setUserDao(new UserMysqlImpl());
        //((UserServiceImpl) userService).setUserDao(new UserOracleImpl());

        userService.getUser();
    }
}

结果:

/*
结果:
	默认获取用户数据 ---> ((UserServiceImpl) userService).setUserDao(new UserDaoImpl());
	Mysql获取用户数据 ---> ((UserServiceImpl) userService).setUserDao(new UserMysqlImpl());
	Oracle获取用户数据 ---> ((UserServiceImpl) userService).setUserDao(new UserOracleImpl());
*/

小结:

  • 传统方式:程序是主动创建对象,控制权在程序员!!
  • IOC理论原型(set注入后):程序员不在具有主动性,变成了被动接受对象
  • ((UserServiceImpl) userService).setUserDao(new UserDaoImpl()) 为什么要强转?—> 因为实现的接口没有set方法实现类独有的方法

IOC

控制反转IOC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IOC的一种方法

  1. 实体类
package com.sgl.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 + '\'' +
                '}';
    }
}
  1. 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">

    <!--使用Spring来创建对象,在Spring这些都称为Bean
    类型 变量名 = new 类型();
    Hello hello = new Hello();

    id = 变量名
    class = new 的对象
    property 相当于给对象中的属性设置一个值
    -->
    <bean id="hello" class="com.sgl.pojo.Hello">
        <property name="str" value="Spring"/>
    </bean>

</beans>

测试:

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

public class MyTest {
    public static void main(String[] args) {
        //获取Spring的上下文对象
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

        //现在对象都在Spring中管理,直接取出即可
        Hello hello = (Hello) context.getBean("hello");
        System.out.println(hello.toString());
    }
}

/*
 结果: Hello{str='Spring'}
*/

User案例再改进:

  1. UserDao接口
package com.sgl.dao;

public interface UserDao {
    void getUser();
}
  1. UserDaoImpl、UserMysqlImpl、UserOracleImpl实现类
package com.sgl.dao;

public class UserDaoImpl implements UserDao{
    @Override
    public void getUser() {
        System.out.println("默认获取用户数据");
    }
}
package com.sgl.dao;

public class UserMysqlImpl implements UserDao{
    @Override
    public void getUser() {
        System.out.println("Mysql获取用户数据");
    }
}
package com.sgl.dao;

public class UserOracleImpl implements UserDao{
    @Override
    public void getUser() {
        System.out.println("Oracle获取用户数据");
    }
}
  1. UserService业务接口
package com.sgl.service;

public interface UserService {
    void getUser();
}
  1. UserServiceImpl业务实现
package com.sgl.service;

import com.sgl.dao.UserDao;

public class UserServiceImpl implements UserService{

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

    @Override
    public void getUser() {
        userDao.getUser();

    }
}
  1. 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="userDaoImpl" class="com.sgl.dao.UserDaoImpl"/>
    <bean id="mysqlImpl" class="com.sgl.dao.UserMysqlImpl"/>
    <bean id="oracleImpl" class="com.sgl.dao.UserOracleImpl"/>

    <bean id="userServiceImpl" class="com.sgl.service.UserServiceImpl">
        <property name="userDao" ref="userDaoImpl"/>
    </bean>
    <!--
        ref:引用Spring容器中创建好的对象
        value:具体的值,基本数据类型
    -->

</beans>

测试:

import com.sgl.service.UserServiceImpl;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {

    @Test
    public void Test(){
        //获取ApplicationContext:拿到Spring容器
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

        UserServiceImpl userService = (UserServiceImpl) context.getBean("userServiceImpl");

        userService.getUser();
    }
}

结果:

/*
结果:
	默认获取用户数据 ---> <bean id="userService" class="com.sgl.service.UserServiceImpl">
                            <property name="userDao" ref="userDaoImpl"/>
                        </bean>
                        
	Mysql获取用户数据 ---> <bean id="userService" class="com.sgl.service.UserServiceImpl">
                                <property name="userDao" ref="mysqlImpl"/>
                            </bean>
	Oracle获取用户数据 ---> <bean id="userService" class="com.sgl.service.UserServiceImpl">
                                <property name="userDao" ref="oracleImpl"/>
                            </bean>
*/

控制反转:

  • 反转:程序本身不创建对象,而变成被动的接收对象
  • 依赖注入:就是利用set方法来进行注入
  • IOC是一种编程思想,由主动的编程编程被动的接收
  • 可以通过newClassPathXmlApplicationContext去浏览以下底层代码

要实现不同的操作,只需要在xml配置文件中进行修改,所谓的IOC:对象由Spring创建,管理,装配

IOC创建对象的方式

实体类:

package com.sgl.pojo;

public class User {
    private String name;

   // public User() {
   //     System.out.println("User的无参构造");
   // }

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

    public String getName() {
        return name;
    }

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

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

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="user" class="com.sgl.pojo.User">
        <property name="name" value="刚龙"/>
    </bean>
</beans>

测试:

import com.sgl.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

        User user = (User) context.getBean("user");
        user.show();
    }
}
  1. 使用无参构造创建对象,默认

  2. 使用有参构造创建对象:

    • 下标赋值
    <!--第一种:下标赋值-->
    <bean id="user" class="com.sgl.pojo.User">
        <constructor-arg index="0" value="狂神"/>
    </bean>
    
    • 类型创建
    <!--第二种:通过类型创建(不建议使用)-->
    <bean id="user" class="com.sgl.pojo.User">
        <constructor-arg type="java.lang.String" value="倩倩"/>
    </bean>
    
    • 直接通过参数名
    <!--第三种:直接通过参数名来设置-->
    <bean id="user" class="com.sgl.pojo.User">
        <constructor-arg name="name" value="老憨"/>
    </bean>
    

总结:在配置文件加载的时候,容器中管理的对象就已经实例化了

Spring配置说明

实体类是上面的User

别名alias

<alias name="user" alias="helloUser"/>

测试:

import com.sgl.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

        //可以用user可以用helloUser
        User user = (User) context.getBean("helloUser");
        user.show();
    }

}

Bean的配置

实体类Teacher

package com.sgl.pojo;

public class Teacher {
    private String name;

    public Teacher() {
        System.out.println("Teacher的无参构造");
    }


    public String getName() {
        return name;
    }

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

    public void show(){
        System.out.println("name="+name);
    }
}
<!--
     id:bean 的唯一标识符,相当于我们学习的对象名
     class: bean 对象所对应的全限定名  包名+类型
     name: 也是别名,并且name可以取多个别名,可以用不同的分隔符
-->
<bean id="teacher" class="com.sgl.pojo.Teacher" name="t1 t2,t3;t4">
    <property name="name" value="秦疆"/>
</bean>

测试:

import com.sgl.pojo.Teacher;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
		
        //teacher可以换成t1/t2/t3/t4
        Teacher teacher = (Teacher) context.getBean("teacher");
        teacher.show();
    }
    
}
/*结果:
	Teacher的无参构造
	name=秦疆
*/

import

一般用于团队的开发使用,它可以将多个配置文件导入合并为一个,如:

​ 项目有多人开发,这三个复制不同的类开发,不同的类需要注册在不同的bean中,我们可以利用import将所有人的beans.xml合并为一个总的

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

    <import resource="beans.xml"/>
    <import resource="beans2.xml"/>
    <import resource="beans3.xml"/>

</beans>

使用的时候直接使用总的配置就可

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

依赖注入

构造器注入

IOC创建对象的方式已讲解

Set方式注入 ***

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

环境搭建

  1. 复杂类型Address
package com.sgl.pojo;

public class Address {
    private String address;

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}
  1. 真实测试对象Student
package com.sgl.pojo;

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

public class Student {

    private String name;
    private Address address;   //复杂类型
    private String[] books;
    private List<String> hobbies;
    private Map<String,String> card;
    private Set<String> games;
    private String girlfriend;
    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> getHobbies() {
        return hobbies;
    }

    public void setHobbies(List<String> hobbies) {
        this.hobbies = hobbies;
    }

    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 getGirlfriend() {
        return girlfriend;
    }

    public void setGirlfriend(String girlfriend) {
        this.girlfriend = girlfriend;
    }

    public Properties getInfo() {
        return info;
    }

    public void setInfo(Properties info) {
        this.info = info;
    }
    @Override
    public String toString() {
        return "Student{ \n " +
                "name='" + name + '\'' +
                ", \n address=" + address.toString() +
                ", \n books=" + Arrays.toString(books) +
                ", \n hobbies=" + hobbies +
                ", \n card=" + card +
                ", \n games=" + games +
                ", \n girlfriend='" + girlfriend + '\'' +
                ", \n info=" + info + "\n" +
                '}';
    }
}

  1. 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">

   <!--第一种:普通值注入,value-->
   <bean id="student" class="com.sgl.pojo.Student">
       <property name="name" value="狂神"/>
   </bean>
</beans>

测试:

import com.sgl.pojo.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

        Student student = (Student) context.getBean("student");

        System.out.println(student.getName());
    }

}

完善注入信息

<?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.sgl.pojo.Address">
        <property name="address" value="河南"/>
    </bean>

   <bean id="student" class="com.sgl.pojo.Student">
       <!--第一种:普通值注入,value-->
       <property name="name" value="狂神"/>

       <!--第二种:Bean注入,ref-->
       <property name="address" ref="address"/>

       <!--数组-->
       <property name="books">
           <array>
               <value>红楼梦</value>
               <value>西游记</value>
               <value>三国演义</value>
               <value>水浒传</value>
           </array>
       </property>

       <!--List-->
       <property name="hobbies">
           <list>
               <value>听歌</value>
               <value>打游戏</value>
               <value>散步</value>
           </list>
       </property>

       <!--Map-->
       <property name="card">
           <map>
               <entry key="身份证" value="4115262000xxxxxx"/>
               <entry key="银行卡" value="1516551656515616"/>
           </map>
       </property>

       <!--Set-->
       <property name="games">
           <set>
               <value>LOL</value>
               <value>CF</value>
               <value>CSGO</value>
           </set>
       </property>

       <!--null-->
       <property name="girlfriend">
           <null></null>
       </property>

       <!--Properties-->
       <property name="info">
           <props>
               <prop key="driver">com.mysql.jdbc.Driver</prop>
               <prop key="url">jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=ture&amp;characterEncoding=UTF-8</prop>
               <prop key="username">root</prop>
               <prop key="password">123456</prop>
           </props>
       </property>

    </bean>
</beans>

测试:

import com.sgl.pojo.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

        Student student = (Student) context.getBean("student");

        System.out.println(student.toString());
    }

}

结果:

/*
Student{ 
 name='狂神', 
 address=Address{address='河南'}, 
 books=[红楼梦, 西游记, 三国演义, 水浒传], 
 hobbies=[听歌, 打游戏, 散步], 
 card={身份证=4115262000xxxxxx, 银行卡=1516551656515616}, 
 games=[LOL, CF, CSGO], 
 girlfriend='null', 
 info={password=123456, url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=ture&characterEncoding=UTF-8, driver=com.mysql.jdbc.Driver, username=root}
}
*/

拓展方式注入

使用p命令空间和c命令空间进行注入

  1. 实体类
package com.sgl.pojo;

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

    public User() {
    }

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

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

  1. userbeans.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"
       
       //使用p、c要加入以下两行内容
       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="user" class="com.sgl.pojo.User" p:age="22" p:name="刚龙"/>

    <bean id="user2" class="com.sgl.pojo.User" c:age="24" c:name="倩倩"/>


</beans>
  1. 测试
@Test
public void test(){
    ApplicationContext context = new ClassPathXmlApplicationContext("userbeans.xml");

    //在其后加上User.class就不需要强转了
    User user = context.getBean("user", User.class);

    System.out.println(user.toString());
}

注意点:

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

<!--p命名空间注入,可以直接注入属性的值:property-->
xmlns:p="http://www.springframework.org/schema/p"
<!--c命名空间注入,通过构造器注入:construct-args-->
xmlns:c="http://www.springframework.org/schema/c"

Bean的作用域

作用域描述
singleton(默认)将每个 Spring IoC 容器的单个 bean 定义范围限定为单个对象实例。
prototype将单个 bean 定义的作用域限定为任意数量的对象实例。
request将单个 bean 定义的范围限定为单个 HTTP 请求的生命周期。也就是说,每个 HTTP 请求都有一个在单个 bean 定义后面创建的 bean 实例。仅在可感知网络的 Spring ApplicationContext中有效。
session将单个 bean 定义的范围限定为 HTTP Session的生命周期。仅在可感知网络的 Spring ApplicationContext上下文中有效。
application将单个 bean 定义的范围限定为ServletContext的生命周期。仅在可感知网络的 Spring ApplicationContext上下文中有效。
websocket将单个 bean 定义的范围限定为WebSocket的生命周期。仅在可感知网络的 Spring ApplicationContext上下文中有效。
  1. 单例模式(Spring默认机制)
<bean id="user" class="com.sgl.pojo.User" c:age="24" c:name="倩倩" 
scope="singleton"/>
  1. 原型模式:每次从容器中get的时候,都会产生一个新对象
<bean id="user" class="com.sgl.pojo.User" p:age="22" p:name="刚龙" scope="prototype"/>

测试:

    @Test
    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("userbeans.xml");

        User user = context.getBean("user", User.class);
        User user1 = context.getBean("user", User.class);

        System.out.println(user.hashCode());
        System.out.println(user1.hashCode());

        System.out.println(user==user1);
    }
/*单例模式结果:
	1561408618
    1561408618
    true
*/
/*原型模式结果:
    2050404090
    388043093
    false
*/
  1. request、session、application、websocket只能在Web开发中使用到

Bean的自动装配

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

Spring有三种装配方式:

  1. 在xml中显示的装配
  2. 在java中显示装配
  3. 隐式的自动装配bean ***

xml中显示的装配

  1. 实体类
package com.sgl.pojo;

public class Cat {
    public void shout(){
        System.out.println("喵喵~~~~~");
    }
}
package com.sgl.pojo;

public class Dog {
    public void shout(){
        System.out.println("汪汪~~~~~");
    }
}

package com.sgl.pojo;

public class People {
    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 "People{" +
                "cat=" + cat +
                ", dog=" + dog +
                ", name='" + name + '\'' +
                '}';
    }
}

  1. 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.sgl.pojo.Cat"/>
    <bean id="dog" class="com.sgl.pojo.Dog"/>
    <bean id="people" class="com.sgl.pojo.People">
        <property name="cat" ref="cat"/>
        <property name="dog" ref="dog"/>
        <property name="name" value="刚龙"/>
    </bean>
</beans>

测试:

import com.sgl.pojo.People;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        People people = context.getBean("people", People.class);

        people.getDog().shout();
        people.getCat().shout();
    }
}
/*结果:
	汪汪~~~~~
	喵喵~~~~~
*/

隐式的自动装配bean ***

byName自动装配

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.sgl.pojo.Cat"/>
    <bean id="dog" class="com.sgl.pojo.Dog"/>
    <!--byName:会自动在容器上下文中查找,和自己对象set方法后面的值对应 bean id-->
    <bean id="people" class="com.sgl.pojo.People" autowire="byName">
    	<property name="name" value="刚龙"/>
    </bean>
</beans>

测试:

import com.sgl.pojo.People;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        People people = context.getBean("people", People.class);

        people.getDog().shout();
        people.getCat().shout();
    }
}
/*结果:
	汪汪~~~~~
	喵喵~~~~~
*/
byType自动装配
<?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 class="com.sgl.pojo.Cat"/>
    <bean class="com.sgl.pojo.Dog"/>
    <!--byType:会自动在容器上下文中查找,和自己对象的属性类型相同的bean-->
    <bean id="people" class="com.sgl.pojo.People" autowire="byType">
    <property name="name" value="刚龙"/>
    </bean>
</beans>

测试:

import com.sgl.pojo.Cat;
import com.sgl.pojo.Dog;
import com.sgl.pojo.People;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        People people = context.getBean("people", People.class);

        Dog dog = people.getDog();
        Cat cat = people.getCat();
        dog.shout();
        cat.shout();
    }
}
/*结果:
	汪汪~~~~~
	喵喵~~~~~
*/

小结:

  • byName:需要保证所有的bean的id唯一,并且这个bean需要和自动注入的属性的set方法的值一致
  • byType:需要保证所有的bean的class唯一,并且这个bean需要和自动注入的属性一致
  • byName就是通过Bean的id或者name,byType就是按Bean的Class的类型

注解实现自动装配

  1. 导入约束(context约束)
xmlns:context="http://www.springframework.org/schema/context"
  1. 配置注解的支持:context:annotation-config/ ***
<?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:annotation-config/>

</beans>
@Autowired注解

直接在属性上使用即可!也可以在set方式上使用!

使用**@Autowired可以不用编写set方法,前提是这个自动装配的属性在IOC(Spring)容器中存在,且符合名字byType**

测试:

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"
       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">

    <context:annotation-config/>

    <bean id="cat" class="com.sgl.pojo.Cat"/>
    <bean id="dog" class="com.sgl.pojo.Dog"/>
    <bean id="people" class="com.sgl.pojo.People"/>

</beans>

实体类(方式一):

package com.sgl.pojo;

import org.springframework.beans.factory.annotation.Autowired;

public class People {

    @Autowired
    private Cat cat;
    @Autowired
    private Dog dog;
    private String name;
}

实体类(方式二):

如果@Autowired自动装配比较复杂,自动装配无法通过一个注解 @Autowired 完成时,可以使用**@Qualifier(value=“xxx”)去配和@Autowired的使用,指定一个唯一的bean对象注入,如beans.xml**

<bean id="cat22" class="com.sgl.pojo.Cat"/>
<bean id="cat11" class="com.sgl.pojo.Cat"/>
<bean id="dog22" class="com.sgl.pojo.Dog"/>
<bean id="dog11" class="com.sgl.pojo.Dog"/>
<bean id="people" class="com.sgl.pojo.People"/>

如果不配合@Qualifier使用会报错(因为没有cat只有cat11和cat22

package com.sgl.pojo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

public class People {

    @Autowired
    @Qualifier(value = "cat11")
    private Cat cat;
    @Autowired
    @Qualifier(value = "dog11")
    private Dog dog;
}
@Resource注解

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"
       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">

    <context:annotation-config/>

    <bean id="cat" class="com.sgl.pojo.Cat"/>
    <bean id="dog" class="com.sgl.pojo.Dog"/>
    <bean id="people" class="com.sgl.pojo.People"/>

</beans>

实体类(方式一):

package com.sgl.pojo;

import org.springframework.beans.factory.annotation.Autowired;

public class People {

    @Resource
    private Cat cat;
    @Resource
    private Dog dog;
    private String name;
}

实体类(方式二):

<bean id="cat22" class="com.sgl.pojo.Cat"/>
<bean id="cat11" class="com.sgl.pojo.Cat"/>
<bean id="dog22" class="com.sgl.pojo.Dog"/>
<bean id="dog11" class="com.sgl.pojo.Dog"/>
<bean id="people" class="com.sgl.pojo.People"/>

如果不给@Resource加参数name=“xxx”,就会报错(No qualifying bean of type ‘com.sgl.pojo.Cat’ available: expected single matching bean but found 2: cat22,cat11)

package com.sgl.pojo;

import javax.annotation.Resource;

public class People {

    @Resource(name = "cat11")
    private Cat cat;
    @Resource(name = "dog11")
    private Dog dog;

    private String name;
}

测试:(都可以成功)

import com.sgl.pojo.Cat;
import com.sgl.pojo.Dog;
import com.sgl.pojo.People;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        People people = context.getBean("people", People.class);

        Dog dog = people.getDog();
        Cat cat = people.getCat();
        dog.shout();
        cat.shout();
    }
}

小结:

@Autowired 和@Resource的区别:

  • @Autowired 通过byType的方式实现,而且必须要求这个对象存在***

  • @Resource 通过**byName的方式实现,如果找不到名字,则可以通过byType实现!**如果两个都找不到的情况,直接报错

  • 执行顺序不同:@Autowired通过byType的方式实现,@Resource通过byName的方式实现

Spring注解开发

需要保证aop的包导入

在这里插入图片描述

需要导入context约束,增加注解的支持

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">

    <context:annotation-config/>

</beans>

@Component

  • bean

  • 属性如何注入

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">
	<context:annotation-config/>
    
    <!--指定扫描的包。这个包下的注解就会生效-->
    <context:component-scan base-package="com.sgl.pojo"/>

</beans>
package com.sgl.pojo;

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

//@Component:组件,放在类上,说明这个类被spring管理了,就是bean!
//@Component 等价于  <bean id="user" class="com.sgl.pojo.User"/>
@Component
public class User {

    //@Value("刚龙") 相当于 <property name="name" value="刚龙"/>
    @Value("刚龙")
    public String name;

    //@Value("刚龙")
    public void setName(String name) {
        this.name = name;
    }
}
  • 衍生的注解

@Component的衍生注解,在Web开发中,会按照mvc三层架构分层

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

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

修改applicationContext.xml

<!--指定扫描的包。这个包下的注解就会生效-->
<context:component-scan base-package="com.sgl"/>

在这里插入图片描述

  • 自动装配
@Autowired
@Resource
@Nullable  字段被标记这个注解,说明这个字段可以为null
@Resource
  • 作用域
@Scope("singleton") 单例模式
@Scope("prototype") 原型模式
package com.sgl.pojo;

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

//@Component:组件,放在类上,说明这个类被spring管理了,就是bean!
//@Component 等价于  <bean id="user" class="com.sgl.pojo.User"/>
@Component

//@Scope("singleton") 单例   @Scope("prototype") 原型
@Scope("prototype")
public class User {

    //@Value("刚龙") 相当于 <property name="name" value="刚龙"/>
    @Value("刚龙")
    public String name;

    //@Value("刚龙")
    public void setName(String name) {
        this.name = name;
    }
}

小结:

xml与注解:

  • xml更加万能,适合于任何场所,维护比较简单
  • 注解 不是自己的类使用不了,维护更佳复杂

一般xml用来管理Bean,注解负责完成属性的注入

注意:

  • 必须让注解生效,需要开启注解的支持

Java配置Spring

多看注释

实体类

package com.sgl.pojo;

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

//@Component:组件,放在类上,说明这个类被spring管理了,就是bean!
//@Component 等价于  <bean id="user" class="com.sgl.pojo.User"/>
@Component
public class User {

    private String name;

    public String getName() {
        return name;
    }

    //@Value("刚龙") 相当于 <property name="name" value="刚龙"/>
    @Value("刚龙")
    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }
}
package com.sgl.config;

import org.springframework.context.annotation.Configuration;

@Configuration
public class SglConfig2 {
}

配置文件

package com.sgl.config;

import com.sgl.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容器托管,注册到容器中,本身就是一个@Configuration
//@Configuration 代表这是一个配置类,相当于beans.xml一样
@Configuration
@ComponentScan("com.sgl.pojo")

@Import(SglConfig2.class)   //引用
public class SglConfig {


    //注册一个bean,相当于我们之前写的一个bean标签
    //这个方法的名字,相当于bean标签中的id属性
    //这个方法的返回值,相当于bean标签中的class属性
    @Bean
    public User getUser() {
        return new User();
    }

    // @Bean
    // public User user() {
    //     return new User();
    // }
}

@Import(SglConfig2.class) //引用

package com.sgl.config;

import org.springframework.context.annotation.Configuration;

@Configuration
public class SglConfig2 {
}

测试:

import com.sgl.config.SglConfig;
import com.sgl.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class MyTest {
    public static void main(String[] args) {
        //使用配置类方式,只能通过AnnotationConfigApplicationContext 上下文获取容器,通过配置类的class对象加载
        ApplicationContext context = new AnnotationConfigApplicationContext(SglConfig.class);

        User user = context.getBean("getUser", User.class);
        //User user = context.getBean("user", User.class);
        System.out.println(user.getName());
    }
}

代理模式

静态代理模式

角色分析:

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

案例一:

代码步骤:

  1. 接口
package com.sgl.demo;

//租房
public interface Rent {
    public void rent();
}
  1. 真实角色
package com.sgl.demo;

public class Host implements Rent{
    @Override
    public void rent() {
        System.out.println("房东出租房子");
    }
}
  1. 代理角色
package com.sgl.demo;

public class Proxy implements Rent{

    private Host host;

    public Proxy() {
    }

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

    @Override
    public void rent() {
        seeHouse();
        host.rent();
        contract();
        fare();
    }

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

    //签合同
    public void contract(){
        System.out.println("前租赁合同");
    }

    //收中介费
    public void fare(){
        System.out.println("收中介费");
    }
}
  1. 客户端访问代理角色
package com.sgl.demo;

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

再理解,案例二:

  1. 接口
package com.sgl.demo02;

//接口
public interface UserService {
    void add();
    void delete();
    void update();
    void query();
}
  1. 真实角色
package com.sgl.demo02;

//真实角色
public class UserServiceImpl implements UserService{
    @Override
    public void add() {
        System.out.println("增加一个用户");
    }

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

    @Override
    public void update() {
        System.out.println("修改一个用户");
    }

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

  1. 代理角色
package com.sgl.demo02;

//代理角色
public class UserServiceProxy implements UserService{

    private UserServiceImpl userService;

    public void setUserService(UserServiceImpl userService) {
        this.userService = userService;
    }

    @Override
    public void add() {
        log("add");
        userService.add();
    }

    @Override
    public void delete() {
        log("delete");
        userService.delete();
    }

    @Override
    public void update() {
        log("update");
        userService.update();
    }

    @Override
    public void query() {
        log("query");
        userService.query();
    }

    //日志方法
    public void log(String msg){
        System.out.println("[debug] 使用了"+msg+"方法");
    }


}
  1. 客户端访问代理角色
package com.sgl.demo02;

//客户端访问代理角色
public class Client {
    public static void main(String[] args) {
        UserServiceImpl userService = new UserServiceImpl();

        UserServiceProxy proxy = new UserServiceProxy();
        proxy.setUserService(userService);
        proxy.add();
    }
}

动态代理模式

动态代理分为两大类:基于接口的动态代理,基于类的动态代理

  • 基于接口:JDK动态代理
  • 基于类:cglib
  • Java字节码实现:javasist

了解两个类:Proxy:代理 InvocationHandler:调用处理程序

代理:

package com.sgl.demo03;

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

//用这个类,自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler {


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

    public void setRent(Rent rent) {
        this.rent = rent;
    }

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


    //处理代理实例,并返回结果
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //动态代理的本质,就是使用反射机制
        seeHouse();
        Object invoke = method.invoke(rent, args);
        fare();
        return invoke;
    }

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

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

客户端:

package com.sgl.demo03;

public class Client {
    public static void main(String[] args) {
        //真实角色
        Host host = new Host();

        //代理角色:现在没有
        ProxyInvocationHandler pih = new ProxyInvocationHandler();

        //通过调用程序处理角色来处理我们调用的接口对象
        pih.setRent(host);

        Rent proxy = (Rent) pih.getProxy();

        proxy.rent();
    }
}

代理:

package com.sgl.demo04;

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

//用这个类,自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler {


    //被代理的接口
    private Object target;

    public void setTarget(Object target) {
        this.target = target;
    }

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


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

        log(method.getName());
        //动态代理的本质,就是使用反射机制
        Object invoke = method.invoke(target, args);
        return invoke;
    }

    public void log(String msg){
        System.out.println("执行了"+msg+"方法");
    }

}

客户端:

package com.sgl.demo04;

import com.sgl.demo02.UserService;
import com.sgl.demo02.UserServiceImpl;

public class Client {
    public static void main(String[] args) {
        //真实角色
        UserServiceImpl userService = new UserServiceImpl();

        //代理角色:不存在
        ProxyInvocationHandler pih = new ProxyInvocationHandler();

        //设置要代理的对象
        pih.setTarget(userService);

        //动态生成代理类
        UserService proxy = (UserService) pih.getProxy();

        proxy.add();

    }
}

AOP(面向切面编程)

AOP在Spring中的作用

提供声明事务;允许用户自定义切面

  • 横切关注点:跨越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点。如日志 , 安全 , 缓存 , 事务等等 …
  • 切面(ASPECT):横切关注点 被模块化 的特殊对象。即,它是一个类。
  • 通知(Advice):切面必须要完成的工作。即,它是类中的一个方法。
  • 目标(Target):被通知对象。
  • 代理(Proxy):向目标对象应用通知之后创建的对象。
  • 切入点(PointCut):切面通知 执行的 “地点”的定义。
  • 连接点(JointPoint):与切入点匹配的执行点。

Spring AOP 默认为 AOP 代理使用标准的 JDK 动态代理。这允许代理任何接口(或接口集)

Spring实现AOP

使用AOP织入,需要导入一个依赖包

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.7</version>
</dependency>
方式一:使用原生Spring API接口

UserSevice

package com.sgl.service;

public interface UserService {
    void add();
    void delete();
    void update();
    void select();
}

UserServiceImpl

package com.sgl.service;

public class UserServiceImpl implements UserService{
    @Override
    public void add() {
        System.out.println("增加一个用户");
    }

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

    @Override
    public void update() {
        System.out.println("修改一个用户");
    }

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

Log

package com.sgl.log;

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

public class Log implements MethodBeforeAdvice {

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

AfterLog

package com.sgl.log;

import org.springframework.aop.AfterReturningAdvice;

import java.lang.reflect.Method;

public class AfterLog implements AfterReturningAdvice {
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("执行了"+method.getName()+"方法,返回结果为"+returnValue);
    }
}

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

    <!--方式一:使用原生Spring API接口-->
    <!--配置aop:需要导入aop依赖-->
    <aop:config>
        <!--切入点:expression:表达式,execution(要执行的位置! * * * * * *)-->
        <aop:pointcut id="pointcut" expression="execution(* com.sgl.service.UserServiceImpl.*(..))"/>

        <!--执行环绕增加!-->
        <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
    </aop:config>
    
</beans>

测试:

import com.sgl.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 = context.getBean("userService", UserService.class);

        userService.delete();
    }
}

结果:

执行了com.sgl.service.UserServiceImpl的delete方法
删除一个用户
执行了delete方法,返回结果为null
方式二:自定义实现AOP【主要是切面定义】

UserSevice

package com.sgl.service;

public interface UserService {
    void add();
    void delete();
    void  update();
    void select();
}

UserServiceImpl

package com.sgl.service;

public class UserServiceImpl implements UserService{
    @Override
    public void add() {
        System.out.println("增加一个用户");
    }

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

    @Override
    public void update() {
        System.out.println("修改一个用户");
    }

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

DiyPointCut

package com.sgl.diy;

public class DiyPointCut {
    public void before(){
        System.out.println("========执行前=========");
    }

    public void after(){
        System.out.println("========执行后=========");
    }
}

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

    <!--方式二:自定义类-->
    <bean id="diy" class="com.sgl.diy.DiyPointCut"/>
    <aop:config>
        <!--自定义切面,ref:要引用的类-->
        <aop:aspect ref="diy">
            <!--切入点-->
            <aop:pointcut id="point" expression="execution(* com.sgl.service.UserServiceImpl.*(..))"/>
            <!--通知-->
            <aop:before method="before" pointcut-ref="point"/>
            <aop:after method="after" pointcut-ref="point"/>
        </aop:aspect>
    </aop:config>

</beans>

测试:

import com.sgl.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 = context.getBean("userService", UserService.class);

        userService.delete();
    }
}

结果:

========执行前=========
删除一个用户
========执行后=========
方式三:使用注解实现AOP

UserSevice

package com.sgl.service;

public interface UserService {
    void add();
    void delete();
    void  update();
    void select();
}

UserServiceImpl

package com.sgl.service;

public class UserServiceImpl implements UserService{
    @Override
    public void add() {
        System.out.println("增加一个用户");
    }

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

    @Override
    public void update() {
        System.out.println("修改一个用户");
    }

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

AnnotationPointCut

package com.sgl.diy;

//方式三:使用注解实现AOP

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;

@Aspect  //标注这个类是一个切面
public class AnnotationPointCut {

    @Before("execution(* com.sgl.service.UserServiceImpl.*(..))")
    public void before(){
        System.out.println("=========方法执行前========");
    }

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

    //在环绕中增强,给定一个参数,代表我们要处理切入的点
    @Around("execution(* com.sgl.service.UserServiceImpl.*(..))")
    public void around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("环绕前");
        //获得签名
        System.out.println("signature:"+joinPoint.getSignature());

        //执行方法
        Object proceed = joinPoint.proceed();
        System.out.println("环绕后");

    }


}

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

    <!--方式三:注解实现AOP-->
    <bean id="annotationPointCut" class="com.sgl.diy.AnnotationPointCut"/>
    <!--开启注解支持-->
    <aop:aspectj-autoproxy/>

</beans>

测试:

import com.sgl.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 = context.getBean("userService", UserService.class);

        userService.delete();
    }
}

结果:

环绕前
signature:void com.sgl.service.UserService.delete()
=========方法执行前========
删除一个用户
=========方法执行后========
环绕后

整合Mybatis

回顾Mybatis

  1. 编写实体类
  2. 编写核心配置文件
  3. 编写接口
  4. 编写Mapper.xml文件
  5. 测试

导入依赖

pom.xml

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.37</version>
</dependency>
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.6</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.3.12</version>
</dependency>
<!--Spring操作数据库需要spring-jdbc-->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.3.12</version>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.7</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>2.0.6</version>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.20</version>
</dependency>
  1. 实体类
package com.sgl.pojo;

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

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private int id;
    private String name;
    private String pwd;
}
  1. Dao接口
package com.sgl.mapper;

import com.sgl.pojo.User;

import java.util.List;

public interface UserMapper {
    List<User> getUserList();
}
  1. 核心配置文件

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核心配置文件-->
<configuration>

    <typeAliases>
        <typeAlias type="com.sgl.pojo.User"/>
    </typeAliases>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF-8" />
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper class="com.sgl.mapper.UserMapper"/>
    </mappers>
</configuration>
  1. 接口实现类 由原来的UserDaoImpl转换为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">
<!--namespace=绑定一个对应的Dao/Mapper接口-->
<mapper namespace="com.sgl.mapper.UserMapper">

    <!--select查询语句-->
    <select id="getUserList" resultType="user">
        select * from mybatis.user
    </select>
</mapper>
  1. 测试
import com.sgl.mapper.UserMapper;
import com.sgl.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 java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class MyTest {
    public static void main(String[] args) throws IOException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();

        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = mapper.getUserList();

        for (User user : userList) {
            System.out.println(user);
        }
    }

}

结果:

User(id=1, name=刚龙, pwd=123456)
User(id=2, name=倩倩, pwd=123456)
User(id=3, name=肖总, pwd=123456)

问题解决:

  1. 资源导出失败的问题:在pom.xml中添加
<!--在build中配置resources,来防止我们资源导出失败的问题-->
<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>true</filtering>
        </resource>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>true</filtering>
        </resource>
    </resources>
</build>
  1. 1 字节的 UTF-8 序列的字节 1 无效

将xml文件的UTF-8修改为UTF8

在这里插入图片描述
如果遇到像这样的字节错误,修改xml文件,UTF-8改为UTF8

Mybatis-Spring 一

  1. 实体类 User
  2. 接口 UserDao
  3. UserMapper.xml
  4. 增加一个实现类 UserMapperImpl
package com.sgl.mapper;

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

import java.util.List;

public class UserMapperImpl implements UserMapper{

    //之前使用sqlSession执行,现在使用SqlSessionTempLate
    private SqlSessionTemplate sqlSession;

    public void setSqlSession(SqlSessionTemplate sqlSession) {
        this.sqlSession = sqlSession;
    }

    @Override
    public List<User> getUserList() {
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = mapper.getUserList();
        return userList;
    }
}
  1. 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核心配置文件-->
<configuration>

    <!--设置-->
    <!--<settings>-->
    <!--    <setting name="" value=""/>-->
    <!--</settings>-->

    <typeAliases>
        <typeAlias type="com.sgl.pojo.User"/>
    </typeAliases>

</configuration>
  1. spring-dao.xml 【重要】
<?xml version="1.0" encoding="UTF8"?>
<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">

    <!--Datasource:使用spring的数据源替换Mybatis的配置
        使用spring提供的JDBC: org.springframework.jdbc.datasource.DriverManagerDataSource
    -->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
        <property name="username" value="root"/>
        <property name="password" value="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/sgl/mapper/*.xml"/>
    </bean>

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

</beans>
  1. applicationContext.xml
<?xml version="1.0" encoding="UTF8"?>
<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">

    <import resource="spring-dao.xml"/>


    <bean id="userMapper" class="com.sgl.mapper.UserMapperImpl">
        <property name="sqlSession" ref="sqlSession"/>
    </bean>

</beans>

测试:

import com.sgl.mapper.UserMapper;
import com.sgl.pojo.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

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

public class MyTest {
    public static void main(String[] args) throws IOException {
        
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
        List<User> userList = userMapper.getUserList();
        for (User user : userList) {
            System.out.println(user);
        }


    }
}

Mybatis-Spring 二

  1. UserMapperImpl2
package com.sgl.mapper;

import com.sgl.pojo.User;
import org.mybatis.spring.support.SqlSessionDaoSupport;

import java.util.List;

public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper{
    @Override
    public List<User> getUserList() {
        // SqlSession sqlSession = getSqlSession();
        // UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        // List<User> userList = mapper.getUserList();
        // return userList;
        return getSqlSession().getMapper(UserMapper.class).getUserList();


    }
}
  1. applicationContext.xml
<?xml version="1.0" encoding="UTF8"?>
<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">


    <import resource="spring-dao.xml"/>


    <bean id="userMapper" class="com.sgl.mapper.UserMapperImpl">
        <property name="sqlSession" ref="sqlSession"/>
    </bean>

    <bean id="userMapper2" class="com.sgl.mapper.UserMapperImpl2">
        <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
    </bean>

</beans>

测试:

import com.sgl.mapper.UserMapper;
import com.sgl.pojo.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

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

public class MyTest {
    public static void main(String[] args) throws IOException {
        
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
        List<User> userList = userMapper.getUserList();
        for (User user : userList) {
            System.out.println(user);
        }
    }
    
    @Test
    public void test () {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserMapper userMapper = context.getBean("userMapper2", UserMapper.class);
        List<User> userList = userMapper.getUserList();
        for (User user : userList) {
            System.out.println(user);
        }
    }
}

注意:使用SqlSessionDaoSupport获取sqlSession不需要注入

声明事务

回顾事务

  • 要么都成功,要么都失败
  • 确保完整性和一致性

事务ACID原则:

  • 原子性(Atomicity)
    原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
  • 一致性(Consistency)
    事务前后数据的完整性必须保持一致。
  • 隔离性(Isolation)
    事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。
  • 持久性(Durability)
    持久性是指一个事务一旦被提交它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响

spring中的事务管理

添加约束:

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

  1. UserMapper
package com.sgl.mapper;

import com.sgl.pojo.User;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface UserMapper {
    List<User> getUserList();

    //添加一个用户
    int addUser(User user);
    //删除一个用户
    int deleteUser(@Param("id") int id);

}
  1. 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">
<!--namespace=绑定一个对应的Dao/Mapper接口-->
<mapper namespace="com.sgl.mapper.UserMapper">

    <!--select查询语句-->
    <select id="getUserList" resultType="user">
        select * from mybatis.user;
    </select>

    <insert id="addUser" parameterType="user">
        insert into mybatis.user (id,name,pwd) values (#{id},#{name},#{pwd});
    </insert>

    <delete id="deleteUser" parameterType="int">
        delete from mybatis.user where id=#{id};
    </delete>
</mapper>
  1. UserMapperImpl
package com.sgl.mapper;

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

import java.util.List;

public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper{



    @Override
    public List<User> getUserList() {

        User user = new User(7,"孙悟空","777777");

        //SqlSession sqlSession = getSqlSession();
        UserMapper mapper = getSqlSession().getMapper(UserMapper.class);
        mapper.addUser(user);
        mapper.deleteUser(5);

        //List<User> userList = mapper.getUserList();
        return mapper.getUserList();
    }

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

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

  1. spring-dao.xml
<?xml version="1.0" encoding="UTF8"?>
<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"
       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/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
        http://www.springframework.org/schema/tx
        https://www.springframework.org/schema/tx/spring-tx.xsd">

    <!--Datasource:使用spring的数据源替换Mybatis的配置
        使用spring提供的JDBC: org.springframework.jdbc.datasource.DriverManagerDataSource
    -->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
        <property name="username" value="root"/>
        <property name="password" value="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/sgl/mapper/*.xml"/>
    </bean>

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

    <!--结合AOP实现事务的织入-->
    <!--配置事务通知-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <!--给方法配置事务-->
        <!--给事务配置传播特性 propagation="REQUIRED"默认  propagation:传播-->
        <tx:attributes>
            <tx:method name="add" propagation="REQUIRED"/>
            <tx:method name="delete" propagation="REQUIRED"/>
            <tx:method name="update" propagation="REQUIRED"/>
            <tx:method name="query" read-only="true"/>
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>
    <!--配置事务织入-->
    <aop:config>
        <!--execution(* com.sgl.service.UserServiceImpl.*(..))"-->
        <aop:pointcut id="txPointCut" expression="execution(* com.sgl.mapper.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
    </aop:config>

</beans>

测试:

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

import java.util.List;

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserMapper userMapper = context.getBean("userMapper",UserMapper.class);

        List<User> userList = userMapper.getUserList();
        for (User user : userList) {
            System.out.println(user);
        }
    }
}

小结:

  • 如果不添加事务,即使代码出错,也会插入数据
  • 添加spring事务后,直接失败

完结

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

等慢慢

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

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

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

打赏作者

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

抵扣说明:

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

余额充值