【Java开发学习笔记】Spring框架

Spring

1.一个创建Bean对象的工厂

JavaBean:用java语言编写的可重用组件(javaBean > 实体类)		
Bean:在计算机语言中,有可重用组件的含义
Bean是创建service和dao对象的
	创建方式:
		*第一个:需要一个配置文件来配置service和dao
			配置的内容:唯一标识=全限定类名(key=value)
		*第二个:通过读取配置文件中的配置内容,反射创建对象
	配置文件可以是xml或者properties

2.程序的耦合

耦合:程序间的依赖关系
	包括:类之间的依赖;方法之间的依赖
解耦:降低程序间的依赖关系
实际开发中应该做到,编译器不依赖,运行时才依赖
解耦的思路:
	*第一步:使用反射来创建对象,而避免使用new关键字
	*第二步:通过读取配置文件来获取要创建的对象全限定类名

3.获取spring的IOC核心容器,并根据id获取对象

ApplicationContext的三个常用实现类:
	*ClassPathXmlApplicationContext:可以加载类路径下的配置文件,要求配置文件必须在类路径下,如果不在加载不了
	*FileSystemXmlApplicationContext:可以加载磁盘任意路径下的配置文件(必须有访问权限)
	*AnnotationConfigApplicationContext:用于读取注解创建容器的核心容器的两个接口引发出的问题:
	ApplicationContext:单例对象使用  采用此接口
		在构建核心容器时创建对象采用的策略是采用立即加载的方式。只要一读取完配置文件马上就创建配置文件中配置的对象
	BeanFactory:多例对象使用
		在构建核心容器时创建对象采用的策略是采用延迟加载的方式,什么时候根据id获取对象了,什么时候才是真正的创建对象

4.Spring对bean的管理细节

1.创建bean的三种方式
     *使用默认构造函数创建:
         在Spring的配置文件中使用bean标签,配以id和class属性后,且没有其他属性和标签时,采用的就是默认构造函数创建bean对象,此时如果类中没有默认构造函数,则对象无法创建。
     *使用普通工厂中的方法创建对象:
         使用某个类中的方法创建对象,并存入spring容器
     *使用工厂中的静态方法创建对象:
         使用某个类中的静态方法创建对象,并存入spring容器中
 2.bean对象的作用范围调整
     bean标签的scope属性:
         作用:用于指定bean的作用范围
         取值:常用的是单例的和多例的
             singleton;单例的(默认值)
             prototype:多例的
             request:作用于web应用的请求范围
             session:作用于web应用的会话范围
             global-session:作用于集群环境的会话范围(全局会话范围),当不是集群环境时,它就是session
 3.bean对象的生命周期:
     *单例对象:
         出生:当容器创建时对象出生
         活着:只要容器还在,对象一直活着
         死亡:容器销毁,对象死亡
         总结:单例对象的声明周期和容器相同
     *多例对象:
         出生:当使用对象时spring框架为我们创建
         活着:对象只要是在使用过程中就一直活着
         死亡:当对象长期不使用,且没有别的对象引用时,由java的垃圾回收器回收

