spring框架教程

Spring框架详解(持续更新) Mybatis Spring SpringMVC详解 阅读详情

Spring框架

一、spring简介

简介:spring框架是一个轻量级的控制反转和面向切面的容器框架,用来解决项目开发中的复杂度问题–解耦

轻量级:体积小,对代码没有侵入性(代码侵入性:指的是业务代码中不会调用spring中任何一个类)
控制反转:IoC(Inverse of contral),把对象创建的工作交给spring完成,并且他还可以给对象属性赋值。
面向切面:AOP(Aspect Oriented Programming)面向切面编程,可以在不改变原有业务逻辑的情况下实现对业务逻辑的增强
容器:实例的容器,管理创建的对象

图片显示的就是spring家族 这篇文章最主要介绍Core Container这里边的组件也是最核心的组件
Web组件也就是我们常说的SpringMVC框架
Test组件是spring提供的测试框架
Data组件是spring对jdbc的封装,相当于mybatis框架。但是我们这里只使用他的transctions组件即事务

先介绍spring最核心的功能IoC和Aop

二、SpringIoC

一、Spring框架部署(IoC)
1.1、创建Maven工程
		创建这两个工程都可以.我创建java工程
  • java
  • web
1.1.2、添加springIoC依赖
  • core
  • beans
  • aop
  • expression
  • context

注意:正常情况下这5个依赖是都要导入的,但是他们5个是互相依赖的所以导入一个就行,maven会自动导入其他的依赖。

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

1.1.3、创建Spring配置文件

通过配置文件告诉Spring容器创建什么对象,给对象属性赋什么值

在rescources目录下创建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"
        xsi:schemaLocation="
		http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context
		http://www.springframework.org/schema/context/spring-context.xsd">

</beans>

1.2、创建Student实体类
public class Student {
    private String stuName;
    private Integer stuAge;
    private String stuGender;

    @Override
    public String toString() {
        return "Student{" +
                "stuName='" + stuName + '\'' +
                ", stuAge=" + stuAge +
                ", stuGender='" + stuGender + '\'' +
                '}';
    }

    public String getStuName() {
        return stuName;
    }

    public void setStuName(String stuName) {
        this.stuName = stuName;
    }

    public Integer getStuAge() {
        return stuAge;
    }

    public void setStuAge(Integer stuAge) {
        this.stuAge = stuAge;
    }

    public String getStuGender() {
        return stuGender;
    }

    public void setStuGender(String stuGender) {
        this.stuGender = stuGender;
    }
}

配置配置文件

<bean id="Student" class="com.xxp.bean.Student">
	<property name="stuName" value="张三"/>
	<property name="stuGender" value="男"/>
	<property name="stuAge" value="25"/>
</bean>
	

写测试类(这里你会发现你已经没有在new出Student啦 直接从spring容器中获取)

public class StudentTest {
    public static void main(String[]args){
        //这个就是创建spring容器的对象
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //从spring容器中获取Student对象 注意:这里的参数是配置文件中的id
        Object student = context.getBean("Student");
        System.out.println(student);
    }
}
二、spring的IoC和DI

IoC控制反转,依赖Spring对象工厂完成对象的创建
DI依赖注入,对创建好的对象的属性赋值

2.1、DI依赖注入
2.1.1、三种方式

spring容器通过反射给类创建对象,并给对象赋值
通过反射,给对象赋值的方式有3种:

  • set方式注入
  • 构造器注入
  • 接口注入(不常用)
2.1.1.1、set注入

使用到的实体类:

/**
 * 书类
 * @author xxp
 */
@Getter
@Setter
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class Book {
    private Integer bookId;
    private String bookName;
}


/**
 * Student实体类
 * @author xxp
 */
@Getter
@Setter
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class Student {
    private String stuName;
    private Integer stuAge;
    private String stuGender;
    private Book book;
    private List<Book> course;
    private Set<String> achievement;
    private Map<String ,String> testMap;
}

一、基本类型可以通过<property标签直接注入

<bean id="Student" class="com.xxp.bean.Student">
	<property name="stuName" value="张三"/>
	<property name="stuGender" value="男"/>
	<property name="stuAge" value="25"/>
	
	
</bean>

二、对象类型有两种方式

  • 第一种:先把对象交给spring容器 然后引入
	<bean id="book" class="com.xxp.bean.Book">
		<property name="bookId" value="01"/>
		<property name="bookName" value="java"/>
	</bean>
	<bean id="Student" class="com.xxp.bean.Student">
		<property name="book" ref="book"/>
	</bean>
  • 第二种方式:
