Spring基础学习
1.Spring是什么:Spring是一个开源框架,是一个IOC(DI)和AOP容器框架。
2.Spring具体描述:
1)轻量级:Spring是非侵入性的
2)依赖注入(DI---depengdency injection、IOC)
3)面向切面编程(AOP---aspect oriented programming)
4)容器:Spring是一个容器,因为它包含并且管理应用对象的生命周期
5)框架:Spring实现了使用简单的组件配置组合成一个复杂的应用,在Spring中可以使用XML和Java注解组合这些对象
6)一站式:在IOC和AOP的基础上可以整合各种企业应用的开源框架和优秀的第三方类库(实际上Spring自身也提供了展现层的SpringMVC和持久层的Spring JDBC)
3.IOC(Inversion of Control):其思想是翻转资源获取的方向。容器主动地将资源推送给它所管理的组件,组件所要做的仅是选择一种何时的方式来接受资源。这种行为也成为查找的被动形式。
4.Spring的IOC容器里配置Bean
1)id:Bean的名称
在IOC容器中必须是唯一的
若id没有指定,Spring自动将权限定性类名作为Bean的名字
id可以指定多个名字,名字之间可用逗号,分号,或空格分隔
5.Spring容器
1)在SpringIOC容器读取Bean配置创建Bean实例之前,必须对它进行实例化,只有在容器实例化后,才可以从IOC容器里获取Bean实例并使用。
2)Spring提供了两种类型的IOC容器实现:
BeanFactory:IOC容器的基本实现
ApplicationContext:提供了更多的高级特性,是BeanFactory的子接口
BeanFactory是Spring框架的基础设施,面向Spring本身;
ApplicationContext面向使用Spring框架的开发者,几乎所有的应用场合都直接使用ApplicationContext而非底层的BeanFactory
无论使用哪种方式,配置文件时是相同的
6.ApplicationContext的主要实现类
1)CalssPathXmlApplicationContext:从类路径下加载配置文件
2)FileSystemXmlApplicationContext:从文件系统中加载配置文件
7.ConfigurableApplicationContext扩展于ApplicationContext,新增加两个主要方法:refresh()和close(),让ApplicationContext具有启动、刷新和关闭上下文的能力
8.ApplicationContext在初始化上下文时就实例化所有单例的Bean
9.WebApplicationContext是专门为WEB应用而准备的,它允许从相对于WEB根目录的路径中完成初始化工作
10.getBean有几种方式:id或类型,注意类型要保证只有一个对象
11.依赖注入的方式(三种):
依赖注入:一个对象的某个方法完成需要依赖于另一个对象,就是依赖关系,构造器传入该对象就是构造器注入。
1)属性注入:通过set方法注入(最常用的方式)
2)构造器注入:使用构造器注入属性值可以指定参数的位置和参数的类型!以区分重载的构造器
3)工厂方法注入(很少使用,不推荐)
12.如果字面值包含特殊字符可以使用<![CDATA[]]>包裹起来
13.可以使用property的ref属性建立bean之间的引用关系
14.可以写内部Bean:不能被外部引用,只能在内部使用
15.可以赋null值:<constructor-arg><null/></constructor-arg>
16.为级联属性赋值:
<constructor-arg ref="car"></constructor-arg>
<property name="car.maxSpeed" value="250"></property>
17.集合属性:
1)在Spring中可以通过一组内置的xml标签(例如:<list><set><map>)来配置集合属性
2)list中可以通过<value>指定简单的常量值,通过<ref>指定其他Bean的引用,通过内置Bean指定内置Bean定义.通过<null/>指定空元素,甚至可以内嵌其他集合。
3)map的子标签用entry,再设置里面的key 和 value
4)Properties可以配置相关的数据,例如一些用户名和密码(Mysql),用props和它的子集prop
5)配置独立的集合bean,以供多个bean进行应用,需要导入util命名空间:
<util-list>
<bean></bean>
<bean></bean>
<bean></bean>
XXX
</util-list>
6)通过p命名空间为bean的属性赋值,需要先导入p命名空间,相对于传统的配置方式更加简洁
<bean id="h" class="com.nick.main.HelloWorld" p:namee="dd"></bean>
7)XML配置里的Bean自动装配的缺点:
不灵活,只能选择一种装配方式,一般情况下实际项目中很少会用到自动装配,明确清晰的配置文档更有说服力一些。
18.bean配置的继承:
1)使用bean的parent属性指定继承哪个bean的配置
2)抽象bean:bean的abstract属性为true的bean,这样的bean不能被IOC容器实例化,只能来被继承配置
3)若某一个bean的class属性没有指定,则该bean必须是一个抽象bean
4)并不会继承所有属性,例如:abstract和autowire
19.依赖Bean配置
1)Spring允许用户通过depends-on属性设定Bean前置依赖的Bean,前置依赖的Bean会在本Bean实例化之前创建好
2)如果前置依赖于多个Bean,则可以通过逗号,空格的方式配置Bean的名称
20.使用Bean的scope属性来配置bean的作用域:
1)subgleton:默认值,容器初始时创建bean实例。在整个容器的声明周期内置创建这一个bean
2)prototype:原形的。容器初始化时不创建bean的实例。而在每次请求时都创建一个新的Bean实例,并返回
21.使用外部化属性文件的属性
1)导入属性文件:<context:property-placeholder location="classpath:car.information"/>
2)在bean中设置属性(类似于EL表达式):<property name="name" value="${name}"></property>
22.Spring表达式语言:SpEl
1)Spring表达式语言(简称SpEL):是一个支持运行时查询和操作对象图的强大的表达式语言。
2)语法类似于EL:SpEL使用#{...}作为定界符,所有在大括号中的字符都将被认为是SpEL
3)SpEL为bean的属性进行动态赋值提供了便利
4)通过SpEL可以实现:
通过bean的id对bean进行引用:value="#{xxx}"
调用方法以及引用对象中的属性:value="#{xxx.xx}"
value="#{xxx.toString()}"
计算表达式的值
正则表达式的匹配
23.SpEL支持的运算符号
1)算数运算符:+ - * / %
2)加号还可以用作字符串连接
3)比较运算符:<> == <= >= It gt eq le ge
4)逻辑运算符:and or not |
5)if-else运算符:?:(if),?:(else)
6)支持正则表达式
7)调用静态方法或静态属性:通过T()调用一个类的静态方法,它将返回一个Class Object,然后再调用响应的方法或属性
<property name="initValue" value="#{T(java.lang.Math).PI}"></property>
24.IOC容器中Bean的生命周期方法
1)SpringIOC容器可以管理Bean的生命周期,Spring允许在Bean生命周期的特定点执行定制的任务
2)SpringIOC容器对Bean的生命周期进行管理的过程:
①通过构造器或工厂方法创建实例
②为Bean的属性设置值和堆其他Bean的引用
③调用Bean的初始化方法
④使用结束后,关闭容器时,调用Bean的销毁方法
3)Bean的声明里设置init-method和destroy-method属性,为Bean指定初始化和销毁方法.
25.配置bean的后置处理器
1)实现BeanPostProcessor接口,并提供具体实现
2)bean:bean实例本身
3)beanName:IOC容器配置的bean的名字
4)返回值:是实际上返回给用户的那个Bean,注意:可以在以上两个方法中修改返回的bean,甚至返回一个新的bean
5)配置bean的后置处理器不需要配置id,IOC容器自动识别是一个BeanPostProcessor
26.通过调用实例工厂方法创建Bean:
1)实例工厂方法:将对象的创建过程封装到另外一个对象实例的方法里,当客户端需要请求对象时,只需要简单的调用该实例方法而不需要关心对象的创建细节(工厂模式)
2)要声明通过实例工厂方法创建的Bean
①在bean的factory-bean属性里指定拥有该工厂方法的Bean
②在factory-method属性里指定该工厂方法的名称
③使用construtor-arg元素为工厂方法传递方法参数
27.实例工厂方法:即现需要创建工厂本身,再调用工厂的实例方法来返回bean的实例
28.自定义的FactoryBean
1)需要实现FactoryBean接口
2)通过FactoryBean来配置Bean的实例
3)class:指向Factory的全类名
4)property:配置FactoryBean的属性
5)实际返回的实例是FactoryBean的getObject()方法返回的实例!
29.在classpath中扫描组件
1)当在组件类上使用了特定的注解之后,还需要在Spring的配置文件中声明<context:component-scan>
2)base-package属性指定一个需要扫描的基类包,Spring容器将会扫描这个基类包里及其子包中的所有类.
3)当需要扫描多个包时,可以使用逗号分隔.
4)如果仅希望扫描特定的类而非基包下的所有类,可以使用resource-pattern属性过滤特定的类:如:resource-pattern="autowire/*class"/>
5)
①不包含哪些类<context:exclude-filter type="annotation" expression=""/>
②包含哪些类<context:include-filter type="annotation" expression=""/>
30.使用@Autowired自动装配Bean
1)@Autowired注解自动装配具有兼容类型的单个Bean属性
2)构造器,普通字段(即使是非public),一切具有参数的方法都可以引用@Autowired注解
3)加上(required=false),当Spring找不到匹配的Bean装配属性时,也不会抛出异常了
4)默认情况下,当IOC容器里存在多个类型兼容的Bean时,通过类型的自动装配将无法工作,此时可以在@Qualifiter已制定注入Bean的名称
5)@Autowired注解也可以引用在数组类型、集合属性、Map的属性上,此时Spring将会把所有匹配的Bean进行自动装配,注意应用Map时Bean的名称要当做键值
31.泛型依赖注入:注意过程,涉及到父类是泛型,子类具体在bean中自动注入的时候,能编程它原来的类型。
32.AOP(面向切面的编程):
1)问题:
①代码混乱:加入越来越多的非业务需求(日志和验证等),原有等等业务方法急剧膨胀,每个方法在处理核心逻辑的同时还必须兼顾其他多个关注点
②代码分散:以日志需求为例,只是为了满足这个单一需求,就不得不在多个模块(方法)里多次重复相同的日志代码,如果日志需求发生变化,必须修改所有模块。
2)解决:使用动态代理
代理设计模式的原理:使用一个代理将对象包装起来,然后用该代理对象取代原始对象,任何对原始对象的调用都要通过代理,代理对象决定是否以及何时将方法调用转到原始对象上。
33.AOP简介(Aspect-Oriented-Programming,面向切面的编程):
1)是一种新的方法论,是对传统OOP(Object-Oriented-Programming,面向对象编程)的补充
2)AOP的主要编程对象是切面(aspect),而切面模块化横切关注点
3)在应用AOP编程时,仍然需要定义公共功能,但可以明确的定义这个功能在哪里,以什么方式应用,并且不必修改受影响的类。这样一来横切关注点就被模块化到特殊的对象(切面)里
4)AOP的好处
①每个事物逻辑位于一个位置,代码不分散,便于维护和升级
②业务模块更简洁,只包含核心业务代码
34.SpringAOP
1)加入jar包
commons-logging-1.1.1.jar
org.aopalliance_1.0.0.v201105210816.jar
spring-aop-4.3.23.RELEASE.jar
spring-aspects-4.3.23.RELEASE.jar
spring-beans-4.3.23.RELEASE.jar
spring-context-4.3.23.RELEASE.jar
spring-core-4.3.23.RELEASE.jar
spring-expression-4.3.23.RELEASE.jar
aspectjweaver.jar
2)在配置文件中加入aop的命名空间
3)基于注解的方式
①在配置文件中加入如下配置
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
②把横切关注点的代码抽象到切面的类中
i.切面首先是一个IOC中的bean,即加入@Component注解
ii.切面还需要加入@Aspect注解
③在类中声明各种通知
i.声明一个方法
ii.在方法前加入@Before
iii.AspectJ支持5种类型的通知注解:
前置通知:@Before 在方法执行之前
后置通知:@After 在方法执行之后执行
返回通知:@AfterRunning 返回通知 在方法返回结果之后执行
异常通知:@AfterThrowing 异常通知 在方法抛出异常之后
环绕通知:@Around 围绕着方法执行
iiii.可以用 * 表示类型或包名
④可以在通知方法中声明一个类型为JoinPoint的参数.然后就能访问连接细节,如方法名称和参数值.
例子:
@Aspect
@Component
public class LoggingAspect {
//声明该方法是一个前置通知:在目标方法开始之前执行
@Before("execution(public int com.nick.spring.aop.impl.ArithmeticCalculator.*(int, int))")
public void beforeMethod(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
List<Object> args = Arrays.asList(joinPoint.getArgs());
System.out.println("The method "+methodName+" begins with "+args);
}
}
35.AspectJ
1)AspectJ:Java社区里最完整最流行的AOP框架
2)在Spring2.0以上版本中,可以使用基于AspectJ注解或基于XML配置的AOP
36.后置通知:@After
在目标方法执行后(无论是否发生异常),执行的通知
在后置通知中还不能访问目标方法执行的结果
37.返回通知:@AfterReturning
1)在方法正常结束后执行的代码
2)返回通知可以访问到方法的返回值!
3)例子:
@AfterReturning(value="execution(publicint com.nick.aop.ArithmeticCalculator.*(..))",returning="result")
public void afterReturning(JoinPoint joinPoint,Object result){}
38.
1)在目标方法出现异常时会执行的代码。
2)可以访问到异常对象,且可以指定在出现特定异常时在执行通知代码
3)例子:
@AfterThrowing(value="execution(public int com.nick.aop.ArithmeticCalculator.*(..))",throwing="e")
public void afterThrowing(JoinPoint,Exception e){}
39.@Order
1)@Order写在@Aspect的上面
2)有多个切面时,可以使用@Order注解指定切面的优先级,值越小优先级越高
40.@Pointcut
1)定义一个方法,用于声明切入点表达式,一般的,该方法中不再需要添入其他的代码
2)使用@Pointcut来声明切入点表达式
3)后面的其他通知直接使用方法名来引用当前的切入点表达式
4)例子:
@Pointcut("execution(public int com.nick.aop.ArithmeticCalculator.*(..))")
public void declareJoinPointExpression(){}
@Before("declareJoinPointExpression()")
public void beforeMethod(JoinPoint joinPoint){}
41.配置文件的方式配置AOP:
<aop:config>
<aop:pointcut expression="execution(* com.nick.spring.aop.xml.ArithmeticCalculator.*(int, int))" id="pointcut"/>
<aop:aspect ref="logging" order="1">
<aop:before method="before" pointcut-ref="pointcut"/>
<aop:after method="xxx"/>
<aop:after-returning method="xxx" pointcut-ref="xxx" returning="result"/>
<aop:after-throwing method="xxx" pointcut-ref="xxx" throwing="e"/>
<aop:around method="xxx" pointcut-ref="xxx" arg-names="xxx"/>
</aop:aspect>
</aop:config>
42.JdbcTemplate:使用这个来连接数据库,各种配置详见MySpring-04(千万注意导包要完整)
1)从数据库中获得一条记录,实际得到对应的一个对象
①注意不是调用queryForObject(String sql,Class<Employee> requiredType,Object... args)方法
②而需要调用queryForObject(String sql,RowMapper<Employee> rowMapper,Object... args)
③细节:
i.其中的RowMapper指定如何去映射结果集的行,常用的实现类为BeanPropertyRowMapper
ii.使用SQL中列的别名完成列名和类的属性名的映射。例如name,id等
iii.不支持级联属性,JdbcTemplate到底是一个JDBC的小工具,而不是ORM框架
④例子
public void testQuery() {
String sql = "SELECT ID,NAME,EMAIL FROM employees where ID = ?";
RowMapper<Employee> rowMapper = new BeanPropertyRowMapper<Employee>(Employee.class);
Employee employee = jdbcTemplate.queryForObject(sql, rowMapper, 4);
System.out.println(employee);
}
43.配置NamedParameterJdbcTemplate
1)该对象可以使用具名参数,其没有无参数的构造器,所以必须为其构造器指定参数
2)具名有两种方式,直接传入参数,或者传入一个对象
44.Spring的事务
1)事务管理是用来确保数据的完整性和一致性
2)事务是一些列的动作,要么全部完成,要么全部不起作用
3)事务的四个关键属性(ACID)
①原子性:要么全部没用,要么全部有用
②一致性:一旦所有事务动作完成,事务就被提交
③隔离性:可能有很多事务同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏
④持久性:一旦事务完成,无论发生什么系统错误,他的结果都不应该受到影响,通常情况下,事务的结果被写到持久化存储器中
45.实现Spring事务的三个步骤
1)xml文件中配置事务管理器
例子:
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
2)启动事务注解
<!-- 启用事务注解 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
3)在对应的方法上加事务的注解:Transactional
46.关于事务的传播行为:(针对当前事务被其他事务调用时)
1)REQUIRES(默认):事务中的事务要都完成
2)REQUIRES_NEW:表示该方法必须启动一个新事务,并在自己的事务内运行(要写在当前事务下,即里面被调用的事务)
47.事务的隔离性:isolation
1)指定事务的隔离级别,最常用的取值为READ_COMMITTED
2)默认情况下Spring的声明式事务对所有的运行时异常进行回滚,也可以通过对应的属性进行设置,通常情况下使用默认即可
48.事务的readOnly:指定事务是否为只读,表示这个事务只读取数据但不更新数据
这样可以帮助数据库引擎优化事务,若真的是一个只读取数据库值的方法,应设置readOnly=true
49.timeout 指定强制回滚之前事务可以占用的时间
例子:@Transactional(propagation = Propagation.REQUIRES_NEW,
noRollbackFor = {UserAccountException.class},
timeout = 3,
readOnly = false
)
50.通过配置XML文件的形式配置Spring的事务
1)配置事务管理器
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
2)配置事务属性
<tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><!-- 根据方法名指定事务属性 --><tx:method name="purchase" read-only="true"/><tx:method name="get*" propagation="REQUIRED_NEW"/><tx:method name="*"/>
</tx:attributes>
</tx:advice>
3)配置事务切入点,以及把事务切入点和事务属性关联起来
<aop:config>
<aop:pointcut expression="execution(* com.nick.jdbc.tx.xml.BookShopServiceDaoImpl.*(..))"
id="txPointCut"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
</aop:config>
51.关于整合Hibernate和Struts2
Spring(P30-P36)