Spring学习笔记

spring底层原理:XML、工厂模式和反射。
spring两大核心:IOC和AOP

IOC(Inversion of Control)思想基于IOC容器完成,IOC容器底层就是对象工厂。

spring提供IOC容器的两种实现方式:
1.beanFactory:这是IOC基本实现,是spring的内部的使用接口—类似于懒汉式加载
2.ApplicaitonContext:这是beanFactory的子接口,功能更强大,开发用—类似于饿汉式加载

ApplicaitonContext的实现类:
1.ClassPathXmlApplicationContext–读取 src 目录下的配置文件
2.FileSystemXmlApplicationContext–即系统文件路径,文件的目录

IOC操作 中的 bean管理
什么是bean管理:

  1. spring创建对象。
  2. spring注入属性

bean管理操作的两种方式:----创建对象,注入属性的方式
1. 基于xml配置文件实现
2. 基于注解方式实现

  1. 基于xml配置文件实现
    创建对象,如:<bean id = "dao" class = "com.laowang.UserDao"></bean>
    id属性:获取对象的唯一标识
    class属性:类全路径
    创建的时候也会执行默认的构造方法

  2. 基于注解方式实现
    DI:依赖注入,就是注入属性
    第一种注入方式:使用set方法进行注入
    1.创建类,定义其属性和set方法
    2.在spring配置文件配置对象创建,配置属性注入
    第二章注入方式:使用有参数构造进行注入

     1. 创建类,定义属性,创建属性对应有参构造方法
    
<bean id = "", name = "">
				<property name="bname" value="">	</property> 			
				<property name="bauthor" value="玛格丽特·米切尔"></property> 	
			</bean>
	2. 在spring配置文件中
<bean id = "", name = "">
				<constructor-arg name="bname" value=""></constructor-arg>			
				<constructor-arg name="bauthor" value="玛格丽特·米切尔"></constructor-arg>	
				<!--constructor-arg index = "0" value="玛格丽特·米切尔"--><!--/constructor-arg-->
			</bean>

1 IOC操作bean管理----xml注入其他属性

  1. 字面量
    (1) 空值:<property name="bname" ><null/></property>
    (2) 属性包含特殊符号:<property name="bname" value="<<南京>>"></property>
    解决方法:转义 &lt; &gt;
    把带特殊符号内容写入CDATA里<value><![CDATA[你的内容]]></value>

2 注入属性-外部bean

<bean id = "userService", class= "com.laowang.springoo.service.UserService">
		<property name="userDao" ref="userDaoImpl">	</property> <!--用ref来注入-->
	</bean>

3 注入属性-内部bean和级联赋值

<bean id = "emp", class= "com.laowang.springoo.bean.Emp">
		<property name="ename" value="lucy"></property> 
		<property name="esex" value=""></property> 
		<property name="dept">
			<bean id = "dept", class= "com.laowang.springoo.bean.Dept">
				<property name="dname" ref="保安部"></property> 
			</bean>
		</property> 
	</bean>

IOC操作bean管理–xml注入集合属性
1. 注入数组类型属性

<property name="list">
			<array><value>张三</value><value>张三</value></array>
		</property>
2.  注入list类型属性
<property name="list">
			<list><value>张三</value><value>张三</value></list>
		</property>
3.  注入map类型属性
<property name="list">
			<map><entry key="张三" value="zhangsan"></entry>
			<entry key="张三" value="zhangsan"></entry></map>
		</property>

IOC操作bean管理—FactoryBean
spring里面有两种bean,一种普通bean,一种工厂bean

  1. 普通bena定义的类型就是返回的类型
  2. 工厂bean定义的类型可以和返回类型不一致

spring bean默认是单实例

  1. 在spring配置文件bean标签里scope属性用于设置单实例还是多实例
  2. scope属性值
    第一种 默认是 singleton:当一个bean的作用域设置为singleton, 那么Spring IOC容器中只会存在一个共享的bean实例,并且所有对bean的请求,只要id与该bean定义相匹配,则只会返回bean的同一实例。换言之,当把 一个bean定义设置为singleton作用域时,Spring IOC容器只会创建该bean定义的唯一实例。这个单一实例会被存储到单例缓存(singleton cache)中,并且所有针对该bean的后续请求和引用都 将返回被缓存的对象实例
<bean id="role" class="spring.chapter2.maryGame.Role" scope="singleton"/> 
第二种 **prototype**  多实例对象:prototype作用域部署的bean,每一次请求(将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法)都会产生一个新的bean实例,相当与一个new的操作,对于prototype作用域的bean,有一点非常重要,那就是Spring不能对一个prototype bean的整个生命周期负责,容器在初始化、配置、装饰或者是装配完一个prototype实例后,将它交给客户端,随后就对该prototype实例不闻不问了。不管何种作用域,容器都会调用所有对象的初始化生命周期回调方法,而对prototype而言,任何配置好的析构生命周期回调方法都将不会被调用。 清除prototype作用域的对象并释放任何prototype bean所持有的昂贵资源,都是客户端代码的职责。
<bean id="role" class="spring.chapter2.maryGame.Role" scope="prototype"/>


