关于spring5全程笔记

关于spring5的重要笔记在下面的百度网盘连接中,欢迎大家一起学习
链接:https://pan.baidu.com/s/1Pb-2gGbtLncUD_Uul-1Ivw
提取码:4m4v

下面就我学习过程中的一些容易忘记的点再做一次记录,以便后续复习

**

IOC注入属性

**
在使用set方法注入属性时(无参构造函数+set方法):

<!--当要给一个属性注入其他类型的值时,操作如下-->
        <!--1 空值--><property name="baddress"><null/></property>
        <!--2 属性值包含特殊符号,首先把<>转义,把带特殊符号内容写到CDATA中-->
        <property name="bid">
            <value>
                <![CDATA[<<南京>>]]><!--输出<<南京>>-->
            </value>
        </property>
   特殊类型的注入
    <bean id="student" class="com.it.spring5.collectiontype.Student">
    <!--数组类型属性的注入-->
    <property name="course">
        <array>
            <value>java课程</value>
            <value>python课程</value>
        </array>
    </property>
    <!--list类型属性的注入-->
    <property name="list">
        <list>
            <value>张三</value>
        </list>
    </property>
    <!--map类型属性的注入-->
    <property name="map">
        <map>
            <entry key="1" value="1.1"></entry>
        </map>
    </property>
    <!--set类型属性的注入-->
    <property name="sets">
        <set>
            <value>111</value>
        </set>
    </property>
</bean>

bean的生命周期

<!--默认是单实例,即加载配置文件后,getBean获得的是同一个对象,可通过scope来设置为多实例-->
    <bean id="myBean" class="com.it.spring5.factorybean.MyBean" scope="prototype">
        <!--这里面还有属性init-method="",destroy-method="",可在对应的类中定义两个方法作为初始化和销毁的功能-->
        <!--bean的生命周期:
        1-通过无参构造创建Bean实例
        2-调用set方法注入属性
        3-调用初始化方法,需自行配置
        4-bean可以使用了
        5-调用销毁方法,自行配置,这里销毁是要自行调用的,为前面强转applicationContext.close()-->

自动注入属性

1)根据属性名称自动注入
<!--实现自动装配
bean 标签属性 autowire,配置自动装配
autowire 属性常用两个值:
byName 根据属性名称注入 ,注入值 bean 的 id 值和类属性名称一样
byType 根据属性类型注入
-->
<bean id="emp" class="com.atguigu.spring5.autowire.Emp" autowire="byName"></bean>
<bean id="dept" class="com.atguigu.spring5.autowire.Dept"></bean>2)根据属性类型自动注入
<bean id="emp" class="com.atguigu.spring5.autowire.Emp" autowire="byType"></bean>
<bean id="dept" class="com.atguigu.spring5.autowire.Dept"></bean>

spring引入外部配置文件配置数据库连接池

<!--引入外部属性文件-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--配置连接池-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
	<property name="driverClassName" value="${prop.driverClass}"></property>
	<property name="url" value="${prop.url}"></property>
	<property name="username" value="${prop.userName}"></property>
	<property name="password" value="${prop.password}"></property>
</bean>

基于注解装配

1、什么是注解
(1)注解是代码特殊标记,格式:@注解名称(属性名称=属性值, 属性名称=属性值…)
//在注解里面 value 属性值可以省略不写,默认值是类名称,首字母小写,即就是这个bean对象的id
(2)使用注解,注解作用在类上面,方法上面,属性上面
2、Spring 针对 Bean 管理中创建对象提供注解
(1)@Component 一般用于javabean层
(2)@Service 一般用于service层
(3)@Controller 一般用于controller层
(4)@Repository 一般用于dao层

  • 上面四个注解功能是一样的,都可以用来创建 bean 实例

开启组件扫描():

spring配置文件中不扫描controller层
<context:component-scan base-package="com.it.spring5">
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
springmvc配置文件中只扫描controller层,要加上不许用默认的过滤器,因为他自己配置了
<context:component-scan base-package="com.it.spring5" use-default-filters="false">
	<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

基于注解方式实现属性注入

(1)@Autowired:根据属性类型进行自动装配

@Autowired
private UserDao userDao;

(2)@Qualifier:根据名称进行注入
这个@Qualifier 注解的使用,和上面@Autowired 一起使用

@Autowired //根据类型进行注入
@Qualifier(value = "userDaoImpl1") //根据名称进行注入
private UserDao userDao;

AOP

1、什么是 AOP
(1)面向切面编程(方面),利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
(2)通俗描述:不通过修改源代码方式,在主干功能里面添加新功能

2、AOP 底层使用动态代理
(1)有两种情况动态代理
第一种 有接口情况,使用 JDK 动态代理 • 创建接口实现类代理对象,增强类的方法
第二种 没有接口情况,使用 CGLIB 动态代理 • 创建子类的代理对象,增强类的方法
但这两种底层原理实现起来都很麻烦,而且有局限,因此我们使用AspectJ这个强大的AOP框架
使用AspectJ实现AOP有两种方式:1-基于XML的声明式AspectJ,2-基于注解的声明式AspectJ

