Spring5
|字数总计:6.9k|阅读时长:32分钟|阅读量:
入门案例
引入beans、context、core、expression依赖
创建类
1 2 3 4 5
| public class User { public void add(){ System.out.println("User add method"); } }
|
spring配置文件配置创建的对象
1
| <bean id="user" class="com.cuc.spring5.User" />
|
调用类中方法
1 2 3 4 5 6 7 8
| @Test public void test(){ ApplicationContext context = new ClassPathXmlApplicationContext("com/cuc/spring5/aop/bean.xml"); User user = context.getBean("user",User.class); user.add(); }
|
IOC容器
什么是IOC?
控制反转
,把对象创建和对象之间的调用过程,交给Spring进行管理,降低耦合度。
原始方式直接调用某个类中方法,如果被调用类方法名改变或路径等发生改变,则调用的路径和方法名同样得改变。所以耦合度高。
而IOC则使用xml解析、工厂模式、反射完成这一过程,IOC容器底层就是对象工厂,对对象进行统一管理。
IOC接口(BeanFactory)
BeanFactory
- 是Spring内部使用接口,一般不使用。
- 加载配置文件时不会创建对象,获取时才创建。
1 2
| BeanFactory context = new ClassPathXmlApplicationContext("com/cuc/spring5/aop/bean.xml");
|
ApplicationContext
- BeanFactory的子接口,提供更多更强大的功能。
- 加载配置文件时就会把在配置文件中的对象进行创建。
1 2 3 4
| ApplicationContext context = new ClassPathXmlApplicationContext("com/cuc/spring5/aop/bean.xml");
ApplicationContext context = new FileSystemXmlApplicationContext("D:/IDEA/workSpace_1.2/Spring5/spring5_AOP/src/com/cuc/spring/aop/bean.xml");
|
IOC操作Bean管理
- Bean管理即
创建对象
和注入属性
- 基于
xml配置文件
和注解
两种方式实现Bean管理
基于xml方式
创建对象
1 2 3
| <bean id="user" class="com.cuc.spring5.User" /> <bean id="userService" class="com.cuc.spring5.UserService" /> <bean id="userDao" class="com.cuc.spring5.UserDaoImp" />
|
属性 |
解释 |
id |
唯一标识(自己取) |
class |
全路径或类路径 |
等等 |
… … |
注入属性
注入方式
1)set方式注入
1 2 3 4 5 6 7 8 9 10 11 12
| <bean id="book" class="com.cuc.spring5.Book"> <property name="bname" value="三体" /> <property name="address"> <null /> </property> <property name="address" value="<>南京" /> <property name="address"> <value><![CDATA[<>南京]]></value> </property> </bean>
|
2)有参构造注入
1 2 3
| <bean id="book" class="com.cuc.spring5.Book"> <constructor-arg name="bname" value="三体" /> </bean>
|
3)p名称空间注入(了解)
1 2 3 4 5 6
| private UserDao userDao;
public void setUserDao(UserDao userDao) { this.userDao = userDao; }
|
1 2 3 4 5
| <bean id="userService" class="com.cuc.spring5.UserService"> <property name="userDao" ref="userDaoImp"></property> </bean>
<bean id="userDaoImp" class="com.cuc.spring5.UserDaoImp" />
|
1 2 3 4 5 6 7 8
| public class Dept { private String name;
public void setName(String name) { this.name = name; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class Emp { private String name; private String sex; private Dept dept; public void setDept(Dept dept) { this.dept = dept; } public void setName(String name) { this.name = name; } public void setSex(String sex) { this.sex = sex; } }
|
1 2 3 4 5 6 7 8 9 10 11 12
| <bean id="emp" class="com.cuc.spring5.Emp"> <property name="name" value="Lucy"></property> <property name="sex" value="女"></property> <property name="dept"> <bean id="dept" class="com.cuc.spring5.Dept"> <property name="name" value="安保部"></property> </bean> </property> </bean>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <bean id="emp" class="com.cuc.spring5.Emp"> <property name="name" value="Lucy"></property> <property name="sex" value="女"></property> <property name="dept" ref="dept"></property> <property name="dept.name" value="技术部"></property> </bean> <bean id="dept" class="com.cuc.spring5.Dept"> <property name="name" value="财务部"></property> </bean>
|
注入集合类型属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| <bean id="stu" class="com.cuc.spring5.collectiontype.Student"> <property name="courses"> <array> <value>Java</value> <value>数据库</value> </array> </property> <property name="list"> <list> <value>111</value> <value>222</value> </list> </property> <property name="map"> <map> <entry key="JAVA" value="java"></entry> <entry key="PHP" value="php"></entry> </map> </property> <property name="set"> <set> <value>MySQL</value> <value>Redis</value> </set> </property>
<property name="courseList"> <list> <ref bean="course1"></ref> <ref bean="course2"></ref> </list> </property> </bean>
<bean id="course1" class="com.cuc.spring5.collectiontype.Course"> <property name="name" value="Spring5框架"></property> </bean> <bean id="course2" class="com.cuc.spring5.collectiontype.Course"> <property name="name" value="Mybatis框架"></property> </bean>
|
1 2 3 4 5 6 7 8 9 10 11
|
<util:list id="bookList"> <value>易筋经</value> <value>九阴真经</value> <value>九阳神功</value> </util:list> <bean id="book" class="com.cuc.spring5.collectiontype.Book"> <property name="list" ref="bookList"></property> </bean>
|
工厂Bean
Spring有两种类型bean:普通bean定义什么类型就返回什么类型,以上所有bean都是普通bean,工厂bean(FactoryBean)定义类型和返回类型可以不一样。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| package com.cuc.spring5.factorybean;
import com.cuc.spring5.collectiontype.Course; import org.springframework.beans.factory.FactoryBean;
public class MyBean implements FactoryBean<Course> {
@Override public Course getObject() throws Exception { Course course = new Course(); course.setName("工厂"); return course; } }
|
1
| <bean id="myBean" class="com.cuc.spring5.factorybean.MyBean"></bean>
|
Bean的作用域
- 设置创建bean实例是单实例还是多实例。
- 默认情况下创建的是单实例对象。
1 2 3 4 5
|
<bean id="book" class="com.cuc.spring5.collectiontype.Book" scope="prototype"> <property name="list" ref="bookList"></property> </bean>
|
Bean生命周期
对象创建到销毁过程。
- 构造器创建bean实例(有参无参等)
- 为bean属性设置值和对其他bean的引用(调用set方法等)
- 初始化前将bean实例传给bean后置处理器
- 调用bean的初始化方法(需要配置初始化方法)
- 初始化后将bean实例传给bean后置处理器
- 使用bean(获取到对象)
- 容器关闭时,调用bean的销毁方法(需要配置销毁方法)
1 2 3 4 5 6 7
| <bean id="order" class="com.cuc.spring5.bean.Order" init-method="init" destroy-method="destroy"> <property name="name" value="手机"></property> </bean>
<bean id="myBeanPost" class="com.cuc.spring5.bean.MyBeanPost"></bean>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| package com.cuc.spring5.bean;
public class Order { private String name;
public Order() { System.out.println("第一步,执行无参构造创建bean实例"); }
public void setName(String name) { this.name = name; System.out.println("第二步,调用set方法设置属性值"); }
public void init(){ System.out.println("第三步,执行初始化方法"); }
public void destroy(){ System.out.println("第五步,执行销毁方法"); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class MyBeanPost implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("初始化之前执行的方法"); return bean; }
@Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("初始化之后执行的方法"); return bean; } }
|
1 2 3 4 5 6 7 8 9
| @Test public void test(){ ApplicationContext context = new ClassPathXmlApplicationContext("com/cuc/spring5/bean/bean.xml"); Order order = context.getBean("order",Order.class); System.out.println("第四步,获取创建bean实例对象"); System.out.println(order); ((ClassPathXmlApplicationContext)(context)).close(); }
|
xml自动装配
之前都是手动装配属性,自动装配会根据属性名称或类型自动完成属性值注入。
1 2 3 4 5 6 7 8 9 10
|
<bean id="emp" class="com.cuc.spring5.autowire.Emp" autowire="byName"> </bean> <bean id="dept" class="com.cuc.spring5.autowire.Dept"></bean>
|
外部属性文件
以数据库连接池为例,先引入druid依赖
1 2 3 4
| prop.driverClass = com.mysql.jdbc.Driver prop.url = jdbc:mysql://localhost:3306/userDb prop.username = root prop.password = root
|
1 2 3 4 5 6 7 8 9 10 11 12 13
|
<context:property-placeholder location="classpath:jdbc.properties" />
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="${prop.driverClass}" /> <property name="url" value="${prop.url}" /> <property name="username" value="${prop.username}" /> <property name="password" value="${prop.password}" /> </bean>
|
基于注解方式
依赖:aop
格式:@注解名称(属性名称=属性值,…)
目的:简化xml配置
创建对象
@Component
:一般用于普通类上
@Service
:一般用于业务层
@Controller
:一般用于web层
@repository
:一般用于dao或持久层上
实际上这些注解可以混用,没有固定哪个层必须用哪个注解。
1 2 3 4
|
<context:component-scan base-package="com.cuc.spring5.a,com.cuc.spring5.b" />
|
细节:
1 2 3 4 5 6 7
|
<context:component-scan base-package="com.cuc.spring5.a" use-default-filters="false"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan>
|
1 2 3 4 5 6
|
<context:component-scan base-package="com.cuc.spring5.a"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan>
|
1 2 3
| @Service(value = "userService") public class UserService { ... }
|
属性注入
@AutoWired
:根据属性类型自动装配
@Qualifier
:根据属性名称进行注入
@Resource
:既可以根据类型也可以根据名称注入
@Value
:注入普通类型属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| @Value("张三") private String name;
@Autowired private UserDao userDao;
@Resource private StudentDao studentDao;
@Resource (name = "studentDaoImp1") private StudentDao studentDao2;
@Autowired @Qualifier(value = "studentDaoImp1") private StudentDao studentDao;
|
完全注解开发
即不使用xml,此时xml里只有(注解扫描)。
1)创建配置类,替代xml配置文件
1 2 3 4 5
| @Configurable @ComponentScan(basePackages = {"com.cuc.spring5.c"}) public class SpringConfig {
}
|
2)编写测试类
1 2 3 4 5 6 7
| @Test public void test(){ ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); BookService bookService = context.getBean("bookService", BookService.class); bookService.add(); }
|
AOP
什么是AOP?
面向切面编程
,利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高开发效率。
通俗描述:不通过修改源代码,在主干功能里添加新功能。
底层原理
使用动态代理,并且有两种情况。
1)有接口情况,使用JDK动态代理
创建接口实现类代理对象,增强类的方法。
底层代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| public class JDKProxy { public static void main(String[] args) {
Class[] interfaces = {UserDao.class}; UserDao userDao = new UserDaoImp();
UserDao dao = (UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao)); int result = dao.add(1,2); System.out.println("result:"+result); } }
class UserDaoProxy implements InvocationHandler{
private Object obj; public UserDaoProxy(Object obj){ this.obj = obj; }
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(method.getName()+"方法之前执行,传递过来的参数为:"+ Arrays.toString(args));
Object res = method.invoke(obj,args);
System.out.println("方法之后执行");
return res; } }
|
2)无接口情况,使用CGLIB动态代理
创建子类的代理对象,增强类的方法。
操作术语
连接点
类里面哪些方法可以被增强,这些方法称为连接点。
切入点
实际被增强的方法,称为切入点。
通知(增强)
实际增强的逻辑部分称为通知(增强)
切面
是动作,把通知应用到切入点的过程。
准备工作
1)Spring框架一般基于AspectJ实现AOP操作
2)两种实现方式:
- 基于xml配置文件
- 基于注解
3)依赖:aop、aspects、cglib、aopalliance、aspectj.weaver
4)切入点表达式
作用:知道对哪个类里面的哪个方法进行增强
语法结构:execution([权限修饰符][返回类型][类全路径].[方法名称]([参数列表]))
举例:
1 2
| # 任意修饰符,返回类型可不写,..代表参数列表。注意*后有空格 execution(* com.cuc.dao.BookDao.add(..))
|
1 2
| # 对类中所有方法进行增强 execution(* com.cuc.dao.BookDao.*(..))
|
1 2
| # 对所有类中所有方法进行增强 execution(* com.cuc.dao.*.*(..))
|
AspectJ注解
1 2 3 4 5 6 7
| @Component public class User { public void add(){ System.out.println("User add method"); } }
|
1 2 3 4 5 6 7 8 9 10 11
| @Component @Aspect @Order(1) public class PersonProxy {
@Before(value = "execution(* com.cuc.spring5.aop.User.add(..))") public void before(){ System.out.println("PersonProxy before method"); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| @Component @Aspect @Order(2) public class UserProxy { @Pointcut(value = "execution(* com.cuc.spring5.aop.User.add(..))") public void point(){}
@Before(value = "point()") public void before(){ System.out.println("UserProxy before method"); }
@AfterReturning(value = "point()") public void afterReturning(){ System.out.println("UserProxy afterReturning method"); }
@After(value = "point()") public void after(){ System.out.println("UserProxy after method"); }
@AfterThrowing(value = "point()") public void afterThrowing(){ System.out.println("UserProxy afterThrowing method"); }
@Around(value = "point()") public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{ System.out.println("环绕前");
proceedingJoinPoint.proceed();
System.out.println("环绕后"); }
}
|
1 2 3 4 5 6
| <context:component-scan base-package="com.cuc.spring5.aop" />
<aop:aspectj-autoproxy />
|
完全注解开发
1 2 3 4 5 6 7
| @Configurable @ComponentScan(basePackages = {"com.cuc.spring5"}) @EnableAspectJAutoProxy(proxyTargetClass = true) public class AopConfig {
}
|
AspectJ配置文件
- 创建两个类,增强类和增强类,创建方法
- 在spring配置文件中创建两个类对象
- 在spring配置文件中配置切入点
1 2 3 4 5 6
| public class Book { public void buy(){ System.out.println("Book buy method"); } }
|
1 2 3 4 5 6
| public class BookProxy { public void before(){ System.out.println("BookProxy before method"); } }
|
1 2 3 4 5 6 7 8 9 10 11 12
| <bean id="book" class="com.cuc.spring5.aopXml.Book"/> <bean id="bookProxy" class="com.cuc.spring5.aopXml.BookProxy"/>
<aop:config> <aop:pointcut id="p" expression="execution(* com.cuc.spring5.aopXml.Book.buy(..))"/> <aop:aspect ref="bookProxy"> <aop:before method="before" pointcut-ref="p"/> </aop:aspect> </aop:config>
|
JdbcTemplate
概述和准备
概述:Spring框架对JDBC进行封装,使用JdbcTemplate方便实现对数据库的操作。
准备:
1)依赖:druid、mysql-connector、spring-jdbc、spring-orm(整合mybatis需要,这里不需要)
2)Spring配置文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <context:component-scan base-package="com.cuc.spring5"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close"> <property name="url" value="jdbc:mysql:///user_db?characterEncoding=utf-8" /> <property name="username" value="root" /> <property name="password" value="root" /> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> </bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"/> </bean>
|
3)注入JdbcTemplate对象
1 2 3 4 5 6 7 8
| @Repository public class UserDaoImp implements UserDao {
@Autowired private JdbcTemplate jdbcTemplate;
}
|
功能实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
| @Repository public class UserDaoImp implements UserDao {
@Autowired private JdbcTemplate jdbcTemplate;
@Override public void add(User user) { String sql = "insert into t_user set username=?,status=?"; Object[] args = {user.getUsername(),user.getStatus()};
int update = jdbcTemplate.update(sql,args);
System.out.println(update); }
@Override public void update(User user) { String sql = "update t_user set username=?,status=? where id=?"; Object[] args = {user.getUsername(),user.getStatus(),user.getId()}; int res = jdbcTemplate.update(sql,args); System.out.println(res); }
@Override public void delete(int id) { String sql = "delete from t_user where id=?"; int update = jdbcTemplate.update(sql,id); System.out.println(update); }
@Override public int findCount() { String sql = "select count(*) from t_user"; Integer count = jdbcTemplate.queryForObject(sql,Integer.class); return count; }
@Override public User findOne(int id) { String sql = "select * from t_user where id=?"; User user = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<User>(User.class), id); return user; }
@Override public List<User> findAll() { String sql = "select * from t_user"; List<User> userList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(User.class)); return userList; }
@Override public void batchAdd(List<Object[]> batchArgs) { String sql = "insert into t_user set username=?,status=?"; int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs); System.out.println(Arrays.toString(ints)); }
@Override public void batchUpdate(List<Object[]> batchArgs) { String sql = "update t_user set username=?,status=? where id=?"; int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs); System.out.println(Arrays.toString(ints)); }
@Override public void batchDelete(List<Object[]> batchArgs) { String sql = "delete from t_user where id=?"; int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs); System.out.println(Arrays.toString(ints)); } }
|
事务
事务概述以及四个特性(ACID)等在MySQL速通文章讲了。
准备
1)依赖:spring-tx
2)Spring配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <context:component-scan base-package="com.cuc.spring5"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close"> <property name="url" value="jdbc:mysql:///user_db?characterEncoding=utf-8" /> <property name="username" value="root" /> <property name="password" value="root" /> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> </bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"/> </bean>
|
3)创建service以及dao的方法
1 2 3 4 5 6 7 8 9 10 11 12 13
| @Service public class UserService {
@Autowired private UserDao userDao;
public void accountMoney(){ userDao.reduceMoney(); userDao.addMoney(); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| @Repository public class UserDaoImp implements UserDao {
@Autowired private JdbcTemplate jdbcTemplate;
@Override public void addMoney() { String sql = "update t_account set money=money+? where username=?"; jdbcTemplate.update(sql,100,"marry"); }
@Override public void reduceMoney() { String sql = "update t_account set money=money-? where username=?"; jdbcTemplate.update(sql,100,"lucy"); } }
|
事务管理介绍
- 通常将事务添加到service中
- Spring事务管理操作方式:
编程式事务管理
和声明式事务管理
- 声明式事务管理:
基于注解
、基于xml配置文件
- 在Spring进行声明式事务管理,底层使用AOP
编程式事务管理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| @Service public class UserService {
@Autowired private UserDao userDao;
public void accountMoney(){
try {
userDao.reduceMoney();
int i = 10/0;
userDao.addMoney();
}catch (Exception e){ } } }
|
声明式事务管理(注解)
1 2 3 4 5 6 7 8
| <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean>
<tx:annotation-driven transaction-manager="transactionManager" />
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| @Service public class UserService {
@Autowired private UserDao userDao; @Transactional public void accountMoney(){
userDao.reduceMoney();
int i = 10/0;
userDao.addMoney(); } }
|
事务参数
1
| @Transactional(propagation=Propagation.REQUIRED,isolation=Isolation.REPEATABLE_READ,timeout=-1,readOnly=false,)
|
参数 |
解释 |
propagation |
事务传播行为 常用(required、required_new、supports等) |
isolation |
事务隔离级别(mysql学过了) |
timeout |
超时时间(秒单位),超时不提交则回滚 |
readOnly |
是否只读,就是只能查询 |
rollbackFor |
回滚,设置哪些异常进行回滚 |
noRollbackFor |
不回滚,设置哪些异常不进行回滚 |
required
:如果有事务在运行,当前的方法就在这个事务内运行,否则,就启动一个新的事务,并在自己的事务内运行。
required_new
:当前的方法必须启动新事务,并在自己的事务内运行,如果有事务正在运行,应该将它挂起。
supports
:如果有事务在运行,当前方法就在这个事务中运行,否则它可以不运行在事务中。
完全注解开发
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
|
@Configurable @ComponentScan(basePackages = "com.cuc.spring5") @EnableTransactionManagement public class TxConfig {
@Bean public DruidDataSource getDruidDataSource(){ DruidDataSource dataSource = new DruidDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql:///user_db?characterEncoding=utf-8"); dataSource.setUsername("root"); dataSource.setPassword("root"); return dataSource; }
@Bean public JdbcTemplate getJdbcTemplate(DataSource dataSource){ JdbcTemplate jdbcTemplate = new JdbcTemplate(); jdbcTemplate.setDataSource(dataSource); return jdbcTemplate; }
@Bean public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource){ DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(); transactionManager.setDataSource(dataSource); return transactionManager; } }
|
声明式事务管理(xml)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean>
<tx:advice id="txAdvice"> <tx:attributes> <tx:method name="accountMoney" progagation="REQUIRED"/> </tx:attributes> </tx:advice>
<aop:config> <aop:pointcut id="pt" expression="execution(* com.cuc.spring5.service.UserService.accountMoney(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="pt" /> </aop:config>
|
Spring5新功能
整合日志框架
1)依赖:slf4j-api、log4j-slf4j-impl、log4j-core、log4j-api
2)创建log4j2.xml配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <?xml version="1.0" encoding="UTF-8"?>
<configuration status="INFO"> <appenders> <console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> </console> </appenders> <loggers> <root level="info"> <appender-ref ref="Console"/> </root> </loggers> </configuration>
|
3)可以手动输出日志
1 2 3 4 5 6 7 8 9 10
| public class UserLog { private static final Logger log = LoggerFactory.getLogger(UserLog.class);
public static void main(String[] args) { log.info("info信息"); log.warn("warn信息"); } }
|
Nullable注解
@Nullable注解可以使用在方法、属性、参数上面,表示方法返回值、属性值、参数值可以为空。
1 2 3 4 5 6 7
| @Nullable String getId();
@Nullable private String name;
String getId(@Nullable String name);
|
函数式注册对象
1 2 3 4 5 6 7 8 9 10 11 12
| @Test public void genericApplicationContextTest(){ GenericApplicationContext context = new GenericApplicationContext(); context.refresh(); context.registerBean(Book.class,()->new Book()); Book book = (Book) context.getBean("com.cuc.spring5.test.Book"); System.out.println(book); }
|
整合JUnit5单元测试框架
依赖:spring-test
1 2 3 4 5 6 7 8
| @Test public void test(){ ApplicationContext context = new ClassPathXmlApplicationContext("com/cuc/spring5/aop/bean.xml"); User user = context.getBean("user",User.class); user.add(); }
|
需要引入JUnit4依赖:junit、hamcrest-core
1 2 3 4 5 6 7 8 9 10
| @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:bean.xml") public class JTest4 { @Autowired private UserService userService; @Test public void test(){ userService.accountMoney(); } }
|
依赖:
1 2 3 4 5 6 7 8 9 10 11 12
|
@SpringJUnitConfig(locations = "classpath:bean.xml") public class JTest5 { @Autowired private UserService userService; @Test public void test(){ userService.accountMoney(); } }
|
Webflux
还没学