1、Spring是一个开源免费且轻量级的框架 , 非侵入式的 .
2、控制反转 IoC , 面向切面 Aop
3 、对事物的支持 , 对框架的支持
一句话概括:
Spring 是一个轻量级的控制反转(IOC),面向切面(AOP)的框架
Sprig官网:Spring.io 去到官网即可下载
GA:稳定通用版本、SNAPSHOT : 快照版本
Spring历史版本下载地址:https://repo.spring.io/ui/native/release/org/springframework/spring
Spring5 Runtime 结构示意图
Core 就是我们的Spring的核心 ,如下就是我们如果使用Spring必须导入的Jar包 ,commons-logging
必须但不属于Spring;
IOC就是通过 工厂模式 + 反射 + XML解析 实现
<!--第一步:配置XML文件,配置创建对象-->
<bean id = dao class = "com.sqx.UserDao"></bean>
//第二步就是,通过解析配置文件,创建工厂对象,进而创建对象!
class UserDaoFactory{
public static UserDao getDao(){
String CalssVlaue = class属性值 // 1、进行xml解析
Calss clazz = Class.forName(CalssVlaue) ; // 2、通过反射创建对象
return (UserDao)clazz.newInstance() ;
}
}
我们通常所说的IOC容器本质上就是一个对象工厂,而我们的Spring提供IOC容器实现的两种方式(也就是两个接口,如下)
1、BeanFactory : IOC容器的基本实现,是Spring内部使用的接口,不提供给开发人员使用 ;
2、ApplicationContext : BeanFactory的子接口提供更多更强大的功能,一般由开发人员进行使用 ; 【推荐】
ApplicationContext接口的实现类
查看ApplicationContext接口的继承结构
区别:
我们通过Spring提供的两种接口 BeanFactory 和 ApplicationContext ,以及其具体的实现类通过读取我们的xml文件创建我们的对象工厂,也就是IOC容器!接下来我们的IOC容器通过反射的方式创建出对象!
IOC有两种创建对象的方式: 方式一:无参构造 + set注入属性值 ,方式二:有参构造
<?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.kuang.pojo.User"> <!--可以理解为 User user = new User-->
<property name="name" value="kuangshen"/>
</bean>
<bean id="ServiceImpl" class="com.sqx.service.impl.UserServiceImpl">
<!--注意: 这里的name并不是属性 , 而是set方法后面的那部分 , 首字母小写-->
<!--引用另外一个bean , 不是用value 而是用 ref-->
<property name="userDao" ref="OracleImpl"/>
</bean>
</beans>
<!-- 第一种根据index参数下标设置 -->
<bean id="userT" class="com.sqx.pojo.UserT">
<!-- index指构造方法 , 下标从0开始 -->
<constructor-arg index="0" value="songqixiang"/>
</bean>
<!-- 第二种根据参数名字设置 -->
<bean id="userT" class="com.sqx.pojo.UserT">
<!-- name指参数名 -->
<constructor-arg name="name" value="songqixiang"/>
</bean>
<!-- 第三种根据参数类型设置 -->
<bean id="userT" class="com.sqx.pojo.UserT">
<constructor-arg type="java.lang.String" value="songqixiang"/>
</bean>
DI : 依赖注入(Dependency Injection)也称属性注入 ;
方式一 :使用set方法进行注入 : 我们使用无参构造创建对象,这个类就会通过set方法注入属性,完成对象的创建!
方式二 :使用有参构造进行注入:我们使用有参构造创建的对象对通过构造方法赋值 !
扩展 :p命名和c命名注入
1、P命名空间注入 : 需要在头文件中加入约束文件
导入约束 : xmlns:p="http://www.springframework.org/schema/p"
<!--P(属性: properties)命名空间 , 属性依然要设置set方法-->
<bean id="user" class="com.sqx.pojo.User" p:name="狂神" p:age="18"/>
2、c 命名空间注入 : 需要在头文件中加入约束文件
导入约束 : xmlns:c="http://www.springframework.org/schema/c"
<!--C(构造: Constructor)命名空间 , 属性依然要设置set方法-->
<bean id="user" class="com.sqx.pojo.User" c:name="狂神" c:age="18"/>
其实p命名注入本质上就是我们的set注入,c命名注入本质上则是我们的构造器注入
向我们的对象属性中注入空值
<bean id="user" class="com.sqx.pojo.User">
<property name="name" value="songqixiang"/>
<property name="address" > <null/> </property> <!--User对象的adderss属性注入空值-->
</bean>
属性值中注入特殊符号
<bean id="user" class="com.sqx.pojo.User">
<property name="name" value="songqixiang"/>
<property name="address" value="<<南京>>"/> <!--User对象的adderss属性注入特殊值,<>是特殊符号,导致报错-->
<!--解决办法1:<>转义-->
<property name="address" value="<><<南京>>"/>
<!--解决方法2:将特殊内容写在CDATA中去-->
<property name="address">
<value>
<![CDATA[<<南京>>]]>
</value>
</property>
</bean>
IOC创建的Bean分为两种:FactoryBean(工厂Bean) 和 Bean(普通Bean)
FactoryBean 和 Bean的区别:
<bean id="user" class="com.sqx.pojo.User">
<property name="name" value="songqixiang"/> <!--普通Bean的创建-->
</bean>
<!--FactoryBean的创建 : 1、让我门的MyBean实现FactoryBean接口,2、并且重写接口中方法-->
<bean id="myBean" class="com.sqx.factoryBean.MyBean"> </bean>
myBean实现FactoryBean
public class MyBean implements FactoryBean<User> {
/***
* 定义返回Bean的类型
* @return
* @throws Exception
*/
public User getObject() throws Exception { //返回类型为一个User,标识这个工厂类只生产User
User user = new User();
user.setName("sqx") ;
return user;
}
public Class<?> getObjectType() {
return null;
}
public boolean isSingleton() { //返回值类型
return false;
}
}
通过IOC获取这个MyBean,进行测试 :
@Test
public void testFactoryBean(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
User myBean = (User) context.getBean("myBean");
System.out.println(myBean); // com.sqx.pojo.User@64f6106c 发现MyBean获取的是一个User类
}
在Spring里面,设置创建Bean实例是单实例(默认)还是多实例
通过标签中scop属性设置我们Bean的作用域,如下:
区别:
关于singleton和prototype还存在一个区别就是:
当我们的scop=singleton
的时候我们的对象是会在ApplicaitionContex加载xml文件的时候创建的;
当我们的scop=prototype
的时候我们的对象不是在加载xml的时候创建的,而是在调用getBean方法的时候创建的!
也就是我们Bean对象从创建到销毁的过程
1、编写一个Orders类,为其设置set方法,
public class Orders {
private String oname ;
public Orders() {
System.out.println("第一步:执行无参构造,构建bean的实例");
}
public void setOname(String oname) {
this.oname = oname;
System.out.println("第二步:执行set方法进行属性注入");
}
//创建一个执行的初始化方法
public void initMethod(){
System.out.println("第三步:执行我们bean的初始化方法");
}
//创建一个bean销毁时执行的方法(只有当对象销毁的时候才会调用)
public void destroyMethod(){
System.out.println("第五步:执行我们bean的销毁方法");
}
}
2、编写xml文件
<bean id="orders" class="com.sqx.bean.Orders" init-method="initMethod" destroy-method="destroyMethod">
<property name="oname" value="手机"></property>
</bean>
3、编写测试方法,对生命周期进行测试
@Test
public void testBean(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans1.xml") ;
Orders orders = (Orders)context.getBean("orders");
System.out.println("第四步:获取我们的创建的bean实例");
System.out.println(orders);
//让我们bean实例销毁(IOC容器关闭,其中的实例销毁)
((ClassPathXmlApplicationContext) context).close();
}
4、查看测试结果
上述的五步就是我们Bean的生命周期,但是是不考虑后置处理器的情况下是五步,如果考虑的话是如下七步:
考虑后置处理器
我们只需创建一个后置处理器,然后将处理器注入到我们的IOC容器当中即可,我们的Spring会默认的将其加在IOC容器中的所有bean!
1、创建后置处理器:创建一个类实现BeanPostProcessor接口,并重写两个方法
public class MyBeanPost implements BeanPostProcessor {
/**
* bean初始化之前执行的方法!(第三步)
* @param bean
* @param beanName
* @return
* @throws BeansException
*/
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("bean初始化之前执行的方法!");
return bean;
}
/***
* bean初始化之后执行的方法!(第五步骤)
* @param bean
* @param beanName
* @return
* @throws BeansException
*/
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("bean初始化之后执行的方法!");
return bean;
}
}
2、注入到我们的IOC容器
<!--配置后置处理器-->
<bean id="myBeanPost" class="com.sqx.bean.MyBeanPost"></bean>
测试添加后置处理器的执行结果
可以看到我们的Bean的生命周期就变为七步了!
我们上边说的是如何将对象注入到IOC容器当中,自动装配简单来说就是自动的从IOC容器中去取对象!
组件扫描和自动装配组合发挥巨大威力,使得显示的配置降低到最少。
推荐不使用xml配置开启自动装配, 而是使用注解,无论是xml还是注解开启自动装配,都需要先了解一下自动装配的类型:byName 和 byType 这两类,自动装配的类型就是我们从IOC容器中按照什么找到我们所需的bean
自动装配的类型分为两种:byName 和 byType 这两类
知道了自动装配类型的区别,那么就可以学习开启自动装配的两种方式了,如下 :
开启自动装配的方式有,xml配置 和 注解 两种方式!
前提:需要自动装配的属性必须是引用数据类型!
<bean id="user" class="com.kuang.pojo.User" autowire="byName"> <!--通过byName的方式-->
<property name="str" value="qinjiang"/>
</bean>
<bean id="user" class="com.kuang.pojo.User" autowire="byType"> <!--通过byType的方式-->
<property name="str" value="qinjiang"/>
</bean>
<!--
注意 : 我们通过xml,开启自动装配的意思:
比如我们呢为User类开启自动装配,装配类型为过byName的方式,会将User类中的所有引用数据类型实现byNmae自动装配,
而非引用数据类型,还需要我们手动的赋值!
-->
注解开启有如下常用注解,将如下主注解放在需要自动装配的属性上即可!
public class TestServiceImpl {
// 下面两种@Autowired只要使用一种即可
@Autowired
private UserDao userDao; // 用于字段上
@Autowired
public void setUserDao(UserDao userDao) { // 用于属性的方法上
this.userDao = userDao;
}
}
// 实现按照名字自动装配
public class TestServiceImpl {
@Autowired
@Qualifier("userDao")
private UserDao userDao;
}
public class TestServiceImpl {
// 下面两种@Resource只要使用一种即可
@Resource(name="userDao")
private UserDao userDao; // 用于字段上
@Resource(name="userDao")
public void setUserDao(UserDao userDao) { // 用于属性的setter方法上
this.userDao = userDao;
}
}
自动装配就这么简单!
扩展一下
@Autowired(required=false) 说明:false,对象可以为null;true,对象必须存对象,不能为null。
//如果允许对象为null,设置required = false,默认为true
@Autowired(required = false)
private Cat cat;
前面我们一直通过在xml标签的形式创建对象,接下来我们介绍一下注解的方式创建对象!
Spring提供如下四种注解来实现对象的创建
以上四个注解的作用是一样的,都可以用来创建bean,这样分只是为了更好的进行分层。
使用注解的具体步骤:
1、引入AOP的依赖(我们如果使用Maven导入webmvc会自动导入aop)
2、开启组件扫描(注解扫描,为有注解的类创建对象)
2.1、引入context名称空间:
<?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:component-scan base-package="com.kuang.pojo"/>
</beans>
2.2、配置扫描哪些包下的注解
<!--指定注解扫描包-->
<context:component-scan base-package="com.sqx.pojo"/>
3、在指定包下编写类,增加注解
//@Component(value="user") value属性完全可以省略不写!
// 相当于配置文件中 <bean id="user" class="当前注解的类"/>
@Component //默认创建对象的名称就是类型的首字母小写! 例如 class:UserServcice ---> id:userService
public class User {
public String name = "sqx";
}
4、测试
@Test
public void test(){
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("beans.xml");
User user = (User) applicationContext.getBean("user");
System.out.println(user.name);
}
5、开启组件扫描的细节
这一块内容知道就好,通过两个例子演示
<!--开启组件扫描,默认扫描com.sqx包下的所含的所有注解,创建对象!-->
<context:component-scan base-package="com.sqx" ></context:component-scan>
<!--同样是开启组件扫描,而不是扫描com.sqx包下的所有注解,而是只扫描Controller注解,然后创建对象-->
<context:component-scan base-package="com.sqx" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!--同样是开启组件扫描,而不是扫描com.sqx包下的所有注解,而是扫描com.sqx包下的全部注解除了Controller注解,然后创建对象-->
<context:component-scan base-package="com.sqx" use-default-filters="false">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
引用数据类型的属性,通过@Atowired、@Quilifire、@Resource 实现,而基本数据类如何实现DI呢?
@Value :注入普通类型属性
@Component("user") // 相当于配置文件中 <bean id="user" class="当前注解的类"/>
public class User {
@Value("宋淇祥") // 相当于配置文件中 <property name="name" value="宋淇祥"/>
public String name;
}
小结一下
XML与注解比较
xml与注解整合开发 :推荐最佳实践
<context:annotation-config/>
作用:
基于Java类进行配置
JavaConfig 原来是 Spring 的一个子项目,它通过 Java 类的方式提供 Bean 的定义信息,在 Spring4 的版本, JavaConfig 已正式成为 Spring4 的核心功能 。
1、编写一个实体类,Dog
@Component //将这个类标注为Spring的一个组件,放到容器中!
public class Dog {
public String name = "dog";
}
2、新建一个config配置包,编写一个MyConfig配置类
@Configuration //代表这是一个配置类
public class MyConfig {
@Bean //通过方法注册一个bean,这里的返回值就Bean的类型,方法名就是bean的id!
public Dog dog(){
return new Dog();
}
}
3、测试
@Test
public void test2(){
ApplicationContext applicationContext =
new AnnotationConfigApplicationContext(MyConfig.class);
Dog dog = (Dog) applicationContext.getBean("dog");
System.out.println(dog.name);
}
关于这种Java类的配置方式,我们在之后的SpringBoot 和 SpringCloud中还会大量看到,我们需要知道这些注解的作用即可!
面向切面编程(方面),利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分耦合度降低,提高开发效率!
通俗描述:在不修改源代码的方式,在主干功能当中添加新功能!
AOP的底层就是动态代理,而其动态代理也根据情况的不同分为JDK动态代理和CGLIB动态代理
JDK动态代理是在有接口的情况下使用,所以我们需要先创建接口实现类的代理对象,这一步通过Proxy的方法可以实现!
Proxy : java.lang.reflect.Proxy
方法有三个参数:
1、类加载器
2、增强方法所在的类,这个类的接口 ,支持多个接口
3、实现这个接口InvocationHandler ,创建代理对象,写增强方法
具体的实现步骤
1、编写一个接口,UserDao
public interface UserDao {
int add(int a, int b) ;
String update(String id) ;
}
2、创建接口的实现类,UserDaoImpl
public class UserDaoImpl implements UserDao {
public int add(int a, int b) {
return a + b ;
}
public String update(String id) {
return id ;
}
}
3、通过Proxy创建代理类,实现方法增强
public class JDKProxy {
public static void main(String[] args) {
//创建接口实现类的代理对象
Class[] interfaces = { UserDao.class } ;
UserDaoImpl userDaoImpl = new UserDaoImpl();
UserDao dao = (UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces,
new UserDaoProxy(userDaoImpl));// invoke方法自动调用
int result = dao.add(1,2) ;
System.out.println("result:"+result);
}
}
//创建代理对象的代码
class UserDaoProxy implements InvocationHandler{
//1、创建的是谁的代理对象,把谁传进来
//有参构造传递
private Object obj ;
public UserDaoProxy(Object obj) {
this.obj = obj ;
}
//增强的逻辑
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("方法之后执行..." + obj);
return res;
}
}
4、测试结果,实现方法增强!
介绍一下AOP当中的的相关术语,例如:发动机术语是引擎
1、连接点 :类里面的哪些方法可以被增强,这些方法称为连接点 ;
2、切入点:实际被真正增强的方法,称为切入点 ;
3、通知(增强):实际增强的逻辑部分就称为通知 ;通知也分5种:前置通知 、后置通知 、环绕通知、异常通知、最终通知!
4、切面 :是一个动作,指的是将通知应用到切入点的过程!
Spring框架一般都是基于Aspectj实现AOP操作!
1、什么是AspectJ ?
2、基于Aspectj实现AOP操作的方式 :
如下开始使用Spring 和 AjpectJ 来实现AOP的操作!
1、环境准备:Ajpectj + Spring
<!--Spring的依赖,默认会引入aop-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
<!--AspectJ-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
2、切入点表达式
execution([权限修饰符][返回类型][类全路径][方法名称]([参数列表])) //类全路径:类的全限定名
例1:对com.sqx.dao.BookDao
类里面的add方法进行增强
execution(* com.sqx.dao.BookDao.add(..)) // * 表示任意权限修饰符
例2:对com.sqx.dao.BookDao
类里面的所有方法进行增强
execution(* com.sqx.dao.BookDao.*(..)) // * 表示任意权限修饰符
例3:对com.sqx.dao
包里面的所有类,类里面的所有方法进行增强
execution(* com.sqx.dao.*.*(..)) // * 表示任意权限修饰符
通过AspectJ注解的方式实现AOP操作
1、创建一个类,在类中定义方法
public class User {
public void add(){
System.out.println("add方法执行....");
}
}
2、创建增强类(编写增强逻辑)
/***
* User增强类
*/
public class UserProxy {
//前置通知
public void before(){
System.out.println("before.......");
}
}
3、进行通知的配置
3.1、在Spring配置文件,开启注解扫描
<!--开启注解扫描-->
<context:component-scan base-package="com.sqx"/>
3.2、使用注解创建User和ProxyUser:也就是在类的上边加上@Component
@Component
public class User { ... }
3.3、在增强类上添加一个注解 @AspectJ
/***
* User增强类
*/
@Component
@Aspect //为增强类生成一个代理对象
public class UserProxy {
//前置通知
public void before(){
System.out.println("before.......");
}
}
3.4、在Spring配置中开启生成代理对象:同时需要引入aop的命名空间
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--开启AspectJ生成代理的对象:为带有@Aspectj的类创建代理对象-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
3.5、配置不同类型的通知
1、在增强类的里面,在作为通知方法上面添加通知类型注解,使用切点表达式配置
/***
* User增强类
*/
@Component
@Aspect //生成增强类的代理对象
public class UserProxy {
//前置通知
@Before(value = "execution(* com.sqx.annot.User.add())") // 表示方法作为前置通知切入到add()方法
public void before(){
System.out.println("before.......");
}
}
2、进行测试
方法增强成功!
4、剩余的配置细节
对以上通知类型都进行测试,我么看一下有什么问题?
①、我们发现,我们为一个切点多次增强,切入点表达式出现冗余,因此,我们可以将切点表达式抽取出来,生成一个公共切入点
1、定义公共切入点:
@Pointcut(value = "execution(* com.sqx.annot.User.add())")
public void pointDemo(){
}
2、使用公共切入点:
//前置通知
@Before(value = "pointDemo()")
public void before(){
System.out.println("before.......");
}
以上就解决了我们的切入点冗余的问题!
②、如果出现如下情况:多个增强类对同一个方法进行增强,我们需要制定其优先级
我们通过@Order注解来设置增强类优先级:这个值越小优先级越高!
@Order(3)
public class UserProxy {}
@Order(1)
public class PersonProxy {}
执行测试,查看结果
通过xml配置文件的方式实现AOP操作(很少使用,了解即可!)
事务一般添加到JavaEE三层结构里面的Service层(业务逻辑层)
Spring事务管理的两种方式:1、编程式事务管理 2、声明式事务管理(推荐)
区别:编程式事务管理,是我们通过代码保证我们的事务,显得比较臃肿,因此推荐声明式事务管理
如下是编程式事务的一个演示:
//模拟一下转账操作,小明向小红转账300 ;
public void accountMony(){
try{
UserDao.addmony() //小明的余额添加300
UserDao.reducemony() //小红的余额减去300
}catche(Exception){
//回滚
}
}
声明式事务的使用方式有如两种:
声明式事务的底层,使用的就是我们的AOP原理
Spring事务管理的一些API :
PlatformTransactionManager //事务管理器的接口,根据整合不同的框架采不同的实现类(事务管理器)
如果我们的Spring整合了Mybatis 、jdbcTemplate都是使用的DataSourceTransactionManger
这个事务管理器!
1、配置Spring的事务管理器
<!--创建事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="datasource"/>
</bean>
2、在Spring配置文件,开启事务注解
<!--在头文件添加如下命名空间tx-->
xmlns:tx="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/tx https://www.springframework.org/schema/aop/spring-tx.xsd
<!--开启事务注解-->
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
3、在Service类上面(获取Service类里面的方法上面)添加事务注解
@Transactional
public class UserServiceImpl { }
public class UserServiceImpl {
@Transactional
void UpdateUserInfo(User User){ }
}
到此,我们的声明式事务,通过注解的方式就已经开启了!
@Transactional扩展 : 了解一个这个注解的一些属性参数
常用的有如下:
指的是事务方法(对数据库表中数据发生改变的方法,统称事务方法),之间的相互调用!
@Transactional
public void add() {
update() ; //调用update方法 这时候引出的一个问题add方法中开启了事务,但是调用了update方法,事务是如何管理的!
}
public void upodate() {}
事务的传播行为有七种:
参考文章:https://blog.csdn.net/weixin_39625809/article/details/80707695
isolation:事务隔离级别
在此处主要是指的多个开启事务的方法的并发问题,本质还是跟我们MySQL中的事务隔离级别一致!
timeout:超时时间
事务需要在一定时间内进行提交,如果说在这一段时间内不提交,就会发生回滚!
默认值是-1 , 设置时间以秒为单位
readOnly:是否只读
读:查询操作,写:增删改操作’
默认值为false , 表示当前事务当中可以查询可以查询和增删改操作
设置为true , 当前事务中只支持读操作
rollbackFor:回滚
设置出现哪些异常,执行回滚
noRollbackFor:不回滚
设置出现哪些异常,不执行回滚
实际开发,我们依然是用注解,但是xml配置方式仍需了解一下!
前提:声明式事务本质还是aop实现的,我们注解只是代替了我们手动切入事务的这个步骤,xml则需要我们手动的完成这个步骤!
1、依然是配置我们事务管理器
<bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
<!--创建事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="datasource"/>
</bean>
2、配置我们的通知
<!--配置通知-->
<tx:advice id="txadvice">
<!--配置事务参数-->
<tx:attributes>
<!--指定哪种规则的方法上面添加事务-->
<!--name可看做切入点中的accounMoney方法添加事务-->
<tx:method name="accountMoney" propagation="REQUIRED"/>
<!--
方法名为account开头的方法,添加事务
<tx:method name="account*"/>
-->
</tx:attributes>
</tx:advice>
3、配置切入点和切面
<!--配置切入点和切面-->
<aop:config>
<!--配置切入点-->
<aop:pointcut id="pt" expression="execution(* com.sqx.service.UserService.*(..))"/>
<!--配置切面-->
<aop:advisor advice-ref="txadvice" pointcut-ref="pt"/>
</aop:config>
xml配置文件方式实现声明式事务完成!
通过JavaConfig的方式配置我们所有信息,无需要xml文件
@Configuration
@ComponentScan(basePackages = "com.sqx")
@EnableTransactionManagement // 开启事务管理
public class MyConfig {
//创建一个数据库的连接池对象
@Bean
public DruidDataSource getDruidDataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8");
dataSource.setUsername("root");
dataSource.setPassword("123456");
return dataSource;
}
//创建一个JdbcTemplate对象
@Bean
public JdbcTemplate getJdbcTemplate(DataSource 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 ;
}
}
需要注意:
事务相关就到此完结!
Spring5 框架自带了通用的日志封装,而且也能整合其他日志工具 如 : Log4j 、Log4j2
由于Spring5 移除了Log4j CofigerListener(使用Log4j的核心),如果需要Log4j 要将Spinrg5降为4版本,所以官方建议使用Log4j2
参考文章:https://blog.csdn.net/zjh2016/article/details/103170578
1、引入相关依赖
需要导入如下的4个依赖,才能使用Log4j2
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.8.0-alpha2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.10.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.10.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.10.0</version>
</dependency>
2、创建Log4j2.xml配置文件
配置都是如下:
<?xml version="1.0" encoding="UTF-8"?>
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--Configuration后面的status用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,可以看到log4j2内部各种详细输出-->
<configuration status="WARN">
<!--先定义所有的appender-->
<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>
<!--然后定义logger,只有定义了logger并引入的appender,appender才会生效-->
<!--root:用于指定项目的根日志,如果没有单独指定Logger,则会使用root作为默认的日志输出-->
<loggers>
<root level="info">
<appender-ref ref="Console"/>
</root>
</loggers>
</configuration>
到这里我们Log4j2就已经开启了,但是如果我们呢想要手动使用Log4j2呢?
3、进行如图操作就好了
就如下两步即可!
private static final Logger log = LoggerFactory.getLogger(MyTest.class) ;
log.info("hello Log4j2");
log.debug("hello Log4j2");
log.warn("hello Log4j2");
log.error("hello Log4j2");
log.trace("hello Log4j2");
完结!
常见的单元测试框架JUnit4 、JUnit5 我们的Spring5 都是支持的,我们逐个测试!
参考文章:https://blog.csdn.net/sinat_32336967/article/details/112275292
前提:先准备Spring5的环境
<!--Start--Spring5的关键Jar包依赖--Start-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.5.RELEASE</version>
<scope>test</scope>
</dependency>
1、导入相关依赖
<!--Start--Junit4的Jar包依赖--Start-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--End--Junit4的Jar包依赖--End-->
2、Spring5+Junit4单元测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classpath = "beans.xml")
public class AppConfigurationTest {
@Autowired
private RestTemplate restTemplate;
@org.junit.Test
public void restTemplate() {
System.out.println(restTemplate);
ResponseEntity<String> res = restTemplate.getForEntity("https://www.baidu.com", String.class);
System.out.println(res.getBody());
}
}
1、引入相关依赖
<!--JUnit5-->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<!--RELEASE表示获取最新版本,此文写作时是5.7.0-->
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
2、Spring5+Junit5单元测试代码
//下面两个注解可以用@SpringJunitConfig(AppConfiguration.class)替代
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = AppConfiguration.class) //加载的JavaConig配置类,也可以classpath = "beans.xml"
public class AppConfigurationTest {
@Autowired
private RestTemplate restTemplate;
@org.junit.jupiter.api.Test
public void restTemplate() {
System.out.println(">>>>>>>>>"+restTemplate);
ResponseEntity<String> res = restTemplate.getForEntity("https://www.jd.com", String.class);
System.out.println(res.getBody());
}
}
不同点
Spring5+Junit4时,使用如下两个注解:
Spring5+Junit5时,使用如下两个注解:
两者均是spring-test包中提供的类。
相同点
加载配置类或者配置文件均使用注解 :
@ContextConfiguration(classes = AppConfiguration.class) 或者 @ContextConfiguration(classpath = “beans.xml”)
注意事项:在使用Spring5时,Junit版本最低为4.12,否则就会报错。
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/m0_46571920/article/details/122584443
内容来源于网络,如有侵权,请联系作者删除!