5.Spring中的依赖注入

 依赖注入:Dependency Injection,依赖关系的维护就称之为依赖注入
 IOC作用:降低程序间的耦合(依赖关系)
 依赖关系的管理:以后都交给spring来维护
 在当前类需要用到其他类的对象,由Spring为我们提供,我们只需要在配置文件中说明
    依赖注入能注入的数据有三类:
         *基本类型和String
         *其他Bean类型(在配置文件中或者注解配置过的bean)
         *复杂类型/集合类型
    注入的方式有三种
         *1.使用构造函数提供
	使用的标签:constructor-arg
 			标签出现的位置:bean标签的内部
 	标签中的属性
		type:用于指定要注入的数据的数据类型,该数据类型也是构造函数中某个或某些参数的类型
		index:用于指定要注入的数据给构造函数中指定索引位置的参数赋值。索引的位置从0开始
		name:用于指定给构造函数中指定名称的参数赋值(常用的)
		================以上是哪个用于指定给构造函数中哪个参数赋值====================
		value:用于提供基本类型和String类型的数据
		ref:用于指定其他的bean类型数据。它指的就是在spring的IOC核心容器中出现过的bean对象
	优势:在获取bean对象时,注入数据是必须的操作,否则对象无法创建成功
	弊端:改变了bean对象的实例化方式,使我们在创建对象时,如果找不到这些数据,也必须提供。
         *2.使用set方法提供(常用的方式)
	涉及的标签:property
 			出现的位置:bean标签的内部
 	标签属性
		name:用于指定注入时所调用的set方法名称
		value:用于提供基本类型和String类型的数据
		ref:用于指定其他的bean类型数据。它指的就是在spring的IOC核心容器中出现过的bean对象
	优势:在获取bean对象时,注入数据是必须的操作,否则对象无法创建成功
	弊端:改变了bean对象的实例化方式,使我们在创建对象时,如果用不到这些数据,就必须提供。
	*复杂类型的注入/集合类型的注入
	*用于给List机构集合注入的标签:
		list array set
	*用于给Map结构集合注入的标签:
		map props
	*结构相同,标签可以互换
         *3.使用注解提供

6.注解配置

曾经XML的配置:
    <bean id="accountService" class="eg.service.impl.AccountServiceImpl"
		scope="" init-method="" destroy-method="">
		<property name="" value="" ref=""></property>
    </bean>
1.用于创建对象的
	作用就和在XML配置文件中编写一个<bean>标签实现的功能是一样的
	*Component:
		作用:用于把当前类对象存入spring容器中
		属性:
			value:用于指定bean的id,不写默认值是当前类名,且首字母改为小写
	*Controller:一般用在表现层
	*Service:一般用在业务层
	*Repository:一般用在持久层
	以上三个注解的作用和属性与Component是一模一样,他们三个是Spring框架为我们提供明确的三层使用的注解,使三层对象更加清晰
2.用于注入数据的
	作用就和在XML配置文件中的<bean>标签中写一个<property>标签的作用是一样的
	*Autowired:
		作用:自动按照类型注入。只要容器中有唯一的一个bean对象类型和要注入的变量类型匹配,就可以注入成功
			如果ioc容器中没有任何bean的类型和要注入的变量类型匹配,则报错
			如果ioc容器汇总有多个类型匹配时,则根据bean对象的name属性一一对应获得
		出现位置:可以是变量上,也可以是方法上
		细节:在使用注解注入时,set方法就不是必须的了
	*Qualifier:
		作用:在按照类中注入的基础上再按照名称注入。他在给类成员注入时不能单独使用。但是在给方法参数注入时可以
		属性:
			value:用于指定注入的bean的id
	*Resource:
		作用:直接按照bean的id注入,它可以独立使用
		属性:
			name:用于指定bean的id
	以上三个注入都只能注入其他bean类型的数据,而基本类型和String类型无法使用上述注解实现。
	另外,集合类型的注入只能通过XML来实现
	*Value:
		作用:用于注入基本类型和String类型的数据
		属性:
			value:用于指定数据的值,它可以使用spring中的SpEL(也就是spring的el表达式)
			SpEl的写法:${表达式}
3.用于改变作用范围的
	作用就和在bean标签中使用scope属性实现的功能是一样的
	*Scope
		作用:用于指定bean的作用范围
		属性:
			value:指定范围的取值。常用取值:singleton prototype
4.和生命周期相关(了解)
	作用就和在bean标签中使用init-method和destroy-method的作用是一样的
	*PreDestroy:用于指定销毁方法
	*PostConstruct:用于指定初始化方法

7.Spring中的新注解

1.Configuration
	作用:指定当前类是一个配置类
	细节:当配置类作为AnnotationConfigApplicationContext对象创建参数时,该注解可以不写