<bean id="Student" class="com.xxp.bean.Student">
	<property name="book">
		<bean class="com.xxp.bean.Book">
			<property name="bookId" value="01"/>
			<property name="bookName" value="java"/>
		</bean>
	</property>
</bean>

三、List类型:使用list标签
基本类型赋值:

  • 第一种方式:
<bean id="Student" class="com.xxp.bean.Student">
	<property name="course">
		<list>
			<value>1</value>
			<value>2</value>
		</list>
	</property>
</bean>

第二种方式:

	<property name="course" value="1,2,3"/>

对象类型赋值:

  • 第一种方式:
<bean id="Student" class="com.xxp.bean.Student">

	<property name="course">
		<list>
			<bean class="com.xxp.bean.Book">
				<property name="bookId" value="01"/>
			</bean>
			<bean class="com.xxp.bean.Book">
				<property name="bookId" value="02"/>
				<property name="bookName" value="mysql"/>
			</bean>
		</list>
	</property>

</bean>
  • 第二种方式:
	<bean id="book" class="com.xxp.bean.Book"></bean>
<bean id="Student" class="com.xxp.bean.Student">
	<property name="course">
		<list>
			<ref bean="book"></ref>
			<ref bean="book"></ref>
		</list>
	</property>

</bean>

</beans>
四、set类型:与list一致
五、map类型:
<property name="testMap">
		<map>
			<entry key="a" value="1"/>
			<entry key="b" value="2"/>
		</map>
	</property>
2.1.1.2、构造器注入

基本数据类型可以使用下面方式注入 index是参数的顺序下标,可以不要这个index,但是必须保证参数列表的顺序是正确的

	<bean id="Student" class="com.xxp.bean.Student">
		<constructor-arg index="0" value="张三"/>
		<constructor-arg index="1" value="22"/>
		<constructor-arg index="2" value="男"/>
	</bean>

对于集合类型采用下面方式注入

<bean id="Student" class="com.xxp.bean.Student">
		<constructor-arg index="0" value="张三"/>
		<constructor-arg index="1" value="22"/>
		<constructor-arg index="2" value="男"/>
		<constructor-arg index="3">
			<bean class="com.xxp.bean.Book"></bean>
		</constructor-arg>

		<constructor-arg index="4">
			<list>
				<bean class="com.xxp.bean.Book"></bean>
				<bean class="com.xxp.bean.Book"></bean>
			</list>
		</constructor-arg>
		<constructor-arg index="5">
			<set>
				<value>1</value>
				<value>2</value>
			</set>
		</constructor-arg>
	</bean>

三、Spring-IoC----Bean的作用域

在spring中bean默认是单例模式,bean标签中设置scope=“singleton” 表示该对象为单例模式
如果想使用非单例模式则将值改为scope=“prototype”
spring中默认是饿汉模式spring容器在初始化的时候就会完成对象创建,在bean标签中设置**lazy-init=“true”**则表示开启懒汉模式

3.1、bean声明周期方法

在bean标签中通过init-method="init"配置当前类的初始化方法(该方法在对象创建之后执行)
使用destroy-method="destroy"来配置当前类的销毁方法(该方法在对象销毁之前执行)

配置文件

	<bean id="book" class="com.xxp.bean.Book" scope="prototype" init-method="init" destroy-method="destroy"></bean>

实体类

@Getter
@Setter
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class Book {
    private Integer bookId;
    private String bookName;

    public void init(){
        System.out.println("对象创建后执行");
    }
    public void destroy(){
        System.out.println("对象销毁前调用");
    }
}

四、Spring-IoC----自动装配

spring可以在实例化bean的时候,从spring容器中找到匹配的实例赋值给当前bean的属性
自动装配有两种方式:
第一种:byName 通过id名装配 缺点:如果id名字一致,但是类型不一致就会装配失败然后抛出异常
第二种:byType 通过类型装配 缺点:如果有多个类型一致的话就会抛出异常

第一种方式:配置autowire=“byName”

<bean id="student" class="com.xxp.bean.Student" autowire="byName"></bean>

第二种方式:配置autowire=“byType”

<bean id="student" class="com.xxp.bean.Student" autowire="byType"></bean>
五、Spring-IoC----注解配置

前面我们可以通过使用xml配置文件的方式将类声明给spring容器管理,从而让spring容器实现对象的创建和属性赋值
我们还可以通过注解的方式将我们的实体类交给spring容器管理,从而简化开发。

5.1、项目部署

5.1.1、引入依赖

  <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.22.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
        </dependency>
    </dependencies>

5.1.2、创建实体类

package com.xxp.bean;

import lombok.*;

@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Setter
@Getter
public class Student {
    private String name;
    private Integer age;
    private String sex;
}