第三种 request :request表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP request内有效。
第四个 session : session作用域表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP session内有效。

bean生命周期----也就是执行顺序
1. 通过构造器创建bean实例(无参数构造)
2. 为bean的属性设置值和对其他bean引用(调用set方法)
bean实例传递bean后置处理器的方法—postprocessbeforeInitialization
3. 调用bean的初始化的方法(配置)
bean实例传递bean后置处理器的方法—postprocessafterInitialization
4. bean可以获取—获取实例对象
5. 当容器关闭的时候,调用bean的销毁方法(需要配置销毁的方法)

IOC操作bean管理—xml自动装配

  1. 自动装配:根据指定装配规则(属性名或者属性类型),spring自动将配置的属性值进行注入
  2. <bean id = "" class = "" autowire = "byName"></bean><bean id = "" class = "" autowire = "byType"></bean>
    byName 根据属性名称注入,注入值bena的id值和类属性名称一样
    byType 根据属性类型注入
    xml装配用的很少

IOC操作bean管理(外部属性文件)

  1. 直接配置数据库信息
    配置德鲁伊连接池
<bean id = "dataSource" class = "com.alibaba.druid.pool.DruidDataSource">
		<property name="driverClassName",value="com.mysql.jdbc.driver"></property>
		<property name="url",value="http://xxxx.xxxx.xxxx.xxx:3306/userDB"></property>
		<property name="username",value="xxx"></property>
		<property name="password",value="xxx"></property>
	</bean>
  1. 引入外部属性文件配置数据库连接池
    1 创建外部配置文件properties,写好驱动url,name,password
    2 把外部的properties属性文件引入到spring配置文件中
    引入context名称空间 xmlns:context
    引入外部属性文件jdbc.properties
<context:property-placeholder location="classpath:hdbc.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>

IOC操作bean管理-----基于注解方式

  1. 什么是注解
    1 注解是代码特殊标记, 格式: @注解名称(属性名称=属性值。。。。)
    2 使用注解,注解作用在类上面,方法上面,属性上面
    3 使用注解简化xml配置。

  2. spring针对bean管理中创建对象提供四种注解
    1 @Component
    2 @Service
    3 @Controller
    4 @Repository
    ***上面的四个注解功能是一样的,都可以用来创建bean实例,只不过用不同的名称用来区分不同的业务逻辑。

  3. 基于注解方式实现对象创建
    引入AOP依赖
    开启组件扫描<context:component-scan base-package="com.laowang.spring.Service, com.laowang.spring.dao"></context:component-scan>
    创建类,在类上面添加创建对象注解-----注解里value属性可以不写,默认就是类名称,首字母小写

  4. 基于注解方式实现属性注入
    1 根据属性的类型进行自动装配–@Autowired
    第一步:把service和dao对象创建,在service和dao类添加创建对象注解
    第二部:在service注入dao对象,在service类田家庵dao类型属性,在属性上面使用注解
    2 根据属性名称进行注入---------@Qualifier
    这个注解和上面的autowired一起使用
    3 根据类型或者名称都行---------@Resource-----javax中的,不是spring中的
    4 注入普通类型属性--------------@Value

  5. 完全注解开发
    创建配置类代替xml文件–配置类用的是@Configuration注解,还有@ConfigurationScan(basePackages={"com.laowang"})代替xml中的component-scan
    同时测试类中的applicationContext用的是AnnotationConfigurationContext(SpringConfig.class)

AOP—概念-----面向切面编程
好处:对业务逻辑各部分隔离,降低耦合度;不通过修改源代码添加功能。

AOP底层原理

  1. AOP用的是动态代理
    两种情况的动态代理
    第一种 有接口情况,使用JDK动态代理
    第二种 没有接口情况, 使用CGLIB动态代理

实现:通过java.lang.reflect.proxy
— 调用newProxyInstance(classLoader loader,类<?>[] interfaces, invocationHandler h)
方法三个参数:
第一个:类加载器 classLoader
第二个:增强方法所在的类,这个类实现的接口,支持多个接口
第三个:实现这个接口invocationHandler ,创建代理对象,写增强的方法

AOP术语

  1. 连接点
    类里的那些方法可以被增强,这些方法就是连接点
  2. 切入点
    实际被真正增强的方法
  3. 通知
    实际增强的逻辑部分称为通知
    通知有五种类型:前置通知,后置通知,环绕通知,异常通知,最终通知
  4. 切面
    是动作----把通知应用到切入点过程

