Spring
项目搭建
1.创建一个maven项目
2.导入Spring依赖
<!-- spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
3.编写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" xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" class="com.ffyc.springdemo.model.User">
<property name="id" value="1"></property>
<property name="name" value="张三"></property>
</bean>
</beans>
4.编写实体类
import lombok.Data;
@Data
public class User {
private int id;
private String name;
}
5.测试
public class Test {
@org.junit.Test
public void test(){
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("spring.xml");
User user=classPathXmlApplicationContext.getBean("user",User.class);
System.out.println(user);
User user1=classPathXmlApplicationContext.getBean("user",User.class);
System.out.println(user1);
System.out.println(user==user1);
}
}
测试结果
User(id=1, name=张三)
User(id=1, name=张三)
true
Spring Bean 管理
1.基于xml配置管理
2.使用注解标签
@Componment(value=“”)
适用于model类
@Repository(value=“”)
适用于dao层
@Service(value=“”)
适用于service层
@Scope(value=“”)
适用于所有类
@Scope(value=“prototype”) 原型
@Scope(value=“ singleton ”) 单例
@Autowired(value=“”)
用来自动注入对象
注入对象的两种方式:
byName
使用该方法注入对象需要加上@Qualifier(value=“”)标签
byType(默认使用类型查找)
@Resource(name=“”)
由JDK提供的自动注入对象的标签,既可以按照名称匹配Bean,也可以通过名称匹配
默认按照ByName自动注入
注解与XML的对比
注解优点:方便直观高效
注解缺点:修改后需要重新编译代码
XML优点:配置与代码是分离的,修改后无需重新编译,只需要重启服务器
XML缺点:编写麻烦,效率低
项目搭建
编写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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.ffyc.springdemo"></context:component-scan></beans>
编写实体类,dao层,service层,并添加注解标签
@Data
@Component(value = "user")
public class User {
private int id;
private String name;
}
@Repository(value = "userDao")
public class UserDao {
public void save(User user){
System.out.println("保存管理员"+user);
}
}
@Service(value = "userService")
public class UserService {
@Autowired
UserDao userDao;
public void save(User user){
userDao.save(user);
}
}
测试
public class Test {
@org.junit.Test
public void test() {
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("spring.xml");
User user=classPathXmlApplicationContext.getBean("user",User.class);
user.setId(1);
user.setName("张三");
UserService userService=classPathXmlApplicationContext.getBean("userService",UserService.class);
userService.save(user);
}
}
结果:保存管理员User(id=1, name=张三)
Spring JDBC
1.导入JDBC,Mysql,阿里巴巴提供的数据源管理组件
<!-- spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
<!-- 阿里数据源 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<!--MySQL-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
2.创建config.properties
classDiverName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/mybatis?serverTimezone=Asia/Shanghai
uname=root
upassword=123
3.创建db.xml,用于配置JDBC(在其中导入config.properties)
<?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 https://www.springframework.org/schema/context/spring-context.xsd">
<!--用来配置数据库相关的东西-->
<!--导入属性文件-->
<context:property-placeholder location="config.properties"/>
<!--管理数据源对象-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${classDiverName}"></property>
<property name="url" value="${url}"></property>
<property name="username" value="${uname}"></property>
<property name="password" value="${upassword}"></property>
<property name="initialSize" value="10"></property>
<property name="minIdle" value="5"></property>
<property name="maxActive" value="20"></property>
</bean>
<!--在配置文件中创建 JdbcTemplate-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
</beans>
4.在spring.xml中导入db.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 https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.ffyc.springdemo"></context:component-scan>
<import resource="classpath:db.xml"></import>
</beans>
5.测试
@Service(value = "userService")
public class UserService {
/*@Autowired
UserDao userDao;*/
@Autowired
JdbcTemplate jdbcTemplate;
public void save() {
// jdbcTemplate.update("delete from user where id=?",1);
List<User> users=jdbcTemplate.query("select * from user", new RowMapper<User>() {
@Override
public User mapRow(ResultSet resultSet, int i) throws SQLException {
User user = new User();
user.setId(resultSet.getInt("id"));
user.setName(resultSet.getNString("name"));
return user;
}
});
System.out.println(users);
}
}
public class Test2 {
@Autowired
JdbcTemplate jdbcTemplate;
@Test
public void Test(){
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("spring.xml");
UserService userService=classPathXmlApplicationContext.getBean("userService",UserService.class);
userService.save();
}
}
结果
五月 27, 2023 3:51:49 下午 com.alibaba.druid.support.logging.JakartaCommonsLoggingImpl info
信息: {dataSource-1} inited
[User(id=3, name=张三), User(id=4, name=李四), User(id=5, name=小王)]
补充
JdbcTemplate 中常用的方法
execute:无返回值,可执行 ddl,增删改语句
update:执行新增、修改、删除语句;
queryForXXX:执行查询相关语句;
AOP
简介
是一种编程技巧,将程序中的非业务代码进行提取,在不改动原代码的基础上为程序添加额外的功能。使用该技巧可以将业务代码和非业务代码进行隔离,使得各个部分的耦合度降低。
非业务代码:验证,日志,提交事务,统一异常处理等。
底层实现:使用的是动态代理模式
AOP中的基本概念
连接点:可以被增强的方法
切入点:实际被增强的方法
通知:需要增强的功能,有五个通知(前置通知,后置通知,环绕通知,最终通知,异常通知)
切面:将通知添加到切入点的过程叫切面
目标:代理的目标对象
代理:向目标对象通知时创建的代理对象
Spring AOP的实现
使用配置实现
1.下载AOP相关jar
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
2.使用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
http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--将通知交给spring管理-->
<bean id="myUtil" class="com.ffyc.springdemo.utils.MyUtil" ></bean>
<aop:config>
<!-- 配置切入点 -->
<aop:pointcut id="save" expression="execution(* com.ffyc.springdemo.dao.UserDao.save(..))"/>
<!--配置通知-->
<aop:aspect ref="myUtil">
<aop:before method="writeLog" pointcut-ref="save"></aop:before>
<!--<aop:after method="commit" pointcut-ref="save"></aop:after>-->
<aop:after-returning method="commit" pointcut-ref="save"></aop:after-returning>
<aop:after-throwing method="exception" throwing="e" pointcut-ref="save"></aop:after-throwing>
</aop:aspect>
</aop:config>
</beans>
3.util类
public class MyUtil {
public void writeLog(){
System.out.println("打印日志");
}
public void commit(){
System.out.println("提交事务");
}
public void exception(Exception e){
System.out.println("异常处理"+e);
}
}
4.UserDao
@Repository(value = "userDao")
public class UserDao {
//被增强的方法
public void save(){
System.out.println("保存管理员");
System.out.println(10/0);
}
}
5.测试
打印日志
保存管理员
异常处理java.lang.ArithmeticException: / by zero
如果是使用最终通知,最终结果为:
打印日志
保存管理员
提交事务
异常处理java.lang.ArithmeticException: / by zero
最终通知无论是否出现异常都会执行
环绕通知
util类
public void aroundAdvice(ProceedingJoinPoint point){
try {
System.out.println("前置通知");
//调用业务方法
point.proceed();
System.out.println("后置通知");
} catch (Throwable throwable) {
System.out.println("异常通知"+throwable.getMessage());
throwable.printStackTrace();
}
System.out.println("最终通知");
}
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
http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--将通知交给spring管理-->
<bean id="myUtil" class="com.ffyc.springdemo.utils.MyUtil" ></bean>
<aop:config>
<!-- 配置切入点 -->
<aop:pointcut id="save" expression="execution(* com.ffyc.springdemo.dao.UserDao.save(..))"/>
<!--配置通知-->
<aop:aspect ref="myUtil">
<!--<aop:before method="writeLog" pointcut-ref="save"></aop:before>
<aop:after method="commit" pointcut-ref="save"></aop:after>-->
<!--<aop:after-returning method="commit" pointcut-ref="save"></aop:after-returning>-->
<!--<aop:after-throwing method="exception" throwing="e" pointcut-ref="save"></aop:after-throwing>-->
<aop:around method="aroundAdvice" pointcut-ref="save"></aop:around>
</aop:aspect>
</aop:config>
</beans>
测试结果
前置通知
保存管理员
后置通知
最终通知
使用注解方式实现
在spring.xml中添加配置
<aop:aspectj-autoproxy />
在通知上加上标签注解
@Component //让spring管理生成对象
@Aspect //表明是含有通知的类
public class MyUtil {
@Before("execution(* com.ffyc.springdemo.dao.UserDao.save(..))")
public void writeLog(){
System.out.println("打印日志");
}
@AfterReturning("execution(* com.ffyc.springdemo.dao.UserDao.save(..))")
public void commit(){
System.out.println("提交事务");
}
@AfterThrowing(value = "execution(* com.ffyc.springdemo.dao.UserDao.save(..))",throwing = "e")
public void exception(Exception e){
System.out.println("异常处理"+e.getMessage());
}
@Around("execution(* com.ffyc.springdemo.dao.UserDao.save(..))")
public void aroundAdvice(ProceedingJoinPoint point){
try {
System.out.println("前置通知");
//调用业务方法
point.proceed();
System.out.println("后置通知");
} catch (Throwable throwable) {
System.out.println("异常通知"+throwable.getMessage());
throwable.printStackTrace();
}
System.out.println("最终通知");
}
}
Spring事务
事务可以看成是数据库若干操作组成的一个单元。
由于在数据库操作时,是由多步操作组成的,任何一步都有可能发生异常,并且导致后面的操作无法正确进行,这种情况下需要回退。数据库事务就是为了保证用户的每一步操作都是可靠的,并且每一步都必须正常执行,只要发生异常就会回退到数据库事务还未开始的状态,从而保证数据满足一致性的要求。
编程时事务
需要注入一个事务管理对象TransactionTemplate ,然后在我们代码中需要提交事务或回滚事务时自己写代 码实现.
声明式事务
使用xml
使用注解标签
1.配置事物管理器
<!-- 配置 spring 事务管理类, 并注入数据源 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
2.注解方式
<!-- 开启注解事务管理 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
3.在方法上添加@Transactional标签
@Transactional
public void saveAdmin(){
jdbcTemplate.update("update user set name =? where id=?","猪猪侠",3);
int i=10/0;
jdbcTemplate.update("update user set name =? where id=?","喜羊羊",4);
}
解释:开启事务后,中间出现异常,不会提交数据,所以id为3的数据也不会被修改
@Transactional
用于service层,一个事务逻辑方法中可能会调用多个dao中的方法,有多条sql,所以需要放在同一个事物中。
用法
用于类上,所有方法都会被添加事务管理
用于方法上,方法会在事务管理中进行
不生效情况
1.应用在非public方法上
2.异常被捕获
3.出现编译期异常
默认只对运行期异常进行回滚,可以设置@Transactional(rollbackFor = Exception.class)
4.事物传播行为设置错误
5.数据库殷勤不支持事务(innodb支持事务,myisam不支持事务)
6.同一个类中,使用非代理对象调用一个有事务的方法,导致事务出错
事务传播行为
概念
是spring提供的一个额外的功能,不属于数据库的功能,指的是一个事务方法调用另一个类中的事务方法。
七种事务传播行为(其中4种)
PROPAGATION_REQUIRED(默认)
没有事务就会新建,有事务就会加入
PROPAGATION_SUPPORTS
有事务就加入,没有就按照没有事务的方法进行
PROPAGATION_NEVER
以非事务的方法进行,有事务就会抛出异常
PROPAGATION_REQUIRES_NEW
无论有没有事务,都会新建一个新的事务
Spring中集成Mybatis
1.导入Spring Mabatis结合的jar包
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
2.配置 sqlSessionFactory
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="configLocation" value="mybatis-config.xml"></property>
<property name="mapperLocations" value="com/ff/*Mapper.xml">
</property>
</bean>
3.指定生成接口代理
<bean id="mapperFactory" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.ff.ssm.dao"></property>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory">
</property>
</bean>