5.1.3、创建配置文件

在配置文件中需要使用context:annotation-config/来声明使用注解配置
并且要通过<context:component-scan base-package=“com.xxp.bean”/>来告诉spring工厂注解的扫描范围,从而让spring容器完成初始化

<?xml version="1.0" encoding="UTF-8"?>
<beans
        xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="
		http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context
		http://www.springframework.org/schema/context/spring-context.xsd">
	<!--声明使用注解配置-->
	<context:annotation-config/>
	<!--声明Spring工厂注解的扫描范围-->
	<context:component-scan base-package="com.xxp.bean"/>
</beans>

六、Spring-IoC----常用注解(注解编程)
6.1.1、@component注解
  • 类注解,声明此类被spirng容器管理,相当于bean标签 @component(value=“类名”)相当于bean标签的id属性,也可以不写默认是类名的首字母小写
  • 除了@component注解外还有 @Service @Controller@Repository这三个注解也可将类声明到spring容器中,他们主要就是语义上的区别(也就是用的地方不一样)
    1.@Service主要用在业务层,比如Service接口的实现类
    2.@Controller主要用在控制层,比如servlet
    3.@Repository主要用在持久层,比如Dao接口
    4.@component主要用在上述中的其他类

实体类

@Component(value = "student")
public class Student {
    private String name;
    private Integer age;
    private String sex;
}

6.1.2、@Scope注解

类注解,在实体类上加上@Scope注解来声明,对象为单例还是多例

单例模式

@Scope(value = "singleton")
public class Student {
    private String name;
    private Integer age;
    private String sex;
}

多例模式

@Scope(value = "prototype")
public class Student {
    private String name;
    private Integer age;
    private String sex;
}
6.1.3、@Lazy注解

类注解,开启饿汉模式或者懒汉模式

@Lazy(value = true)
public class Student {
    private String name;
    private Integer age;
    private String sex;
}

6.1.4、@PostConstruct和 @PreDestroy注解

方法注解,@PostConstruct表示在创建对象之后执行
方法注解, @PreDestroy表示在对象销毁之前执行

	 @PostConstruct
    public void init(){
        System.out.println("初始化方法");
    }
    @PreDestroy
    public void destroy(){
        System.out.println("销毁方法");
    }

6.1.5、@Autowired注解和@Resource注解

属性注解、方法注解,@Autowired注解用于spring在创建对象的时候对对象的属性进行初始化操作
默认是使用的byType根据类型赋值,如果类型不匹配就会报错,可以使用它的required = false属性设置如果类型不匹配就设置当前属性值为null
要是想使用byName类型进行赋值,可以在set方法参数处加上@Qualifier注解

public class Student {
    private String name;
    private Integer age;
    private String sex;
    @Autowired(required = false)
    private Book book;
}

byName类型

public class Student {
    private String name;
    private Integer age;
    private String sex;
    
    private Book book;
    @Autowired(required = false)
	public void setBook(@Qualifier Book book){
	this.book=book;
}
	
}

@Resource注解 也是自动装配属性,它是java注解包提供的,并不是spring提供的,它默认是byName如果byName找不到那么会byType,如果根据类型也找不到那么就会抛出异常

public class Student {
    private String name;
    private Integer age;
    private String sex;
    
    private Book book;
   @Resource(required = false)
	public void setBook(@Qualifier Book book){
	this.book=book;
}
	
}

三、SpringAOP

先学习一下代理模式,代理模式比较抽象,可以选择暂时跳过这一部分,理论上不会影响SpringAOP的学习,当然学会啦更容易理解SpringAOP。

代理模式的优点:将通用性工作交给代理对象处理,被代理对象只需要关注自己的业务代码

比如下面这个例子:

这个你会发现开启事务和关闭事务每个方法都需要使用,造成啦代码重复。
这个时候就可以使用代理模式,把这些代码交给代理对象来完成
代理模式分两种:静态代理和动态代理 下面分别介绍

public class StudentDao {
    public void insert(){
        System.out.println("开启事务");
        System.out.println("insert-------");
        System.out.println("提交事务");
    }
    
    public void delete(){
        System.out.println("开启事务");
        System.out.println("delete-------");
        System.out.println("提交事务");
    }
}
一、SpringAOP----静态代理

静态代理只能为特定的类产生代理对象,不能代理任意类
好处:
1、被代理类只需要关注自己的业务代码的实现,将通用型的管理型逻辑(事务管理、日志管理)和业务逻辑分离。
2、 将通用的代码放在代理类中,提高代码的复用性
3、 通过在代理类中添加业务逻辑实现对原有业务逻辑的增强