3、AOP术语
1.连接点——类里面哪些方法可以被增强,这些方法称为连接点,注意是可以
2.切入点——哪些方法真正的被增强,称为切入点
切入点表达式
(1)切入点表达式作用:知道对哪个类里面的哪个方法进行增强
(2)语法结构: execution([权限修饰符][空格][返回类型][空格][类全路径][.]方法名称 )
其中,权限修饰符可省略,返回类型*可代表所有 ,后面的类全路径以及方法名称可以写可写*,参数类型可写..代表所有
例如:execution(* com.atguigu.dao.*.* (..))
3.通知(增强)——实际增强的逻辑部分称为通知(增强)
通知有多种类型:
* 前置通知
* 后置通知
* 环绕通知
* 异常通知
* 最终通知
4.切面——把通知应用到切入点的过程,是动作

使用AspectJ实现AOP

1、使用基于XML的声明式AspectJ
这种情况需要在配置文件中配置切入点,切面,通知,标签使用起来十分复杂,不推荐使用
2、使用基于注解的声明式AspectJ
一般实际开发中我们使用这种方法
1、在需要被增强的类如User和增强后的代理类如UserProxy上添加注解创建对应的对象
2、在增强后的代理类如UserProxy上添加注解@AspectJ生成代理对象
3、在 spring 配置文件中开启生成代理对象以及扫描

		<!-- 开启 Aspect 生成代理对象-->
		<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

4、配置不同类型的通知
(1)在增强类UserProxy的里面,在作为通知方法上面添加通知类型注解,使用切入点表达式配置

@Component   // 注解创建对象
@Aspect      // 生成代理对象
@Order(0)    // 当有多个代理类对同一个方法进行增强时,我们可以对其增强设置增强的先后顺序,数字越小越先执行,0开始
public class UserProxy {

    // 这里有很多相同的切入点,于是我们可以进行抽取
    @Pointcut(value = "execution(* com.it.spring5.AOP_annotation.User.add(..))")
    public void pointCut(){}
    
    // before代表的就是前置通知,value的值是execution表达式,指定要增强的方法
    @Before(value="execution(* com.it.spring5.AOP_annotation.User.add(..))")
    public void beforeAdd(){
        System.out.println("before......");
    }
    
    // 环绕通知
    @Around(value = "pointCut()")
    public void aroundAdd(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("around前......");
        // 中间执行原始方法,使用下面这条代码
        proceedingJoinPoint.proceed();
        System.out.println("around后......");
    }
    
    // 后置通知
    @AfterReturning(value = "pointCut()")
    public void afterReturningAdd(){
        System.out.println("afterReturning......");
    }
    
    // 异常通知
    @AfterThrowing(value = "pointCut()")
    public void afterThrowingAdd(){
        System.out.println("afterThrowing......");
    }
    
    // 最终通知
    @After(value = "pointCut()")
    public void afterAdd(){
        System.out.println("after......");
    }
}

测试:
@Test
    public void testAop(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean1.xml");
        User user = applicationContext.getBean("user", User.class);// 这里用的是被增强的类,而不是代理类
        user.add();
    }

总结:没有异常时首先是环绕的前面,然后是before,接着是本体,然后是环绕后,接着是after,最后是AfterReturning

输出:
around前......
before......
本体add........
around后......
after......
afterReturning......

有异常时:没有around后,没有AfterReturning,有afterThrowing

输出:
around前......
before......
本体add........
after......
afterThrowing......

事务操作

1、什么事务
(1)事务是数据库操作最基本单元,逻辑上一组操作,要么都成功,如果有一个失败所有操作都失败
2、事务四个特性(ACID)
(1)原子性
(2)一致性——操作之前和操作之后总量不变
(3)隔离性——多事务操作时互不影响
(4)持久性
3、事务管理介绍
事务添加到 JavaEE 三层结构里面 Service 层(业务逻辑层)
在 Spring 进行事务管理操作:声明式事务管理——基于XML方式,基于注解方式
在 Spring 进行声明式事务管理,底层使用 AOP 原理
4、事务操作步骤
第一种:基于XML方式:

 	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--注入数据源-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--2 配置通知-->
    <tx:advice id="txadvice">
        <!--配置事务参数-->
        <tx:attributes>
            <!--指定哪种规则的方法上面添加事务,比如这里指定accountMoney方法加事务,第二种表示将以account开头的方法加事务,第三种表示所有方法-->
            <tx:method name="accountMoney" propagation="REQUIRED"/>
            <!--<tx:method name="account*"/>-->
            <!--<tx:method name="*"/>-->
        </tx:attributes>
    </tx:advice>

    <!--3 配置切入点和切面-->
    <aop:config>
        <!--配置切入点-->
        <aop:pointcut id="pt" expression="execution(* com.it.spring5.service.UserService.*(..))"/>
        <!--配置切面-->
        <aop:advisor advice-ref="txadvice" pointcut-ref="pt"/>
    </aop:config>