AOP操作

  1. spring框架一般基于AspectJ实现AOP操作
    ----什么是AspectJ:独立的AOP框架,只不过一半和spring一起使用,进行AOP操作
  2. 基于AspectJ实现AOP操作
    1. 基于XML配置文件实现
    2. 基于注解方式实现
  3. 项目工程里引入AOP相关依赖 AspectJ
  4. 切入点表达式
    1. 切入点表达式的作用:知道对哪个类里的哪个方法进行增强
    2. 语法结构:
executioon([权限修饰符] [返回类型] [类全路径] [方法] ([参数列表]))
		例子:对com.laowang.dao.BookDao类里的add进行增强
		         execution(*com.laowang.dao.BookDao.add(..))
		例子:对com.laowang.dao.BookDao类里的所有方法进行增强
		         execution(*com.laowang.dao.BookDao.*(..))
		例子:对com.laowang.dao包里的所有类里的所有方法进行增强
		         execution(*com.laowang.dao.*.*(..))

AOP操作—AspectJ注解

  1. 创建类,在类里定义方法
    User

  2. 创建增强类
    1.在增强类里创建方法,让不同方法代理不同通知类型
    UserProxy

  3. 进行通知的配置

    1. 在spring配置文件中开启注解扫描-------xml配置注解扫描
    2. 使用注解创建User和UserProxy对象-----添加@Component
    3. 在增强类中添加@AspectJ--------------生成代理对象
    4. 在spring配置文件中开启生成代理对象–<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
  4. 在spring配置文件中开启生成代理对象

  5. 公共切入点抽取—@PointCut注解抽取,想要被抽取的方法的value="pointcut对应的方法"

  6. 有多个增强类对同一个方法进行增强,设置增强类优先级
    — 增强类中添加注解@Order,优先级越小越优先

AOP操作—AspectJ配置文件

  1. 创建两个类,增强类和增强方法
  2. 在spring配置文件中创建两个类对象
  3. 在spring配置文件中配置切入点

JdbcTemplate
spring对jdbc进行封装成了jdbctemplate
准备工作

  1. 引入jar包
  2. spring配置文件中配置数据库连接池
  3. 配置jdbctemplate,注入DataSource
    编写service和dao层
    dao层进行数据库添加操作
    调用jdbctemplate进行增删改查

事务:逻辑上的一组操作,要么全部成功,要么全部不成功

事务四大特性 ACID 原子性-一致性-隔离性-持久性

spring中进行事务操作管理两种方式:编程式事务管理和声明式事务管理

声明式事务管理----底层就是AOP

  1. 基于注解方式
  2. 基于xml配置文件方式

事务操作—声明式事务管理配置参数

  1. 在service类上面添加注解**@Transactional**,此注解中配置事务相关参数

  2. 配置propagation:事务传播行为
    多事务方法直接进行调用,这个过程中事务是如何进行管理的
    也就是 事务方法调用事务方法,非事务方法调用事务方法,事务方法调用非事务方法等
    事务的传播行为分为7种****
    1.REQUIRED:默认
    如果add()方法本身有事务,调用了update方法后,update使用当前add方法的事务
    如果add()方法本身没有事务,调用了update方法后,update创建新的事务
    2.REQUIRED_NEW: 使用add方法调用update方法
    无论add方法是否有事务,都创建新的事务
    3.SUPPORTS:如果有事务在运行,当前方法就在这个事务运行,否则可以 不在事务中运行
    4.NOT_SUPPORTED:当前的方法不应该运行在事务中,如果有运行的事务,挂起它
    5.MANDATORY:当前方法必须运行在事务中,没有事务会抛异常
    6.NEVER:和MANDATORY相反,当前方法不能运行在事务中,否则异常
    7.NESTED:有事务运行的话,当前方法就应在这个事务的桥套事务内运行,否则启动一个新事务,在新事物内运行。

  3. ioslation:事务隔离级别

1)  事务有隔离性,多事务操作之间不会有影响,不考虑隔离性会有三个问题。
2) 三个问题:**脏读,不可重复度,幻读**。
		**脏读:一个未提交的事务读取到了另一个未提交事务的数据---加乐观锁
		不可重复读:一个未提交的事务读取到了另一个已经修改过的数据(和自己读的不一样了)
		幻读:一个未提交的事务读取到了另一个事务添加的数据**
3) 通过设置事务的隔离性解决三个问题:
		设置隔离级别:		        脏读     不可重复读  		幻读
			READ UNCOMMITTED     	有	          有	         有  
			READ COMMITTED          无	          有             有
			REPEATABLE READ	        无	          无	         有
			SERIALIZATION	        无	          无	         无
 4) timeout:超时时间
	事务需要在限定时间内提交,不提交就回滚
 5) readOnly:是否只读
	默认 false
 6) rollbackFor:回滚
	出现哪些异常会回滚
 7) noRollBackFor:不回滚
	出现哪些异常不回滚
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值