1.1、创建一个通用代理方法接口

/**
 * @author xxp
 */
public interface GeneralProxy {
    void insert();
    void delete();
}


1.2、创建StudentDao并实现GeneralProxy接口重写方法

public class StudentDao implements GeneralProxy {
    public void insert() {
        System.out.println("StudentInsert");
    }

    public void delete() {
        System.out.println("StudentDelete");
    }
}

1.3、创建BookDao并实现GeneralProxy接口重写方法

public class BookDao implements GeneralProxy {
    public void insert() {
        System.out.println("BookInsert");
    }

    public void delete() {
        System.out.println("BookDelete");
    }
}

1.4、创建代理类,定义通用的方法,如:开启事务,提交事务

/**
 * 静态代理类
 * @author xxp
 */
public class MyProxy {
    private GeneralProxy generalProxy;
	//这个构造方法是重点,它决定代理哪个类
    public MyProxy(GeneralProxy generalProxy) {
        this.generalProxy = generalProxy;
    }

    public void insert() {
        begin();
        generalProxy.insert();
        commit();
    }

    public void delete() {
        begin();
        generalProxy.delete();
       commit();
    }
    public void begin(){
        System.out.println("开启事务");
    }
    public void commit(){
        System.out.println("提交事务");
    }
}

1.5、测试类

public class MyTest {
    public static void main(String[] args) {
        BookDao bookDao = new BookDao();
        StudentDao studentDao = new StudentDao();
//这里就实现啦代理,参数可以是bookDao也可以是 studentDao
        MyProxy myProxy = new MyProxy(bookDao);
        myProxy.delete();

    }
}

二、SrpingAOP----动态代理

静态代理有个缺点,就是只能代理实现啦特定接口的类。
动态代理则可以代理几乎所有的类。
动态代理实现的方式有两种:
1.JDK动态代理
2.CGLib动态代理

2.1、JDK动态代理

JDK动态代理是通过被代理对象实现的接口(这也是它的缺点)产生其代理对象的
实现步骤
1.创建一个类,实现InvocationHandler接口,重新invoke方法
2.定义一个Object类型的变量,并提供其有参构造方法,方便被代理对象传递进来
3.定义getProxy方法来获取被代理对象的实现的接口,并为它创建代理对象返回出去(这个过程是通过反射实现的)


/**
 * JDK动态代理
 * @author xxp
 */
public class JDKDynamicProxy implements InvocationHandler {
    //定义一个Object类型的变量,并提供其有参构造方法,方便被代理对象传递进来
    private Object object;
    public JDKDynamicProxy(Object object) {
        this.object = object;
    }

    public Object getProxy(){
        //获取被代理对象的类加载器
        ClassLoader loader = object.getClass().getClassLoader();
        //获取被代理对象实现的接口
        Class<?>[] interfaces = object.getClass().getInterfaces();
        //产生代理对象(通过被代理对象的类加载器及实现的接口)
        //1、第一个参数 被代理对象的类加载器
        //2、第二个参数 被代理对象实现的接口
        //3、第三个参数 用于拦截 产生的代理对象 调用的方法
        Object proxyInstance = Proxy.newProxyInstance(loader, interfaces, this);
        return proxyInstance;
    }


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

    public void begin(){
        System.out.println("开启事务");
    }
    public void commit(){
        System.out.println("关闭事务");
    }
}

测试类

public class MyTest {
    public static void main(String[] args) {
        BookDao bookDao = new BookDao();
        StudentDao studentDao = new StudentDao();
        //产生代理对象
        JDKDynamicProxy jdkDynamicProxy = new JDKDynamicProxy(bookDao);
        GeneralProxy proxy = (GeneralProxy) jdkDynamicProxy.getProxy();
        //使用代理对象调用方法时候并不会执行方法,而是被拦截啦进入到啦InvocationHandler中的invoke方法
        //调用的方法被作为参数传递给啦method
        proxy.delete();
    }
}

2.2、CGLib动态代理

前面的JDK动态代理有一个缺点:被代理的类必须实现接口
所以这里介绍另一个代理,CGLib动态代理
CGLib动态代理是通过创建被代理类的子类来创建代理对象的,因此没有实现接口的对象也可以创建代理对象
实现步骤:
1.创建一个类,实现MethodInterceptor接口,重写intercept方法
2.定义一个Object类型的变量,并提供其有参构造方法,方便被代理对象传递进来
3.定义getProxy方法来获取被代理对象,通过创建被代理对象的子类来实现

导入依赖

        <!-- https://mvnrepository.com/artifact/cglib/cglib -->
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>3.3.0</version>
        </dependency>