第二种:基于注解方式:
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"></tx:annotation-driven>

3、在 service 类上面(或者 service 类里面方法上面)添加事务注解,这个注解里面可以配置事务相关参数。但需要注意的是,在实际开发中,事务的配置信息在配置文件中完成,业务逻辑层只需要添加注解,不需要配置里面的参数
@Transactional,这个注解添加到类上面,也可以添加方法上面,如果把这个注解添加类上面,这个类里面所有的方法都添加事务,如果把这个注解添加方法上面,为这个方法添加事务
事务注解的参数:
1、propagation:事务传播行为——多事务方法直接进行调用,这个过程中事务是如何进行管理的
propagation的取值
2、isolation:事务隔离级别
(1)事务有特性成为隔离性,多事务操作之间不会产生影响。不考虑隔离性产生很多问题
(2)有三个读问题:脏读、不可重复读、虚(幻)读
(3)脏读:一个未提交事务读取到另一个未提交事务的数据
例如:数据原本为50,事务B修改这条数据为100,事务A读取到这个100,接着事务B进行回滚,又将这条数据修改为50,这个时候事务A读取到的是50,与前面的读取不一样,这就出现了问题,这就叫脏读,两个事务都没提交,致命问题,不能发生
(4)不可重复读:一个未提交事务读取到另一提交事务修改数据
例如:数据原本50,事务A读取到50,事务B读取到50,将其修改为100后进行提交,由于A没有提交,回滚后继续读,读取到100,与之前的50不一致,这就叫不可重复读,是一种现象,会发生
(5)虚读:一个未提交事务读取到另一提交事务添加数据
(6)解决:通过设置事务隔离级别,解决读问题,默认为可重复读
isolation取值
3、timeout:超时时间
(1)事务需要在一定时间内进行提交,如果不提交进行回滚
(2)默认值是 -1 ,设置时间以秒单位进行计算
4、readOnly:是否只读
(1)读:查询操作,写:添加修改删除操作
(2)readOnly 默认值 false,表示可以查询,可以添加修改删除操作
(3)设置 readOnly 值是 true,设置成 true 之后,只能查询
5、rollbackFor:回滚
(1)设置出现哪些异常进行事务回滚
6、noRollbackFor:不回滚
(1)设置出现哪些异常不进行事务回滚

Spring5框架新功能

1、整个 Spring5 框架的代码基于 Java8,运行时兼容 JDK9,许多不建议使用的类和方法在代码库中删除
2、Spring 5.0 框架自带了通用的日志封装,可以整合其他的第三方日志,如已经整合了Log4j2
1、引入jar包
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="INFO">
    <!--先定义所有的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>

手动加入日志内容

public class UserLog {
    private static final Logger log = LoggerFactory.getLogger(UserLog.class);
    public static void main(String[] args) {
        log.info("hello log4j2");
        log.warn("hello log4j2");
    }
}

3、Nullable注解和函数式注册对象
Spring5 框架核心容器支持@Nullable 注解
@Nullable 注解可以使用在方法上面,属性上面,方法参数里面(即在参数的类型前面写@Nullable),表示方法返回可以为空,属性值可以为空,参数值可以为空
Spring5 核心容器支持函数式风格 GenericApplicationContext,类似lambda表达式,把自己在类里面创建的对象也交给spring管理

	// 函数式风格创建对象,交给 spring 进行管理
	@Test
	public void testGenericApplicationContext() {
		//1 创建 GenericApplicationContext 对象
		GenericApplicationContext context = new GenericApplicationContext();
		//2 调用context的方法对象注册
		context.refresh();
		context.registerBean("user1",User.class,() -> new User());
		//3 获取在 spring 注册的对象
		// User user = (User)context.getBean("com.atguigu.spring5.test.User");
		User user = (User)context.getBean("user1");
		System.out.println(user);
	}

4、Spring5 支持整合 JUnit5
1、整合JUnit4
测试类不用写application.getBean了,直接注解加载配置文件,注解注入对象,很方便

		@RunWith(SpringJUnit4ClassRunner.class) //单元测试框架
		@ContextConfiguration("classpath:bean1.xml") //加载配置文件
		public class JTest4 {
		    @Autowired
		    private UserService userService;       // 直接获得到对象
		    @Test
		    public void test1() {
		        userService.accountMoney();
		    }
		}
2、整合JUnit5
	@SpringJUnitConfig(locations = "classpath:bean1.xml")
	public class JTest5 {
	    @Autowired
	    private UserService userService;
	    @Test
	    public void test1() {
	        userService.accountMoney();
	    }
	}

5、Spring5 框架新功能(Webflux)
学习这个需要有SpringMVC、SpringBoot、Maven、Java8新特性的相关基础才能搞这个,后续我会再更新的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值