Spring IOC IOP
Maven安装和配置手册
项目管理工具:管理jar包
Jar:别人写好的类,用来实现一定的功能
镜像:通过镜像去相应的中央仓库下载jar包
1.Maven软件安装包下载
安装包下载地址可以参照 01 - 环境安装说明的所有软件下载网盘地址,也可以自行下载。
2.Maven安装步骤
2.1Maven是一个压缩包,解压后就直接可用。
2.2下载后解压该压缩包到指定目录,解压后的目录如下:
2.3在Maven解压目录的统计目录新建一个空文件夹,作为Maven仓库目录。
2.4打开apache-maven-3.6.2->conf->settings.xml文件,设置本地仓库路径
2.5打开apache-maven-3.6.2->conf->settings.xml文件,设置阿里镜像
阿里镜像地址:
nexus-aliyun
*
Nexus aliyun
http://maven.aliyun.com/nexus/content/groups/public
2.6配置Maven的环境变量:MAVEN_HOME和path
MAVEN_HOME maven的根目录配置:
Path配置:
2.7打开cmd,输入mvn -v查看maven的版本信息
2.8输入mvn help:system,下载maven的jar包
下载完毕后,原来空的仓库目录会下载一些初始的jar包
2.9在Eclipse中配合Maven路径和仓库路径
打开Eclipse->windows->preferences->Maven->Installations,弹出页面后点击add按钮
点击Directory按钮,弹出文件选择框,选择maven安装的根目录。点击选择文件夹
点击Finish后,选择新添加的maven安装路径,并且应用
打开Eclipse->preferences->Maven->Installations。设置本地Maven的settings 文件路径和本地仓库路径。
至此,Maven安装配置完毕。
一、 spring概述
1.什么是Springhttps://www.processon.com/view/5d9bfe1ee4b08fc441fe1032#map
Spring是一个轻量级的IOC和AOP容器的开源框架
Spring提倡以最少侵入(可以理解为耦合度)的方式来管理应用中的代码
2. Spring发展历程 (了解)
Rod Johnson ( Spring 之父)
2017 年
9 月份发布了 Spring 的最新版本 Spring5.0
通用版(GA)
3.Spring的优势(理解)
1)方便解耦,简化开发
通过 Spring 提供的 IoC容器,可以将对象间的依赖关系交由 Spring 进行控制,避免硬编码所造成的过度耦合。
用户也不必再为单例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。
2)AOP 编程的支持
通过 Spring的 AOP 功能,方便进行面向切面编程,许多不容易用传统 OOP 实现的功能可以通过 AOP 轻松实现。
3)声明式事务的支持
可以将我们从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活的进行事务管理,提高开发效率和质量。
4)方便程序的测试
可以用非容器依赖的编程方式进行几乎所有的测试工作,测试不再是昂贵的操作,而是随手可做的事情。
5)方便集成各种优秀框架
Spring对各种优秀框架(Struts、Hibernate、Hessian、Quartz等)的支持。
6)降低 JavaEE API 的使用难度
Spring对 JavaEE API(如 JDBC、JavaMail、远程调用等)进行了薄薄的封装层,使这些 API 的使用难度大为降低。
7)Java 源码是经典学习范例
Spring的源代码设计精妙、结构清晰、匠心独用,处处体现着大师对Java 设计模式灵活运用以及对 Java技术的高深
造诣。它的源代码无意是 Java 技术的最佳实践的范例。
4.Spring的体系结构(了解)
spring快速入门
2 .1Spring程序开发步骤
①导入 Spring 开发的基本包坐标
②编写 Dao 接口和实现类
③创建 Spring 核心配置文件
④在 Spring 配置文件中配置 UserDaoImpl
⑤使用 Spring 的 API 获得 Bean 实例
2.2 导入Spring开发的基本包坐标
<properties><spring.version>5.0.5.RELEASE</spring.version>
</properties>
<!--导入spring的context坐标,context依赖core、beans、expression-->
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version></dependency>
</dependencies>
2.3 编写Dao接口和实现类
public interface UserDao { public void save();
}
public class UserDaoImpl implements UserDao { @Override public void save() {System.out.println("UserDao save method running....");}
}
2.4 创建Spring核心配置文件
在类路径下(resources)创建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 http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
2.5 在Spring配置文件中配置UserDaoImpl
<?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 http://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="userDao" class="com.hopu.dao.impl.UserDaoImpl"></bean>
</beans>
2.6 使用Spring的API获得Bean实例
@Test
public void test1(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");UserDao userDao = (UserDao) applicationContext.getBean("userDao"); userDao.save();}
3. Spring配置文件
3.1 Bean标签基本配置
用于配置对象交由Spring 来创建。
默认情况下它调用的是类中的无参构造函数,如果没有无参构造函数则不能创建成功。
基本属性:
id:Bean实例在Spring容器中的唯一标识
class:Bean的全限定名称
3.2 Bean标签范围配置
scope:指对象的作用范围,取值如下:
取值范围 | 说明 |
---|---|
singleton | 默认值,单例的 |
prototype | 多例的 |
request | WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 request 域中 |
session | WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 session 域中 |
global session | WEB 项目中,应用在 Portlet 环境,如果没有 Portlet 环境那么globalSession 相当于 session |
1)当scope的取值为singleton时
Bean的实例化个数:1个Bean的实例化时机:当Spring核心文件被加载时,实例化配置的Bean实例Bean的生命周期:对象创建:当应用加载,创建容器时,对象就被创建了对象运行:只要容器在,对象一直活着对象销毁:当应用卸载,销毁容器时,对象就被销毁了
2)当scope的取值为prototype时
Bean的实例化个数:多个Bean的实例化时机:当调用getBean()方法时实例化Bean对象创建:当使用对象时,创建新的对象实例对象运行:只要对象在使用中,就一直活着对象销毁:当对象长时间不用时,被 Java 的垃圾回收器回收了
3.3 Bean生命周期配置
init-method:指定类中的初始化方法名称
destroy-method:指定类中销毁方法名称
3.4 Bean实例化三种方式
1) 使用无参构造方法实例化1) 它会根据默认无参构造方法来创建类对象,如果bean中没有默认无参构造函数,将会创建失败
<bean id="userDao" class="com.hopu.dao.impl.UserDaoImpl"/>
2) 工厂静态方法实例化 工厂的静态方法返回Bean实例
public class StaticFactoryBean {public static UserDao createUserDao(){ return new UserDaoImpl();}
}
<bean id="userDao" class="com.hopu.factory.StaticFactoryBean" factory-method="createUserDao" />
3) 工厂实例方法实例化 工厂的非静态方法返回Bean实例
public class DynamicFactoryBean { public UserDao createUserDao(){ return new UserDaoImpl(); }
}
<bean id="factoryBean" class="com.hopu.factory.DynamicFactoryBean"/>
<bean id="userDao" factory-bean="factoryBean" factory-method="createUserDao"/>
3.5 Bean的依赖注入入门
①创建 UserService,UserService 内部在调用 UserDao的save() 方法
public class UserServiceImpl implements UserService {@Overridepublic void save() {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); UserDao userDao = (UserDao) applicationContext.getBean("userDao"); userDao.save();}}
②将 UserServiceImpl 的创建权交给 Spring
<bean id="userService" class="com.hopu.service.impl.UserServiceImpl"/>
③从 Spring 容器中获得 UserService 进行操作
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) applicationContext.getBean("userService");
userService.save();
3.6 Bean的依赖注入概念
依赖注入(Dependency Injection):它是 Spring 框架核心 IOC 的具体实现。在编写程序时,通过控制反转,把对象的创建交给了 Spring,但是代码中不可能出现没有依赖的情况。IOC 解耦只是降低他们的依赖关系,但不会消除。例如:业务层仍会调用持久层的方法。那这种业务层和持久层的依赖关系,在使用 Spring 之后,就让 Spring 来维护了。简单的说,就是坐等框架把持久层对象传入业务层,而不用我们自己去获取
3.7 Bean的依赖注入方式
①构造方法 创建有参构造
public class UserServiceImpl implements UserService {@Override
public void save() {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); UserDao userDao = (UserDao) applicationContext.getBean("userDao"); userDao.save();}}
配置Spring容器调用有参构造时进行注入<bean id="userDao" class="com.hopu.dao.impl.UserDaoImpl"/>
<bean id="userService" class="com.hopu.service.impl.UserServiceImpl"> <constructor-arg name="userDao" ref="userDao"></constructor-arg>
</bean>
②set方法 在UserServiceImpl中添加setUserDao方法
public class UserServiceImpl implements UserService {private UserDao userDao;public void setUserDao(UserDao userDao) {this.userDao = userDao; } @Override public void save() { userDao.save();}
}
配置Spring容器调用set方法进行注入<bean id="userDao" class="com.hopu.dao.impl.UserDaoImpl"/>
<bean id="userService" class="com.hopu.service.impl.UserServiceImpl"><property name="userDao" ref="userDao"/>
</bean>
set方法:P命名空间注入P命名空间注入本质也是set方法注入,但比起上述的set方法注入更加方便,主要体现在配置文件中,如下:首先,需要引入P命名空间:xmlns:p="http://www.springframework.org/schema/p"
其次,需要修改注入方式<bean id="userService" class="com.hopu.service.impl.UserServiceImpl" p:userDao-ref="userDao"/>
3.8 Bean的依赖注入的数据类型
上面的操作,都是注入的引用Bean,处了对象的引用可以注入,普通数据类型,集合等都可以在容器中进行注入。注入数据的三种数据类型 普通数据类型引用数据类型集合数据类型其中引用数据类型,此处就不再赘述了,之前的操作都是对UserDao对象的引用进行注入的,下面将以set方法注入为例,演示普通数据类型和集合数据类型的注入。
Bean的依赖注入的数据类型
(1)普通数据类型的注入
public class UserDaoImpl implements UserDao {private String company;private int age;public void setCompany(String company) {this.company = company;}public void setAge(int age) {this.age = age;}public void save() {System.out.println(company+"==="+age);System.out.println("UserDao save method running...."); }
}
<bean id="userDao" class="com.hopu.dao.impl.UserDaoImpl"><property name="company" value="传智播客"></property><property name="age" value="15"></property>
</bean>
(2)集合数据类型(List)的注入
public class UserDaoImpl implements UserDao {private List<String> strList;public void setStrList(List<String> strList) {this.strList = strList;}public void save() {System.out.println(strList);System.out.println("UserDao save method running....");}
}
<bean id="userDao" class="com.hopu.dao.impl.UserDaoImpl"><property name="strList"><list><value>aaa</value><value>bbb</value><value>ccc</value></list></property>
</bean>
(3)集合数据类型(List)的注入
public class UserDaoImpl implements UserDao {private List<User> userList;public void setUserList(List<User> userList) {this.userList = userList; }
public void save() {System.out.println(userList);System.out.println("UserDao save method running....");}
}
<bean id="u1" class="com.hopu.domain.User"/>
<bean id="u2" class="com.hopu.domain.User"/>
<bean id="userDao" class="com.hopu.dao.impl.UserDaoImpl"><property name="userList"><list><bean class="com.hopu.domain.User"/><bean class="com.hopu.domain.User"/><ref bean="u1"/><ref bean="u2"/> </list></property>
</bean>
(4)集合数据类型( Map<String,User> )的注入
public class UserDaoImpl implements UserDao {private Map<String,User> userMap;public void setUserMap(Map<String, User> userMap) {this.userMap = userMap;}
public void save() { System.out.println(userMap);System.out.println("UserDao save method running....");}
}
<bean id="u1" class="com.hopu.domain.User"/>
<bean id="u2" class="com.hopu.domain.User"/>
<bean id="userDao" class="com.hopu.dao.impl.UserDaoImpl"><property name="userMap"><map> <entry key="user1" value-ref="u1"/><entry key="user2" value-ref="u2"/></map></property>
</bean>
(5)集合数据类型(Properties)的注入
public class UserDaoImpl implements UserDao {private Properties properties;public void setProperties(Properties properties) {this.properties = properties;}public void save() {System.out.println(properties);System.out.println("UserDao save method running....");}
}
<bean id="userDao" class="com.hopu.dao.impl.UserDaoImpl"><property name="properties"><props><prop key="p1">aaa</prop><prop key="p2">bbb</prop> <prop key="p3">ccc</prop></props></property>
</bean>
3.9 引入其他配置文件(分模块开发)
实际开发中,Spring的配置内容非常多,这就导致Spring配置很繁杂且体积很大,所以,可以将部分配置拆解到其他配置文件中,而在Spring主配置文件通过import标签进行加载<import resource="applicationContext-xxx.xml"/>
4. spring相关API
4.1 ApplicationContext的继承体系
applicationContext:接口类型,代表应用上下文,可以通过其实例获得 Spring 容器中的 Bean 对象
4.2 ApplicationContext的实现类
1)ClassPathXmlApplicationContext 它是从类的根路径下加载配置文件 推荐使用这种2)FileSystemXmlApplicationContext 它是从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置。3)AnnotationConfigApplicationContext当使用注解配置容器对象时,需要使用此类来创建 spring 容器。它用来读取注解。
4.3 getBean()方法使用
public Object getBean(String name) throws BeansException { assertBeanFactoryActive(); return getBeanFactory().getBean(name);
}
public <T> T getBean(Class<T> requiredType) throws BeansException { assertBeanFactoryActive();return getBeanFactory().getBean(requiredType);
}其中,当参数的数据类型是字符串时,表示根据Bean的id从容器中获得Bean实例,返回是Object,需要强转。当参数的数据类型是Class类型时,表示根据类型从容器中匹配Bean实例,当容器中相同类型的Bean有多个时,则此方法会报错
getBean()方法使用ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");UserService userService1 = (UserService) applicationContext.getBean("userService");UserService userService2 = applicationContext.getBean(UserService.class);
代码展示https://blog.csdn.net/weixin_47174945/article/details/116094637
SpringIoC和DI注解开发
二.Spring配置数据源
1.1 数据源(连接池)的作用
数据源(连接池)是提高程序性能如出现的事先实例化数据源,初始化部分连接资源使用连接资源时从数据源中获取使用完毕后将连接资源归还给数据源常见的数据源(连接池):DBCP、C3P0、BoneCP、Druid等
开发步骤①导入数据源的坐标和数据库驱动坐标②创建数据源对象③设置数据源的基本连接数据④使用数据源获取连接资源和归还连接资源
1.2 数据源的手动创建
①导入c3p0和druid的坐标<!-- C3P0连接池 -->
<dependency><groupId>c3p0</groupId><artifactId>c3p0</artifactId><version>0.9.1.2</version>
</dependency>
<!-- Druid连接池 -->
<dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.10</version>
</dependency>
①导入mysql数据库驱动坐标<!-- mysql驱动 -->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.39</version>
</dependency>
②创建C3P0连接池@Test
public void testC3P0() throws Exception {//创建数据源ComboPooledDataSource dataSource = new ComboPooledDataSource();//设置数据库连接参数dataSource.setDriverClass("com.mysql.jdbc.Driver"); dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");dataSource.setUser("root");dataSource.setPassword("root");//获得连接对象Connection connection = dataSource.getConnection();System.out.println(connection);
}
②创建Druid连接池@Test
public void testDruid() throws Exception {//创建数据源DruidDataSource dataSource = new DruidDataSource();//设置数据库连接参数dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost:3306/test"); dataSource.setUsername("root");dataSource.setPassword("root");//获得连接对象Connection connection = dataSource.getConnection(); System.out.println(connection);
}
③提取jdbc.properties配置文件jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=root
jdbc.password=root
④读取jdbc.properties配置文件创建连接池@Test
public void testC3P0ByProperties() throws Exception {//加载类路径下的jdbc.propertiesResourceBundle rb = ResourceBundle.getBundle("jdbc");ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setDriverClass(rb.getString("jdbc.driver")); dataSource.setJdbcUrl(rb.getString("jdbc.url")); dataSource.setUser(rb.getString("jdbc.username")); dataSource.setPassword(rb.getString("jdbc.password"));Connection connection = dataSource.getConnection(); System.out.println(connection);
}
1.3 Spring配置数据源
可以将DataSource的创建权交由Spring容器去完成
DataSource有无参构造方法,而Spring默认就是通过无参构造方法实例化对象的
DataSource要想使用需要通过set方法设置数据库连接信息,而Spring可以通过set方法进行字符串注入
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="com.mysql.jdbc.Driver"/><property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"/><property name="user" value="root"/><property name="password" value="root"/>
</bean>
测试从容器当中获取数据源ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");DataSource dataSource = (DataSource)
applicationContext.getBean("dataSource");
Connection connection = dataSource.getConnection();
System.out.println(connection);
1.4 抽取jdbc配置文件
applicationContext.xml加载jdbc.properties配置文件获得连接信息。首先,需要引入context命名空间和约束路径:命名空间:xmlns:context="http://www.springframework.org/schema/context"约束路径:http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="${jdbc.driver}"/><property name="jdbcUrl" value="${jdbc.url}"/><property name="user" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/>
</bean>
1.5 知识要点
Spring容器加载properties文件<context:property-placeholder location="xx.properties"/>
<property name="" value="${key}"/>
2. Spring注解开发
2.1 Spring原始注解
Spring是轻代码而重配置的框架,配置比较繁重,影响开发效率,所以注解开发是一种趋势,注解代替xml配置文件可以简化配置,提高开发效率。
Spring原始注解主要是替代的配置
注解 说明
@Component 使用在类上用于实例化Bean
@Controller 使用在web层类上用于实例化Bean
@Service 使用在service层类上用于实例化Bean
@Repository 使用在dao层类上用于实例化Bean
@Autowired 使用在字段上用于根据类型依赖注入
@Qualifier 结合@Autowired一起使用用于根据名称进行依赖注入
@Resource 相当于@Autowired+@Qualifier,按照名称进行注入
@Value 注入普通属性
@Scope 标注Bean的作用范围
@PostConstruct 使用在方法上标注该方法是Bean的初始化方法
@PreDestroy 使用在方法上标注该方法是Bean的销毁方法
注意:使用注解进行开发时,需要在applicationContext.xml中配置组件扫描,作用是指定哪个包及其子包下的Bean需要进行扫描以便识别使用注解配置的类、字段和方法。<!--注解的组件扫描-->
<context:component-scan base-package="com.hopu"></context:component-scan>
使用@Compont或@Repository标识UserDaoImpl需要Spring进行实例化。//@Component("userDao")
@Repository("userDao")
public class UserDaoImpl implements UserDao {@Overridepublic void save() {System.out.println("save running... ...");}
}
使用@Compont或@Service标识UserServiceImpl需要Spring进行实例化使用@Autowired或者@Autowired+@Qulifier或者@Resource进行userDao的注入//@Component("userService")
@Service("userService")
public class UserServiceImpl implements UserService {/*@Autowired@Qualifier("userDao")*/@Resource(name="userDao")private UserDao userDao;@Overridepublic void save() { userDao.save();}
}
使用@Value进行字符串的注入@Repository("userDao")
public class UserDaoImpl implements UserDao {@Value("注入普通数据")private String str;@Value("${jdbc.driver}")private String driver;@Overridepublic void save() {System.out.println(str);System.out.println(driver);System.out.println("save running... ...");}
}
使用@Scope标注Bean的范围//@Scope("prototype")
@Scope("singleton")
public class UserDaoImpl implements UserDao {//此处省略代码
}
使用@PostConstruct标注初始化方法,使用@PreDestroy标注销毁方法@PostConstruct
public void init(){System.out.println("初始化方法....");
}
@PreDestroy
public void destroy(){System.out.println("销毁方法.....");
}
2.2 Spring新注解
使用上面的注解还不能全部替代xml配置文件,还需要使用注解替代的配置如下:非自定义的Bean的配置:加载properties文件的配置:context:property-placeholder组件扫描的配置:context:component-scan
引入其他文件:注解 说明
@Configuration 用于指定当前类是一个 Spring 配置类,当创建容器时会从该类上加载注解
@ComponentScan 用于指定 Spring 在初始化容器时要扫描的包。 作用和在 Spring 的 xml 配置文件中的 <context:component-scan base-package="com.hopu"/>一样
@Bean 使用在方法上,标注将该方法的返回值存储到 Spring 容器中
@PropertySource 用于加载.properties 文件中的配置
@Import 用于导入其他配置类
@Configuration
@ComponentScan("com.hopu")
@Import({DataSourceConfiguration.class})
public class SpringConfiguration {}
@PropertySource("classpath:jdbc.properties")
public class DataSourceConfiguration {@Value("${jdbc.driver}")private String driver;@Value("${jdbc.url}")private String url;@Value("${jdbc.username}")private String username;@Value("${jdbc.password}")private String password;
@Bean(name="dataSource")
public DataSource getDataSource() throws PropertyVetoException { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setDriverClass(driver);dataSource.setJdbcUrl(url);dataSource.setUser(username);dataSource.setPassword(password);return dataSource;
}
测试加载核心配置类创建Spring容器@Test
public void testAnnoConfiguration() throws Exception {ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfiguration.class); UserService userService = (UserService) applicationContext.getBean("userService");userService.save();DataSource dataSource = (DataSource) applicationContext.getBean("dataSource");Connection connection = dataSource.getConnection(); System.out.println(connection);}
3. Spring整合Junit
3.1 原始Junit测试Spring的问题
在测试类中,每个测试方法都有以下两行代码:ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");IAccountService as = ac.getBean("accountService",IAccountService.class);这两行代码的作用是获取容器,如果不写的话,直接会提示空指针异常。所以又不能轻易删掉。
3.2 上述问题解决思路
让SpringJunit负责创建Spring容器,但是需要将配置文件的名称告诉它
将需要进行测试Bean直接在测试类中进行注入
3.3 Spring集成Junit步骤
①导入spring集成Junit的坐标
②使用@Runwith注解替换原来的运行期
③使用@ContextConfiguration指定配置文件或配置类
④使用@Autowired注入需要测试的对象
⑤创建测试方法进行测试
3.4 Spring集成Junit代码实现
①导入spring集成Junit的坐标<!--此处需要注意的是,spring5 及以上版本要求 junit 的版本必须是 4.12 及以上-->
<dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>5.0.2.RELEASE</version>
</dependency>
<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope>
</dependency>
②使用@Runwith注解替换原来的运行期@RunWith(SpringJUnit4ClassRunner.class)
public class SpringJunitTest {}
③使用@ContextConfiguration指定配置文件或配置类@RunWith(SpringJUnit4ClassRunner.class)
//加载spring核心配置文件
//@ContextConfiguration(value = {"classpath:applicationContext.xml"})
//加载spring核心配置类
@ContextConfiguration(classes = {SpringConfiguration.class})
public class SpringJunitTest {}
④使用@Autowired注入需要测试的对象@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {SpringConfiguration.class})
public class SpringJunitTest {@Autowiredprivate UserService userService;
}
⑤创建测试方法进行测试@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {SpringConfiguration.class})•public class SpringJunitTest {@Autowiredprivate UserService userService;@Testpublic void testUserService(){userService.save();}
}
Spring集成Junit步骤①导入spring集成Junit的坐标②使用@Runwith注解替换原来的运行期③使用@ContextConfiguration指定配置文件或配置类④使用@Autowired注入需要测试的对象⑤创建测试方法进行测试
三.Spring 的 AOP 简介
1.1 什么是 AOP
AOP 为 Aspect Oriented Programming 的缩写,意思为面向切面编程,是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP 是 OOP 的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
1.2 AOP 的作用及其优势
作用:在程序运行期间,在不修改源码的情况下对方法进行功能增强优势:减少重复代码,提高开发效率,并且便于维护
1.3 AOP 的底层实现
实际上,AOP 的底层是通过 Spring 提供的的动态代理技术实现的。在运行期间,Spring通过动态代理技术动态的生成代理对象,代理对象方法执行时进行增强功能的介入,在去调用目标对象的方法,从而完成功能的增强。
1.4 AOP 的动态代理技术
常用的动态代理技术JDK 代理 : 基于接口的动态代理技术cglib 代理:基于父类的动态代理技术
1.5 JDK 的动态代理
①目标类接口
public interface TargetInterface {public void method();
}
②目标类
public class Target implements TargetInterface {@Overridepublic void method() {System.out.println("Target running....");}
}
③动态代理代码
Target target = new Target(); //创建目标对象
//创建代理对象
TargetInterface proxy = (TargetInterface) Proxy.newProxyInstance(target.getClass()
.getClassLoader(),target.getClass().getInterfaces(),new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("前置增强代码...");Object invoke = method.invoke(target, args);System.out.println("后置增强代码...");return invoke;}}
);
④ 调用代理对象的方法测试
// 测试,当调用接口的任何方法时,代理对象的代码都无序修改
proxy.method();
1.6 cglib 的动态代理
①目标类
public class Target {public void method() {System.out.println("Target running....");}
}
②动态代理代码
Target target = new Target(); //创建目标对象
Enhancer enhancer = new Enhancer(); //创建增强器
enhancer.setSuperclass(Target.class); //设置父类
enhancer.setCallback(new MethodInterceptor() { //设置回调@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("前置代码增强....");Object invoke = method.invoke(target, objects);System.out.println("后置代码增强....");return invoke;}
});
Target proxy = (Target) enhancer.create(); //创建代理对象
③调用代理对象的方法测试
//测试,当调用接口的任何方法时,代理对象的代码都无序修改
proxy.method();
1.7 AOP 相关概念
Spring 的 AOP 实现底层就是对上面的动态代理的代码进行了封装,封装后我们只需要对需要关注的部分进行代码编写,并通过配置的方式完成指定目标的方法增强。在正式讲解 AOP 的操作之前,我们必须理解 AOP 的相关术语,常用的术语如下:Target(目标对象):代理的目标对象
Proxy (代理):一个类被 AOP 织入增强后,就产生一个结果代理类
Joinpoint(连接点):所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点
Pointcut(切入点):所谓切入点是指我们要对哪些 Joinpoint 进行拦截的定义
Advice(通知/ 增强):所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知
Aspect(切面):是切入点和通知(引介)的结合
Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程。spring采用动态代理织入,而AspectJ采用编译期织入和类装载期织入
1.8 AOP 开发明确的事项
1)需要编写的内容
编写核心业务代码(目标类的目标方法)
编写切面类,切面类中有通知(增强功能方法)
在配置文件中,配置织入关系,即将哪些通知与哪些连接点进行结合
2)AOP 技术实现的内容
Spring 框架监控切入点方法的执行。一旦监控到切入点方法被运行,使用代理机制,动态创建目标对象的代理对象,根据通知类别,在代理对象的对应位置,将通知对应的功能织入,完成完整的代码逻辑运行。
3)AOP 底层使用哪种代理方式
在 spring 中,框架会根据目标类是否实现了接口来决定采用哪种动态代理的方式。
1.9 知识要点
aop:面向切面编程aop底层实现:基于JDK的动态代理 和 基于Cglib的动态代理aop的重点概念:Pointcut(切入点):被增强的方法Advice(通知/ 增强):封装增强业务逻辑的方法Aspect(切面):切点+通知Weaving(织入):将切点与通知结合的过程
开发明确事项:谁是切点(切点表达式配置)谁是通知(切面类中的增强方法)将切点和通知进行织入配置
2. 基于 XML 的 AOP 开发
2.1 快速入门
①导入 AOP 相关坐标
②创建目标接口和目标类(内部有切点)
③创建切面类(内部有增强方法)
④将目标类和切面类的对象创建权交给 spring
⑤在 applicationContext.xml 中配置织入关系
⑥测试代码
①导入 AOP 相关坐标<!--导入spring的context坐标,context依赖aop-->
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.0.5.RELEASE</version>
</dependency>
<!-- aspectj的织入 -->
<dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.13</version>
</dependency>
②创建目标接口和目标类(内部有切点)public interface TargetInterface {public void method();
}
public class Target implements TargetInterface {@Overridepublic void method() {System.out.println("Target running....");}
}
③创建切面类(内部有增强方法)public class MyAspect {//前置增强方法public void before(){System.out.println("前置代码增强.....");}
}
④将目标类和切面类的对象创建权交给 spring<!--配置目标类-->
<bean id="target" class="com.hopu.aop.Target"></bean>
<!--配置切面类-->
<bean id="myAspect" class="com.hopu.aop.MyAspect"></bean>
⑤在 applicationContext.xml 中配置织入关系导入aop命名空间<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/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd">
⑤在 applicationContext.xml 中配置织入关系配置切点表达式和前置增强的织入关系<aop:config><!--引用myAspect的Bean为切面对象--><aop:aspect ref="myAspect"><!--配置Target的method方法执行时要进行myAspect的before方法前置增强--><aop:before method="before" pointcut="execution(public void com.hopu.aop.Target.method())"></aop:before></aop:aspect>
</aop:config>⑥测试代码@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class AopTest {@Autowiredprivate TargetInterface target;@Testpublic void test1(){target.method();}
}
2.2 XML 配置 AOP 详解
1) 切点表达式的写法
表达式语法:execution([修饰符] 返回值类型 包名.类名.方法名(参数))访问修饰符可以省略返回值类型、包名、类名、方法名可以使用星号* 代表任意包名与类名之间一个点 . 代表当前包下的类,两个点 .. 表示当前包及其子包下的类参数列表可以使用两个点 .. 表示任意个数,任意类型的参数列表
例如:execution(public void com.hopu.aop.Target.method()) execution(void com.hopu.aop.Target.*(..))execution(* com.hopu.aop.*.*(..))execution(* com.hopu.aop..*.*(..))execution(* *..*.*(..))
2) 通知的类型
通知的配置语法:<aop:通知类型 method=“切面类中方法名” pointcut=“切点表达式"></aop:通知类型>
3) 切点表达式的抽取
当多个增强的切点表达式相同时,可以将切点表达式进行抽取,在增强中使用 pointcut-ref 属性代替 pointcut 属性来引用抽取后的切点表达式。
<aop:config><!--引用myAspect的Bean为切面对象--><aop:aspect ref="myAspect"><aop:pointcut id="myPointcut" expression="execution(* com.hopu.aop.*.*(..))"/><aop:before method="before" pointcut-ref="myPointcut"></aop:before></aop:aspect>
</aop:config>
2.3 知识要点
aop织入的配置<aop:config><aop:aspect ref=“切面类”><aop:before method=“通知方法名称” pointcut=“切点表达式"></aop:before></aop:aspect>
</aop:config>
通知的类型:前置通知、后置通知、环绕通知、异常抛出通知、最终通知
切点表达式的写法:execution([修饰符] 返回值类型 包名.类名.方法名(参数))
3.基于注解的 AOP 开发
3.1 快速入门
基于注解的aop开发步骤:①创建目标接口和目标类(内部有切点)②创建切面类(内部有增强方法)③将目标类和切面类的对象创建权交给 spring④在切面类中使用注解配置织入关系⑤在配置文件中开启组件扫描和 AOP 的自动代理⑥测试
①创建目标接口和目标类(内部有切点)
public interface TargetInterface {public void method();
}
public class Target implements TargetInterface {@Overridepublic void method() {System.out.println("Target running....");}
}
②创建切面类(内部有增强方法)
public class MyAspect {//前置增强方法public void before(){System.out.println("前置代码增强.....");}
}
③将目标类和切面类的对象创建权交给 spring
@Component("target")
public class Target implements TargetInterface {@Overridepublic void method() {System.out.println("Target running....");}
}
@Component("myAspect")
public class MyAspect {public void before(){System.out.println("前置代码增强.....");}
}
④在切面类中使用注解配置织入关系
@Component("myAspect")
@Aspect
public class MyAspect {@Before("execution(* com.hopu.aop.*.*(..))")public void before(){System.out.println("前置代码增强.....");}
}
⑤在配置文件中开启组件扫描和 AOP 的自动代理
<!--组件扫描-->
<context:component-scan base-package="com.hopu.aop"/>
<!--aop的自动代理-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
⑥测试代码
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class AopTest {@Autowiredprivate TargetInterface target;@Testpublic void test1(){target.method();}
}
3.2 注解配置 AOP 详解
1) 注解通知的类型
通知的配置语法:@通知注解(“切点表达式")
2) 切点表达式的抽取
同 xml配置
aop 一样,我们可以将切点表达式抽取。抽取方式是在切面内定义方法,在该方法上使用@Pointcut注解定义切点表达式,然后在在增强注解中进行引用。具体如下:
@@Component("myAspect")
@Aspect
public class MyAspect {@Before("MyAspect.myPoint()")public void before(){System.out.println("前置代码增强.....");}@Pointcut("execution(* com.hopu.aop.*.*(..))")public void myPoint(){}
}
3.3 知识要点
注解aop开发步骤
①使用@Aspect标注切面类
②使用@通知注解标注通知方法
③在配置文件中配置aop自动代理aop:aspectj-autoproxy/
通知注解类型
四JdbcTemplate基本使用
01-JdbcTemplate基本使用-概述(了解)
JdbcTemplate是spring框架中提供的一个对象,是对原始繁琐的Jdbc API对象的简单封装。spring框架为我们提供了很多的操作模板类。例如:操作关系型数据的JdbcTemplate和HibernateTemplate,操作nosql数据库的RedisTemplate,操作消息队列的JmsTemplate等等。
02-JdbcTemplate基本使用-开发步骤(理解)
①导入spring-jdbc和spring-tx坐标
②创建数据库表和实体
③创建JdbcTemplate对象
④执行数据库操作
03-JdbcTemplate基本使用-快速入门代码实现(应用)
导入spring-jdbc和spring-tx坐标
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.hopu</groupId><artifactId>hopu_spring_jdbc</artifactId><version>1.0-SNAPSHOT</version><packaging>war</packaging>
<name>hopu_spring_jdbc Maven Webapp</name><!-- FIXME change it to the project's website --><url>http://www.example.com</url><dependencies><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.32</version></dependency><dependency><groupId>c3p0</groupId><artifactId>c3p0</artifactId><version>0.9.1.2</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.10</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.0.5.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>5.0.5.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>5.0.5.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.0.5.RELEASE</version></dependency><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.0.1</version><scope>provided</scope></dependency><dependency><groupId>javax.servlet.jsp</groupId><artifactId>javax.servlet.jsp-api</artifactId><version>2.2.1</version><scope>provided</scope></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.9.0</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.9.0</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-annotations</artifactId><version>2.9.0</version></dependency><dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.3.1</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.3</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.0.5.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId><version>5.0.5.RELEASE</version></dependency></dependencies>
</project>
创建数据库表和实体
package com.hopu.domain;
public class Account {private String name;private double money;
public String getNa me() {return name;}
public void setName(String name) {this.name = name;}
public double getMoney() {return money;}
public void setMoney(double money) {this.money = money;}
@Overridepublic String toString() {return "Account{" +"name='" + name + '\'' +", money=" + money +'}';}
}
创建JdbcTemplate对象 执行数据库操作
@Test//测试JdbcTemplate开发步骤public void test1() throws PropertyVetoException {//创建数据源对象ComboPooledDataSource dataSource = new ComboPooledDataSource();dataSource.setDriverClass("com.mysql.jdbc.Driver");dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");dataSource.setUser("root");dataSource.setPassword("root");
JdbcTemplate jdbcTemplate = new JdbcTemplate();//设置数据源对象 知道数据库在哪jdbcTemplate.setDataSource(dataSource);//执行操作int row = jdbcTemplate.update("insert into account values(?,?)", "tom", 5000);System.out.println(row);
}
04-JdbcTemplate基本使用-spring产生模板对象分析(理解)
我们可以将JdbcTemplate的创建权交给Spring,将数据源DataSource的创建权也交给Spring,在Spring容器内部将数据源DataSource注入到JdbcTemplate模版对象中,然后通过Spring容器获得JdbcTemplate对象来执行操作。
05-JdbcTemplate基本使用-spring产生模板对象代码实现(应用)
配置如下:
<!--数据源对象--><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="com.mysql.jdbc.Driver"></property><property name="jdbcUrl" value="jdbc:mysql:///test"></property><property name="user" value="root"></property><property name="password" value="root"></property></bean>
<!--jdbc模板对象--><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource"/></bean>
测试代码
@Test//测试Spring产生jdbcTemplate对象public void test2() throws PropertyVetoException {ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");JdbcTemplate jdbcTemplate = app.getBean(JdbcTemplate.class);int row = jdbcTemplate.update("insert into account values(?,?)", "lisi", 5000);System.out.println(row);}
06-JdbcTemplate基本使用-spring产生模板对象代码实现(抽取jdbc.properties)(应用)
将数据库的连接信息抽取到外部配置文件中,和spring的配置文件分离开,有利于后期维护
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=root
jdbc.password=root
配置文件修改为:
<?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.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
">
<!--加载jdbc.properties--><context:property-placeholder location="classpath:jdbc.properties"/>
<!--数据源对象--><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="${jdbc.driver}"/><property name="jdbcUrl" value="${jdbc.url}"/><property name="user" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></bean>
<!--jdbc模板对象--><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource"/></bean>
</beans>
07-JdbcTemplate基本使用-常用操作-更新操作(应用)
package com.hopu.test;
import com.hopu.domain.Account;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.List;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class JdbcTemplateCRUDTest {@Autowiredprivate JdbcTemplate jdbcTemplate;//修改更新@Testpublic void testUpdate(){jdbcTemplate.update("update account set money=? where name=?",10000,"tom");}//删除@Testpublic void testDelete(){jdbcTemplate.update("delete from account where name=?","tom");}
}
08-JdbcTemplate基本使用-常用操作-查询操作(应用)
在这里插入代码片package com.hopu.test;
import com.hopu.domain.Account;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.List;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class JdbcTemplateCRUDTest {@Autowiredprivate JdbcTemplate jdbcTemplate;//聚合查询@Testpublic void testQueryCount(){Long count = jdbcTemplate.queryForObject("select count(*) from account", Long.class);System.out.println(count);}//查询一个@Testpublic void testQueryOne(){Account account = jdbcTemplate.queryForObject("select * from account where name=?", new BeanPropertyRowMapper<Account>(Account.class), "tom");System.out.println(account);}//查询所有@Testpublic void testQueryAll(){List<Account> accountList = jdbcTemplate.query("select * from account", new BeanPropertyRowMapper<Account>(Account.class));System.out.println(accountList);}
}
09-JdbcTemplate基本使用-知识要点(理解,记忆)
①导入spring-jdbc和spring-tx坐标②创建数据库表和实体③创建JdbcTemplate对象JdbcTemplate jdbcTemplate = newJdbcTemplate();jdbcTemplate.setDataSource(dataSource);④执行数据库操作更新操作:
jdbcTemplate.update (sql,params)
查询操作:
jdbcTemplate.query (sql,Mapper,params)
jdbcTemplate.queryForObject(sql,Mapper,params)
声明式事务控制
1.1 PlatformTransactionManager
PlatformTransactionManager 接口是 spring 的事务管理器,它里面提供了我们常用的操作事务的方法。
注意:
PlatformTransactionManager 是接口类型,不同的 Dao 层技术则有不同的实现类,例如:Dao 层技术是jdbc 或 mybatis 时:org.springframework.jdbc.datasource.DataSourceTransactionManager Dao 层技术是hibernate时:org.springframework.orm.hibernate5.HibernateTransactionManager
1.2 TransactionDefinition
1. 事务隔离级别
设置隔离级别,可以解决事务并发产生的问题,如脏读、不可重复读和虚读。ISOLATION_DEFAULT
ISOLATION_READ_UNCOMMITTED
ISOLATION_READ_COMMITTED
ISOLATION_REPEATABLE_READ
ISOLATION_SERIALIZABLE
###2. 事务传播行为
REQUIRED:如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。一般的选择(默认值)
SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行(没有事务)
MANDATORY:使用当前的事务,如果当前没有事务,就抛出异常
REQUERS_NEW:新建事务,如果当前在事务中,把当前事务挂起。
NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
NEVER:以非事务方式运行,如果当前存在事务,抛出异常
NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行 REQUIRED 类似的操作
超时时间:默认值是-1,没有超时限制。如果有,以秒为单位进行设置
是否只读:建议查询时设置为只读
1.3 TransactionStatus
TransactionStatus 接口提供的是事务具体的运行状态,方法介绍如下。
###1.4 知识要点
编程式事务控制三大对象PlatformTransactionManager
TransactionDefinition
TransactionStatus
2 基于 XML 的声明式事务控制
2.1 什么是声明式事务控制
Spring 的声明式事务顾名思义就是采用声明的方式来处理事务。这里所说的声明,就是指在配置文件中声明,用在 Spring 配置文件中声明式的处理事务来代替代码式的处理事务。
声明式事务处理的作用
事务管理不侵入开发的组件。具体来说,业务逻辑对象就不会意识到正在事务管理之中,事实上也应该如此,因为事务管理是属于系统层面的服务,而不是业务逻辑的一部分,如果想要改变事务管理策划的话,也只需要在定义文件中重新配置即可
在不需要事务管理的时候,只要在设定文件上修改一下,即可移去事务管理服务,无需改变代码重新编译,这样维护起来极其方便
注意:Spring 声明式事务控制底层就是AOP。
2.2 声明式事务控制的实现
声明式事务控制明确事项:
谁是切点?
谁是通知?
配置切面?
①引入tx命名空间
<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/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd">
②配置事务增强
<!--平台事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property>
</bean>
<!--事务增强配置-->
<tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><tx:method name="*"/></tx:attributes>
</tx:advice>
③配置事务 AOP 织入
<aop:config><aop:pointcut id="myPointcut" expression="execution(* com.hopu.service.impl.*.*(..))"/><aop:advisor advice-ref="txAdvice" pointcut-ref="myPointcut"></aop:advisor>
</aop:config>
④测试事务控制转账业务代码
@Override
public void transfer(String outMan, String inMan, double money) {accountDao.out(outMan,money);int i = 1/0;accountDao.in(inMan,money);
}
2.3 切点方法的事务参数的配置
<!--事务增强配置-->
<tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><tx:method name="*"/></tx:attributes>
</tx:advice>
其中,tx:method 代表切点方法的事务参数的配置,例如:
<tx:method name="transfer" isolation="REPEATABLE_READ" propagation="REQUIRED" timeout="-1" read-only="false"/>
name:切点方法名称
isolation:事务的隔离级别
propogation:事务的传播行为
timeout:超时时间
read-only:是否只读
2.4 知识要点
声明式事务控制的配置要点
平台事务管理器配置
事务通知的配置
事务aop织入的配置
3 基于注解的声明式事务控制
3.1 使用注解配置声明式事务控制
编写 AccoutDao
@Repository("accountDao")
public class AccountDaoImpl implements AccountDao {@Autowiredprivate JdbcTemplate jdbcTemplate;public void out(String outMan, double money) {jdbcTemplate.update("update account set money=money-? where name=?",money,outMan);}public void in(String inMan, double money) {jdbcTemplate.update("update account set money=money+? where name=?",money,inMan);}
}
编写 AccoutService
@Service("accountService")
@Transactional
public class AccountServiceImpl implements AccountService {@Autowiredprivate AccountDao accountDao;@Transactional(isolation = Isolation.READ_COMMITTED,propagation = Propagation.REQUIRED)public void transfer(String outMan, String inMan, double money) {accountDao.out(outMan,money);int i = 1/0;accountDao.in(inMan,money);}
}
编写 applicationContext.xml 配置文件
<!—之前省略datsSource、jdbcTemplate、平台事务管理器的配置-->
<!--组件扫描-->
<context:component-scan base-package="com.hopu"/>
<!--事务的注解驱动-->
<tx:annotation-driven/>
3.2 注解配置声明式事务控制解析
①使用 @Transactional 在需要进行事务控制的类或是方法上修饰,注解可用的属性同 xml 配置方式,例如隔离级别、传播行为等。
②注解使用在类上,那么该类下的所有方法都使用同一套注解参数配置。
③使用在方法上,不同的方法可以采用不同的事务参数配置。
④Xml配置文件中要开启事务的注解驱动<tx:annotation-driven />
3.3 知识要点
注解声明式事务控制的配置要点
平台事务管理器配置(xml方式)
事务通知的配置(@Transactional注解配置)
事务注解驱动的配置 tx:annotation-driven/
Spring IOC IOP相关推荐
- spring IOC创建对象方式
spring IOC创建对象方式 通过无参构造来创建 验证方法: 创建实体类: public class User {private String name;public User() {System ...
- spring ioc原理分析
spring ioc原理分析 spring ioc 的概念 简单工厂方法 spirng ioc实现原理 spring ioc的概念 ioc: 控制反转 将对象的创建由spring管理.比如,我们以前用 ...
- Spring IoC是如何进行依赖注入的
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 依赖注入(DI) DI(Dependency Injection) ...
- 面试被问烂的 Spring IOC(求求你别再问了)
点击上方"方志朋",选择"置顶或者星标" 你的关注意义重大! 作者:莫那·鲁道 链接:http://thinkinjava.cn 广义的 IOC IoC(Inv ...
- spring根据名称获取bean_带你从零开始手写 spring ioc 框架,深入学习 spring 源码
IoC Ioc 是一款 spring ioc 核心功能简化实现版本,便于学习和理解原理. 创作目的 使用 spring 很长时间,对于 spring 使用非常频繁,实际上对于源码一直没有静下心来学习过 ...
- 还不懂spring IOC核心原理?200行代码带你手撸一个
Spring做为Java企业级应用的开源开发框架,早已成为Java后端开发事实上的行业标准,无数的公司选择Spring作为基础的开发框架. 使用Spring框架的人一定都听过Spring的IoC(控制 ...
- 头条一面:Spring IOC容器中只存放单例Bean吗?
最近,很多小伙伴出去面试,感觉自己面的不是很理想,回来后,不少小伙伴把面试题做了记录发给我,让我给大家解析下,然后发出来.当我看到这些面试题时,快速在脑海中构建起了整个知识体系,从基础到框架.从分布式 ...
- 谈谈对Spring IOC的理解
2019独角兽企业重金招聘Python工程师标准>>> 学习过Spring框架的人一定都会听过Spring的IoC(控制反转) .DI(依赖注入)这两个概念,对于初学Spring的人 ...
- Spring点滴一:Spring Ioc 容器
Spring 容器: Spring 容器是Spring框架的核心.Spring容器将创建Bean对象实例,把它们联系在一起,配置它们,并管理它们整个生命周期从创建到销毁.Spring 容器通过依赖注入 ...
最新文章
- 高级程序设计 c语言 在线作业,[北京师范大学]19秋《高级程序设计(C)》离线作业(资料)...
- python 的回调函数
- Python线程、进程知识整理
- GridView Bind 短日期 格式
- jQuery—淘宝精品服饰案例
- CloudStack之nfs
- linux dd copy all partitions,Linux 系统下使用dd命令备份还原MBR主引导记录
- visual studio可以开发app吗_郑州app开发价格是怎么定得呢?预约理发app好做吗
- 邢波老师致广大学员的一封信(2010-10-26)
- django登录验证码操作
- python: 大规模数据集的读存技巧
- DSP 6678的NETCP
- OpenCV常用库函数
- 【HarmonyOS HiSpark IPC DIY Camera试用连载2 】一天内极速完成从开箱编译烧写到跑通hello world
- codeforces 707c
- 俄黑客入侵100多万部安卓手机 盗取500多万卢布
- Visual Studio开发环境介绍 及控件属性、事件
- 中移动浦发联合发布四款产品 ,NFC手机年底上市
- 线下店迎来“文艺复兴”,三只松鼠哪里寻“独门妙方”?
- web安全性测试用例(输入、输出、SQL注入、跨站请求伪造(CSRF)、跨站脚本攻击(XSS))实实在在的干货
热门文章
- java读取纯真IP数据库qqwry.dat的源代码
- C++ 简化 推箱子 小游戏 完整代码 参考网络资料 命令行运行 仅供初学者参考交流
- 春哥博客 - Day01 - Python基础之print
- 【Elasticsearch】bulk的使用
- 【面经】华为车BU面经
- C语言练习,计算圆的面积和周长。
- 软件功能介绍之(数据维护)3.1数据编辑(1)
- BZOJ 1257 [CQOI2007]余数之和sum 题解
- 使用JSP从服务器下载文件的示例
- (python基础)df.loc和df.iloc