代理类

/**
 * CGLib‘动态代理
 * @author xxp
 */
public class CGLibDynamicProxy  implements MethodInterceptor {
    private Object object;

    public CGLibDynamicProxy(Object object) {
        this.object = object;
    }

    public Object getProxy(){
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(object.getClass());
        enhancer.setCallback(this);
        Object proxy = enhancer.create();
        return proxy;
    }
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        begin();
        Object returnValue = method.invoke(object, objects);
        commit();
        return returnValue;
    }

    public void begin(){
        System.out.println("开启事务");
    }
    public void commit(){
        System.out.println("关闭事务");
    }
}

测试类


/**
 * @author xxp
 */
public class MyTest {
    public static void main(String[] args) {
        BookDao bookDao = new BookDao();
        StudentDao studentDao = new StudentDao();
     
        CGLibDynamicProxy cgLibDynamicProxy = new CGLibDynamicProxy(bookDao);
        BookDao bookDaoProxy = (BookDao) cgLibDynamicProxy.getProxy();
        bookDaoProxy.delete();
    }
}

三、SpringAOP
3.1、AOP

AOP面向切面编程,是一种利用“横切的技术”(底层实现就是动态代理),对原有的逻辑进行拦截,并且可以在这个横切面上进行添加特定的业务逻辑,对原有代码进行增强
简单来说就是基于动态代理实现在不改变原有业务的情况下对业务逻辑进行增强。
专业术语:
切点:要增强的方法
切面:增强类
通知:织入切点处(这个通知分好多,后续详细介绍)

下面的例子是对studentDao中的insert和delete方法进行增强
导入依赖

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

定义切面

/**
 * 事务切面
 * @author xxp
 */
public class TxManager {
    public void begin(){
        System.out.println("开启事务!");
    }
    public void commit(){
        System.out.println("关闭事务!");
    }
}

创建studentDao

/**
 * @author xxp
 */
public class StudentDao {
    public void insert(){
        System.out.println("student添加");
    }
    public void delete(){
        System.out.println("student删除");
    }
}

配置文件

	<bean id="studentDao" class="com.xxp.dao.StudentDao"></bean>
	<!--切面类必须交给spring容器管理-->
	<bean id="txManager" class="com.xxp.util.TxManager"></bean>

	<aop:config>
	<!--声明切点-->
		<aop:pointcut id="studentDaoInsert" expression="execution(* com.xxp.dao.StudentDao.delete())"/>
	<!--声明切面-->
		<aop:aspect ref="txManager">
			<!--声明通知-->
			<aop:before method="begin" pointcut-ref="studentDaoInsert"/>
			<aop:after method="commit" pointcut-ref="studentDaoInsert"/>
		</aop:aspect>
	</aop:config>

</beans>

测试类

/**
 * @author xxp
 */
public class AspetTest {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
       StudentDao studentDao = (StudentDao) context.getBean("studentDao");

        studentDao.delete();
    }
}

3.2、通知的详解

AOP中通知分为:
前置通知:在指定切点的前面执行
后置通知:在指定切点的后面执行
环绕通知:在指定切点的前后执行


	<bean id="studentDao" class="com.xxp.dao.StudentDao"></bean>

	<bean id="txManager" class="com.xxp.util.TxManager"></bean>

	<aop:config>
	<!--声明切点-->
		<aop:pointcut id="studentDaoInsert" expression="execution(* com.xxp.dao.StudentDao.delete())"/>
	<!--声明切面-->
		<aop:aspect ref="txManager">
			<!--声明通知-->
			<!--前置通知-->
			<aop:before method="begin" pointcut-ref="studentDaoInsert"/>
			<!--后置通知-->
			<aop:after method="commit" pointcut-ref="studentDaoInsert"/>
			<!--环绕通知-->
			<aop:around method="method5" pointcut-ref="studentDaoInsert"/>
		</aop:aspect>
	</aop:config>

四、SrpingAop注解实现

@Aspect声明该类为切面类
@Pointcut声明切点
@Before前置通知
@After后置通知
@Around环绕通知

配置文件

<!--开启注解配置-->
	<context:annotation-config/>
<!--	注解扫描的范围-->
	<context:component-scan base-package="com.xxp"/>
	<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

切面类


/**
 * 事务切面
 * @author xxp
 */
@Component
@Aspect
public class TxManager {
    @Pointcut("execution(* com.xxp.dao.StudentDao.*(..))")
    public void tx() {
    }