2.ComponentScan
	作用:用于通过注解指定spring在创建容器时要扫描的包
	属性:
		value:它和basePackages的作用是一样的,都是用于指定创建容器时要扫描的包。
			使用此注解等同于在xml中配置了:<context:component-scan base-package="eg"></context:component-scan>
3.Bean
	作用:用于把当前方法的返回值作为bean对象存入spring的ioc容器中
	属性:
		name:用于指定bean的id,当不写时,默认值是当前反复噶的名称
	细节:
		当我们使用注解配置方法时,如果方法有参数,spring框架会去容器中查找有没有可用的bean对象
		查找的方式和Autowired注解的作用是一样的
4.Import
	作用:用于导入其他配置类
	属性
		value:用于指定其他配置类的字节码
			当我们使用Import的注解之后,有Import注解的类就是父配置类,而导入的就是子配置类
5.PropertySource
	作用:用于指定properties文件的位置
	属性:
		value:指定文件的名称和路径
		关键字:classpath,表示类路径下

8.Spring整合junit的配置

1.导入spring整合junit的jar(坐标)spring-test
2.使用junit提供的一个注解把原有的main方法替换成spring提供的
	@Runwith
3.告知spring的运行器,spring和ioc创建时基于xml还是注解的,并且说明位置
	 @ContextConfiguration
		locations:指定xml文件的位置,加上classpath关键字,表示在类路径下
		classes:指定注解类所在的位置

9.动态代理

特点:字节码随用随创建,随用随加载
作用:不修改源码的基础上对方法增强
分类:
    1.基于接口的动态代理
		涉及的类:Proxy
		提供者:JDK官方
		如何创建代理对象:
			使用proxy类中的newProxyInstance方法
		创建代理对象的要求:
			被代理类最少实现一个接口,如果没有则不能使用
		newProxyInstance方法的参数:
			ClassLoader:类加载器
				用于让代理对象和被代理对象使用相同的类加载器。固定写法
			Class[]:字节码数组
				用于让代理对象和被代理对象有相同方法。固定写法
			InvocationHandler:用于提供增强的代码
				它是让我们写如何代理。我们一般都是写一些该接口的实现类,通常情况下都是匿名内部类,但不是必须的
				此接口的实现类都是谁用谁写
    2.基于子类的动态代理
		涉及的类:Enhancer
		提供者:第三方库cglib
		如何创建代理对象:
			使用Enhancer类中的create方法
		创建代理对象的要求:
			被代理类不能是最终类
		create方法的参数:
			Class:字节码
				用于指定被代理对象的字节码
			Callback:用于提供增强的代码
				它是让我们写如何代理。我们一般都是写一个该接口的实现类MethodInterceptor,通常情况下都是匿名内部类,但不是必须的。
				此接口的实现类都是谁用谁写

10.spring中基于XML的AOP配置步骤

1.把通知Bean也交给spring来管理
2.使用aop:config标签表明开始AOP的配置
3.使用aop:aspect标签表明配置切面
	id属性:是给切面提供一个唯一的标识
	ref属性:是指定通知类bean的id
4.在aop:aspect标签的内部使用对应标签来配置通知的类型
		我们现在示例是让printLog方法在切入点方法执行之前执行,所以是前置通知
		aop:before:表示配置前置通知
			method属性:用于指定Logger类中哪个方法是前置通知
			pointcut属性:用于指定切入点表达式,该表达式的含义指的是对业务层中哪些方法增强

11.切入点表达式的写法

关键字:execution(表达式)
表达式:
	访问修饰符  返回值  包名.包名.包名...类名.方法名(参数列表)
标准的表达式写法:
	public void eg.service.impl.AccountServiceImpl.saveAccount()
访问修饰符可以忽略
	void eg.service.impl.AccountServiceImpl.saveAccount()
返回值可以使用通配符,表示任意返回值
	* eg.service.impl.AccountServiceImpl.saveAccount()
