Spring5
Posted 秃头专业计算机
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring5相关的知识,希望对你有一定的参考价值。
Spring框架一是基于AspectJ实现AOP操作。AspectJ不是Spring的组成部分,独立AOP框架。基于AspectJ实现AOP操作也是有基于xml配置文件实现和基于注解方式实现两种方法。
使用AspectJ前我们要导包
切入点表达式也要学习一下,这个表达式的作用是让编译器知道我们需要对哪个类里面的哪个方法进行增强。
语法结构:
权限修饰符可以省略,返回类型不可省。
举例1:对com.atguigu.dao.BookDao类里面的add方法进行增强。
权限修饰符省略,*代表返回类型execution(* com.atguigu.dao.Boo.a(..))
举例2:对com.atguigu.dao.BookDao类里面的所有的方法进行增强。
execution(* com.atguigu.dao.BookDao.*(..))
举例3:对com.atguigu.dao包里面所有类,类里面所有方法进行增强
execution(* com.atguigu.dao.*.*(..))
基于注解完成AOP操作
创建被增强类
//被增强类
@Component
public class User {
public void add(){
//int i=12/0;
System.out.println("add.....");
}
}
创建增强类
//增强类
@Component//通过注解创建对象
@Aspect
public class UserProxy {
//前置通知
@Before(value="execution(* com.DY.Spring5.annoaop.User.add(..))")
public void before(){
System.out.println("before.....");
}
//最终通知
@After(value="execution(* com.DY.Spring5.annoaop.User.add(..))")
public void after(){
System.out.println("after.......");
}
//后置通知
@AfterReturning(value="execution(* com.DY.Spring5.annoaop.User.add(..))")
public void afterReturning(){
System.out.println("afterReturn.......");
}
//异常通知,被增强的方法有异常执行
@AfterThrowing(value="execution(* com.DY.Spring5.annoaop.User.add(..))")
public void afterThrowing(){
System.out.println("afterThrowing.......");
}
//环绕通知,方法前和方法后都执行
@Around(value="execution(* com.DY.Spring5.annoaop.User.add(..))")
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕之前.....");
//执行被增强的方法
proceedingJoinPoint.proceed();
System.out.println("环绕之后.....");
}
}
在xml文件中配置组件扫描,生成代理对象
<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 http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--开启注解扫描-->
<context:component-scan base-package="com.DY.Spring5.annoaop"></context:component-scan>
<!--开启Aspect生成代理对象-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
这一步我们也可以用配置类来完成
public class ConfigAop {
}
写两个测试类
从增强类中可以看出切入点表达式都是一样的。所以我们可以将它提取出来
//相同切入点抽取
@Pointcut(value="execution(* com.DY.Spring5.annoaop.User.add(..))")
public void point(){
}
然后使用即可
如果有多个增强类对同一个方法进行增强,我们需要设置增强类优先级。我们可以在增强类上面添加注解@Order(数字类型的值),值从0开始,越小优先级越高。
基于xml文件实现AOP
首先被增强类和增强类各写一个
然后编写xml文件
<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 http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--创建对象-->
<bean id="book" class="aopxml.Book"></bean>
<bean id="bookProxy" class="aopxml.BookProxy"></bean>
<!--配置aop增强-->
<aop:config>
<!--切入点-->
<aop:pointcut id="p" expression="execution(* aopxml.Book.buy(..))"/>
<!--配置切面-->
<aop:aspect ref="bookProxy">
<!--增强作用在具体的方法上-->
<aop:before method="before" pointcut-ref="p"/>
</aop:aspect>
</aop:config>
</beans>
测试即可
public void test1(){
ApplicationContext context=new ClassPathXmlApplicationContext("bean2.xml");
Book book = context.getBean("book", Book.class);
book.buy();
}
事务
事务是数据库操作最基本的单元,逻辑上的一组操作,要么都成功,如果有一个失败就所有操作都失败。事务有四个特性(ACID)包括原子性、一致性、隔离性、持久性。
在Spring中进行事务管理操作有两种方式:编程式事务管理和声明式事务管理。编程式事务管理很少用,它会造成代码冗余。声明式事务管理又是有两种方法:基于注解方式和基于xml配置文件方式
在Spring进行声明式事务管理,底层使用AOP原理。还有几个参数需要我们了解一下:
(1)传播行为(propagation)
(2)隔离级别(isolation)
事务有个特性叫隔离性,这是因为多事务操作之间不考虑隔离性会产生很多问题。有三个问题:脏读、不可重复读、幻读
脏读:一个事务读取到另一个事务未提交的数据
不可重复读:一个事务读取到另一个已提交事务修改的数据
幻读:一个事务读取到另一个已提交事务增加的数据
(3)超时时间(timeout)
事务需要在一定时间内进行提交,如果不提交就会进行回滚。默认值是-1,代表没有超时时间,永不超时。单位是秒
(4)是否只读(readOnly)
默认值是false,表示可以进行增删改查操作。readOnly值设为true后,只能查询
(5)回滚(rollbackFor)
设置出现哪些异常进行事务回滚
(6)不回滚(norollbackFor)
设置出现哪些异常不进行事务回滚
使用注解方式创建事务
创建一个Dao接口,实现这个接口
public class UserDaoImpl implements UserDao {
private JdbcTemplate jdbcTemplate;
//lucy转账100给mary
//少钱
public void reduceMoney() {
String sql = "update t_account set money=money-? where username=?";
jdbcTemplate.update(sql,100,"lucy");
}
//多钱
public void addMoney() {
String sql = "update t_account set money=money+? where username=?";
jdbcTemplate.update(sql,100,"mary");
}
}
xml配置
<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 http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 组件扫描 -->
<context:component-scan base-package="Spring5"></context:component-scan>
<!-- 数据库连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
destroy-method="close">
<property name="url" value="jdbc:mysql:///user_db" />
<property name="username" value="root" />
<property name="password" value="root" />
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
</bean>
<!-- JdbcTemplate对象 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!--注入dataSource-->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--创建事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入数据源-->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--开启事务注解-->
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
</beans>
我们也可以用配置类替换xml配置文件
//配置类
"spring5") //组件扫描 (basePackages =
//开启事务
public class TxConfig {
//创建数据库连接池
public DruidDataSource getDruidDataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql:///user_db");
dataSource.setUsername("root");
dataSource.setPassword("root");
return dataSource;
}
//创建JdbcTemplate对象
public JdbcTemplate getJdbcTemplate(DataSource dataSource) {
//到ioc容器中根据类型找到dataSource
JdbcTemplate jdbcTemplate = new JdbcTemplate();
//注入dataSource
jdbcTemplate.setDataSource(dataSource);
return jdbcTemplate;
}
}
然后在类或方法上加上@Transactional,在类上加代表该类所有方法都添加事务,只在方法上添加就只为这个方法添加事务
false,timeout = -1,propagation = Propagation.REQUIRED,isolation = Isolation.REPEATABLE_READ) (readOnly =
public class UserService {
//注入UserDao
private UserDao userDao;
//转账的方法
public void accountMoney() {
userDao.reduceMoney();
//模拟异常
//int i = 10/0;
userDao.addMoney();
}
}
测试
public void testAccount1() {
ApplicationContext context =new ClassPathXmlApplicationContext("bean1.xml");
UserService userService = context.getBean("userService", UserService.class);
userService.accountMoney();
}
//配置类测试方法
public void testAccount2() {
ApplicationContext context =new AnnotationConfigApplicationContext(TxConfig.class);
UserService userService = context.getBean("userService", UserService.class);
userService.accountMoney();
}
使用xml配置文件创建事务就不写了,用到再看看
以上是关于Spring5的主要内容,如果未能解决你的问题,请参考以下文章