    @Before("tx()")
    public void begin(){
        System.out.println("开启事务!");
    }
    @After("tx()")
    public void commit(){
        System.out.println("关闭事务!");
    }
    @Around("tx()")
    public Object method5(ProceedingJoinPoint point) throws Throwable {
        System.out.println("------环绕通知--前------");
        Object proceed = point.proceed();
        System.out.println("-------环绕通知---后------");
        return proceed;
    }
}

Spring全面讲解(无比详细) 希望大家共同进步,有兴趣的可以互相加个关注。石河子大学西北大学单元测试数据库连接池文件包含通配符。 阅读详情

相关推荐

Spring框架详细教程文档

Spring框架是企业级Java开发的核心框架,提供全面的编程和配置模型。核心特性包括控制反转(IoC)、依赖注入(DI)和面向切面编程(AOP)。IoC容器管理Bean的生命周期,支持多种作用域(singleton、prototype等)和配置方式(XML/注解/Java)。AOP实现横切关注点,提供五种通知类型。事务管理支持声明式和编程式两种方式,具有七种传播行为和四种隔离级别。资源管理统一访问各类资源,SpEL表达式语言支持运行时查询和操作对象图。Spring生态系统还包括Spring Boot、MV

weixin_51040479的博客 1050

Spring快速入门超详细讲解

在Spring框架规范中,所有由spring管理的对象都称之为Bean对象。Spring提供了以下多个注解,这些注解可以直接标注在java类上,将它们定义成Spring Bean。注解说明@Component该注解用于描述Spring中的Bean,它是一个泛化的概念,仅仅标识容器中的一 个组件(Bean),并且可以作用在任何层次,例如Service层、Dao层等,使用时只需将该注解标注在相应的类上即可。

南 阳 的博客 5088

Spring框架超全面快速入门教程(学spring,看这一篇就够了!)

Spring框架,由Rod Johnson开发,是一个非常强大的反转控制(IOC)框架,以帮助分离项目组件之间的依赖关系。 Spring通过PlatformTransactionManager平台事务管理器接口对事务的管理进行高度抽象,但是该接口下具体的实现是由各个平台自己实现,Spring并不直接管理事务,而是提供了多种事务管理器,也就是对各个平台的事务管理进行封装,最终将事务管理的职责委托给JDBC、Hibernate、JPA、JMS、MongoDB等持久化平台框架的事务来实现。 动力节点的sp

weixin_54585403的博客 3719

Spring入门第一讲——Spring框架的快速入门

IoC即Inversion of Control,反应过来就是控制反转。啥是控制反转啊?控制反转指的就是将对象的创建权反转给(交给)了Spring,其作用是实现了程序的解耦合。也可这样解释:获取对象的方式变了,对象创建的控制权不是"使用者",而是"框架"或者"容器"。用更通俗的话来说,IoC就是指对象的创建,并不是在代码中用new操作new出来的,而是通过Spring进行配置创建的。

m0_67393157的博客 765

尚硅谷-Spring5框架2020最新版教程笔记