包名可以使用通配符,表示任意包,但是有几级包,就需要写几个*
	* *.*.AccountServiceImpl.saveAccount()
包名可以使用..表示当前包及其子包
	* *..AccountServiceImpl.saveAccount()
类名和方法名都可以使用*来实现通配
	* *..*.*()
参数列表
	可以直接写数据类型
		基本类型直接写名称   int
		引用数据类型写包名.类名的方式     java.lang.String
可以使用通配符表示任意类型,但是必须有参数
可以使用..表示有无参数均可,有参数可以是任意参数
全通配符写法
	* *..*.*(..)
实际开发中切入点表达式的通常写法
	切到业务层实现类下的所有方法
		* eg.service.impl.*.*(..)

12.配置通知的类型,并且建立通知方法和切入点方法的关联

1.配置前置通知:在切入点方法执行之前执行&ndash;&gt;
    <aop:before method="beforePrintLog" pointcut="execution(* eg.service.impl.*.*(..))"></aop:before>
    <aop:before method="beforePrintLog" pointcut-ref="pt1"></aop:before>
2.配置后置通知:在切入点方法正常执行之后执行,它和异常通知永远只能执行一个
    <aop:after-returning method="afterReturningPrintLog" pointcut-ref="pt1"></aop:after-returning>
3.配置异常通知:在切入点方法执行产生异常之后执行。它和后置通知永远只能执行一个
    <aop:after-throwing method="afterThrowingPrintLog" pointcut-ref="pt1"></aop:after-throwing>
4.配置最终通知:无论切入点方法是否正常执行他都会在其后面执行
    <aop:after method="afterPrintLog" pointcut-ref="pt1"></aop:after>
5.环绕通知问题:
	当我们配置了环绕通知之后,切入点方法没有执行,而通知方法执行了
	分析;通过对比动态代理中的环绕通知代码,发现动态代理的环绕通知有明确的切入点方法调用,而我们的代码中没有
	解决:Spring框架为我们提供了一个接口:ProceedingJoinPoint。该接口有一个方法proceed(),此方法就相当于明确调用切入点方法
		该接口可以作为环绕通知的方法参数,在程序执行时,spring框架会为我们提供该接口的实现类供我们使用
	Spring中的环绕通知:它是spring框架为我们提供的一种可以在代码中手动增强方法何时执行的方式

13.spring中的声明式事务控制配置

1.基于注解的声明式事务控制配置步骤
	1.配置事务管理器
    2.开启spring对注解事务的支持
    3.在需要事务支持的地方使用@Transactional注解
2.基于XML的声明式事务控制配置步骤
    1.配置事务管理器
    2.配置事务的通知
        此时我们需要导入事务的约束 tx名称空间和约束,同时也需要aop的
        使用tx:advance标签配置事务通知
            属性:
                id:给事务通知起一个唯一的标识
                transaction-manager:给事务通知提供一个事务管理器引用
    3.配置AOP中的通用切入点表达式
    4.建立事务通知和切入点表达式的对应关系
    5.配置事务的属性
        是在事务的通知tx:advice标签的内部
		isolation=""用于指定事务的隔离级别。默认值是DEFAULT,表示使用数据库的默认隔离级别
		propagation=""用于指定事务的传播行为。默认值是REQUIRED,表示一定会有事务,增删改的选择。查询方法可以选择SUPPORTS
		read-only=""用于指定事务是否只读,只有查询方法才能设置为true。默认值是false,表示读写。
		timeout=""用于指定事务的超时时间,默认值是-1,表示永不超时,如果指定了数值,以秒为单位
		rollback-for=""用于指定一个异常,当产生该异常时,事务回滚,产生其他异常时,事务不回滚。没有默认值,表示任何异常都回滚
		no-rollback-for=""用于指定一个异常,当产生该异常时,事务不回滚,产生其他异常时事务回滚,没有默认值,表示任何异常都回滚
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值