尚硅谷-Spring5框架2020最新版教程 文章目录尚硅谷-Spring5框架2020最新版教程一、Spring框架概述1、Spring特点2、Spring版本选择3、入门案例二、IOC容器1、IOC底层原理2、IOC接口(BeanFactory)4、IOC操作 Bean 管理5、IOC操作 Bean 管理(基于xml)6、IOC操作Bean管理(xml注入其他类型属性)7、IOC操作Bean管理(xml注入集合属性)8、IOC操作Bean管理(FactotyBean)9、IOC操作Bean管理(bean

面向百度编程专家 6268

Spring4 HelloWorld - 掌握Spring框架的基础教程

Spring是一个开源的Java平台,最初由Rod Johnson创建并首次发布于2003年。它最初是作为一个轻量级的解决方案,用于替代EJB(Enterprise JavaBeans)等重型企业级Java应用。Spring框架的核心特性之一是支持依赖注入(DI)和控制反转(IoC)的概念,这使得它在单元测试和集成测试中表现出色。随着版本的演进,Spring已经发展成为一个全面的编程和配置模型,广泛应用于企业级应用的开发。

weixin_36078669的博客 817

Spring 最全入门教程详解

Spring 基础框架,可以视为Spring 基础设施,基本上任何其他 Spring 项目都是以 SpringFramework 为基础的。Spring 5 的模块结构图: lOC: Inversion of Control,翻译过来是反转控制。把对象创建和对象之间的调用过程,交给 Spring 进行管理Spring 的IOC 容器就是IOC 思想的一个落地的产品实现。IOC 容器中管理的组件也叫做 bean。在创建 bean 之前,首先需要创建IOC容器。Spring 提供了IOC容器的两种实现方式:

lucky_fd的博客 1万+

支付系统保证可靠性的秘诀 ----- 订单的补偿和补单

文章目录WHAT? 前言WHY? 为什么要用多级缓存?HOW 怎么做?方案 版本1:数据库存储专线配置通过优先级进行动态上下线方案 版本1 劣势:方案 版本2 :本地缓存替代数据库方案 版本2 劣势:方案 版本3:分布式缓存做自动补偿方案 版本3 总结:Where 分布式多级缓存还能用在哪些地方?总结 WHAT? 前言 刚入职场的时候觉得支付宝等第三方支付系统好强大,要保证这么多的交易不能错,也不能重复还要保证正确的扣钱,直到后面接触订单系统以及第三方支付公司的核心交易系统后才真正窥探到了支付系统的核心

boboaisisi的专栏 3534

2020最新Spring框架教程【IDEA版】-Spring框架从入门到精通

第一章:认识Spring 01p/102p Spring认识框架 02p/102p Spring官网浏览以及资源介绍 03p/102p 框架内部模块 第二章 IoC控制反转 04p/102p IoC概念 05p/102p 创建对象的方式 06p/102p IoC的实现技术 07p/102p 第一个例子创建对象 08p/102p 创建spring配置文件 09p/102p 创建容器对象ApplicaitonContext【拿到spring创建的对象】 @Test publi

不要回答的博客 3636

从JX-2R-01热敏打印机芯到稳定打印:硬件设计与时序控制的实践指南

本文详细解析了JX-2R-01热敏打印机芯的硬件设计与驱动开发全流程。核心内容包括:实现严格的双电源上电时序控制、采用PWM恒流驱动步进电机确保走纸平稳,以及精确控制SPI数据加载与加热脉冲时序以获得清晰打印效果。文章提供了从电路设计、芯片选型到代码调试的实战指南,旨在帮助开发者构建稳定可靠的热敏打印模块。

weixin_29169899的博客 223

COMSOL报错调试总结(不定期更新)

COMSOL报错调试总结1. 可定位错误1.1 除零错误1.2 未定义变量值1.3 边界条件/材料属性等缺失2. 难定位错误2.1. 装配期间内存不足 官方给的案例总是非常完美,运行流畅,结果完美。但是自己做模型时候就总是报错,而且不像自己coding的程序那样可以明确定位哪里出了bug。这里把我碰到的一些报错问题以及调试方法记录下来~ 部分来源于以下参考来源: http://wap.sciencenet.cn/blog-1467490-1118453.html?mobile=1 1. 可定位错误 以下错误

jessica0307的博客 8万+

Spring框架系列教程

18. Spring Integration:介绍Spring框架的集成解决方案,可以集成各种不同的应用程序和服务,包括数据库、消息队列、Web服务等。在这一部分,我们将介绍Spring框架的Web开发支持,包括Spring MVC、Spring WebFlux和Spring Boot。以上是一个Spring框架系列教程的大纲,您可以根据您的学习需求,逐一学习这些内容。15. Spring AOP:介绍Spring框架中的面向切面编程(AOP)功能,包括切面、连接点、切入点、通知、顾问等。

m0_75198698的博客 283

Zynq-PS-SDK(12) 之 VDMA+VTC+AXI4S-VideoOut 视频通路硬件搭建

前面分别叙述了《Zynq-PS-SDK(9) 之 VDMA》、《Zynq-PS-SDK(10) 之 VTC》以及《Zynq-PS-SDK(11) 之 AXI4-Stream To Video Out》;搭建一个简单的视频通路(Framebuffer -> HDMI)就要用到这些个模块,总体的设计框图如下所示: 视频数据的 Framebuffer 在 DDR 中,通过 Processing System 写入进去; 数据通过高带宽的 AXI4 接口(这里用到了 HP AXI,即 64bits 带

StephenZhou 5592

Spring框架实战教程

Spring框架实战教程 项目介绍 Spring 是一个极其广泛使用的 Java 应用程序框架,由 Pivotal 团队提供支持,它简化了企业级 Java 应用程序的开发。通过倡导依赖注入(DI)原则和面向切面编程(AOP),Spring 提供了一个全面的编程和配置模型,以用于现代Java EE应用程序。此GitHub仓库 https://github.com/JaydenForYou/Sprin...

gitblog_00562的博客 833

NVIDIA Jetson Xavier NX刷机教程

NVIDIA Jetson Xavier NX刷机教程,分别安装OS和SDK的经验分享

qq_68271367的博客 6958

多物理场耦合仿真-主题032-电磁-流体耦合

电磁-流体耦合,即磁流体动力学(MHD, Magnetohydrodynamics),是研究导电流体在电磁场中运动规律的学科,涉及电磁场与流体力学的深度耦合。本主题系统阐述磁流体动力学的基本理论、控制方程和数值方法。首先介绍MHD的基本概念和物理基础,包括导电流体的性质、电磁场基本方程;然后详细推导MHD控制方程组,包括连续性方程、动量方程、能量方程和电磁场方程;接着讨论MHD流动的特征参数,如Hartmann数、磁雷诺数、相互作用参数等;最后通过六个典型工程案例展示MHD分析的实际应用,包括电磁泵、磁流体

2401_87715305的博客 425

Spring框架教程

Spring是一个开源的Java EE开发框架。Spring框架的核心功能可以应用在任何Java应用程序中,但对Java EE平台上的Web应用程序有更好的扩展性。Spring框架的目标是使得Java EE应用程序的开发更加简捷,通过使用POJO为基础的编程模型促进良好的编程风格。

不古的博客 2091

OpenCV计算机视觉实战(11)——边缘检测详解

在本节中,我们系统介绍了三大经典边缘检测算子,包括 Sobel 算子:一阶导数平衡了噪声抑制与边缘提取,结合方向信息可用于纹理分析与车道检测;Laplacian 算子:二阶导数对微小亮度突变尤为敏感,配合零交叉和细化技术,可精确捕捉任意方向的细节边缘;Canny 算法:集成多阶段处理与双阈值策略,通过多尺度融合与自适应阈值优化,达到抗噪与细节兼顾的卓越效果。

qq_30167691的博客 4377

Django 教程、Spring框架介绍及使用

参考: Django 教程 Spring框架介绍及使用

qq_22820783的博客 1741

编写python脚本调用ordinals以及BRC20的接口

1、钱包地址生成walletreceive,对应ord命令:ord wallet receive。6、测试手动出块generate,这个只在regtest链节点用得上。所有接口都是post请求,采用postman进行测试。4、测试bitcoin转币sendtoaddress。7、测试其他的wallet方法wallet。2、钱包币种铭刻inscription,对应bitcoin-cli命令。对应bitcoin-cli命令。对应bitcoin-cli命令。fee.json文本模板。还可以加很多根据需要加减。

云深海阔专栏 1048

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

Mini-Spring 框架简易教程

Mini-Spring 框架简易教程 【免费下载链接】mini-spring mini-spring是简化版的spring框架,能帮助你快速熟悉spring源码和掌握spring的核心原理。抽取了spring的核心逻辑,代码极度简化,保留spring的核心功能,如IoC和AOP、资源加载器、事件监听器、类型转换、容器扩展...

gitblog_00339的博客 701

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

Spring框架下载教程

Spring下载

weixin_67628431的博客 1341

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Spring框架使用教程

Spring框架使用教程 项目介绍 Spring框架是Java平台上的一个开源应用框架,它为构建企业级应用提供了全面的基础架构支持。Spring不仅仅是一个框架,而是一系列优秀框架的集合,常简称为“Spring”。它极大地简化了Java企业级应用程序的开发,通过依赖注入(DI)和面向切面编程(AOP)等核心特性,支持从简单的Web应用到复杂的分布式系统。Spring框架提供了一系列模块,包括数据访...

gitblog_00518的博客 419

《Spring框架教程》

Spring框架简介 Spring框架教程Spring数据访问 Spring安全配置 Spring云服务 Spring微服务架构 Spring AOP使用 Spring事务管理 Spring最佳实践 Spring配置文件解析 Spring事件处理 Spring Bean生命周期 Spring框架案例分析 Spring更新日志 Spring框架面试题 Spring插件和工具 Spring框架视频教程 Spring框架在线课程 Spring框架书籍推荐 Spring错误解决方法

猫头虎技术团队:授渔优于赠鱼,兴趣引领智慧,探索之乐尤显珍贵。商务合作+:Libin9iOak ,万粉变现+:优快云WF,猫头虎承诺每年免费为100名C站创作者做账号流量诊断服务!全网搜:猫头虎技术团队,点击文章底部名片或直接私信我一切皆可谈,快找虎哥! 234

Spring 框架注解项目教程

Spring 框架注解项目教程 1. 项目的目录结构及介绍 Anotacoes-Spring-Framework/ ├── LICENSE ├── README.md └── src/ └── main/ └── java/ └── com/ └── example/ └── a...

gitblog_00267的博客 920
上一篇: Establishing SSL connection without server‘s identity verification is not recommended.问题解决
下一篇: spring DI的set方式注入,源码实现原理
秋水调威士忌
博客等级 码龄6年 631粉丝 23原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值