Spring快速入门

1.概述
1.1 什么是Spring

Spring是一个分层的Java SE/EE full-stack(一站式)轻量级开源框架,它以IOC和AOP为内核,使用基本的JavaBean来完成以前只可能由EJB完成的工作,取代了EJB臃肿、低效的开发模式。

Spring致力于Java EE应用各层的解决方案,在表现层(它提供了Spring MVC以及与Struts框架的整合功能;在业务逻辑层可以管理事务、记录日志等;在持久层可以整合MyBatis、Hibernate、JdbcTemplate等技术。

1.2 优点
  • 非侵入式设计
  • 方便解耦、简化开发
  • 支持AOP
  • 支持声明式事务处理
  • 方便事务的测试(提供了对Junit的支持,额可以通过注解@Test方便地测试Spring程序)
  • 方便集成各种优秀框架
  • 降低Java EE API的使用难度
1.3 Web项目ApplicationContext容器的实例化

Web项目ApplicationContext容器的实例化由web服务器万册灰姑娘。在web.xml中添加如下配置

<!--指定Spring配置文件的位置,有多个配置文件时,以逗号分隔-->
<context-param>
    <param-name>contextConfigLocation</param-name>
    <!--Spring将加载spring目录下的applicationCOntext.xml文件-->
    <param-value>
        	classpath:spring/applicationContext.xml
    </param-value>
</context-param>
<!--指定以ContextLoaderListener方式启动Spring容器-->
<listener>
    <listener-class>
        org.springframework.web.context.ContextLoaderListener
    </listener-class>
</listener>
2.IOC(控制反转)
2.1 什么是IOC

在传统模式下,一个对象(调用者)需要调用另一个对象(被调用者,即被依赖对象)时,使用“new 被调用者”这种方式来创建对象。但是这种方式会导致调用者与被调用者之间的耦合性增加,不利于后期项目的升级和维护。

在IOC的思想下,对象的实例不再由调用者来创建,而是由容器(如Spring容器)来创建,容器会负责控制程序之间的关系,而不是由调用者的程序代码直接控制。这样,控制权由代码转移到容器,控制权发生了反转,这就是IOC(控制反转)

2.2 IOC与DI(依赖注入)

IOC是一种设计思想,而实现这种思想的两种方式包括依赖注入和依赖查找。

依赖注入:容器负责将被依赖对象赋值给调用者的成员变量,这相当于为调用者注入了它以来的实例,这就是依赖注入。

2.3 DI的实现方式
  • 1.属性setter方法注入
  • 2.构造方法注入
2.4 Bean
2.4.1 什么是Bean

Bean被实例的、组装的(及被Spring管理的)Java对象

2.4.2 Bean的配置

一般通过XML文件来注册并管理Bean之间的关系。XML配置文件的根元素是<beans>,<beans>中可包含多个 <bean>元素。

<?xml version="1.0" encoding="UTF-8"?>
<!-Spring XML配置文件的根元素是<beans>-->
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 		 http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--一个<beans>元素可包含多个<bean>子元素-->
    <!--
		属性含义:
		1.id:Bean的唯一标识符,Spring容器对Bean的配置、管理都通过该属性来完成
		2.name:Spring容器同样可以通过此属性对容器中的Bean进行配置和管理,可以为Bean指定多个名称,中间用			逗号或分号分隔
		如果在Bean中未指定id和name属性,则Spring会将class指当作id使用
		3.class:该属性指定Bean的具体实现类,它必须是一个完整的类名(类全限定名=包名+类名)
		4.scope:该属性用来设定Bean实例的作用域。默认值为"singleton"。后续会由详细解释
	-->
    <bean id="duke" name="duke" class="com.springinaction.springidol.Juggler" scope="singleton"> 
        <!-- constructor-arg:通过构造方法设置属性值 -->
        <constructor-arg value="15"></constructor-arg>
    </bean>
    
    <bean id="saxphone" class="com.springinaction.springidol.saxphone"></bean>
    <bean id="piano" class="com.springinaction.springidol.piano"></bean>  
    <!-- 为集合配置bean -->
    <bean id="hank" class="com.springinaction.springidol.OneManBand">
        <!--<property>:用于调用Bean中的setter方法完成属性赋值,从而完成以来注入。
			name属性:指定Bean实例中的相应属性名
			ref或value属性:指定参数值
		-->
        <property name="instruments">
            <list>
                <ref bean="piano" />
                <ref bean="saxphone" />
            </list>
        </property>
        <property name="instruments2">
            <map>
                <!--entry:用于设置map的一个键值对-->
                <entry key="piano" value-ref="piano"></entry>
                <entry key="saxphone" value-ref="saxphone"></entry>
            </map>
        </property>
    </bean>
</beans>

实例化Bean有三种方式:构造器实例化(通常情况下使用该中方式)、静态工厂实例化和实例工厂实例化。

2.4.3 Bean的作用域

使用scope可以指定Bean的作用域。

  • singleton:单例,该类型的Bean在容器中只有一个实例,无论有多少个Bean引用它,始终指向同一个对象。这是Spring容器默认的作用域。
  • prototype:原型,每次通过Spring容器获取的prototype定义的Bean时,容器都将创建一个新的Bean实例。

以上为常用的作用域,还有其他5种作用域:request、session、globalSession、application、websocket

2.4.4 Bean的声明周期

Spring容器可以管理singleton作用域的Bean的生命周期。而prototype作用域的Bean,Spring只负责创建,当创建了实例后,Bean的实例就交给客户端代码来管理,容器不再追踪其声明周期。

Bean的生命周期流程:

  • 1.实例化Bean
  • 2.设置属性值:利用依赖注入完成Bean中所有属性值的配置注入
  • 3.调用BeanNameAware的setBeanName()方法
  • 4.调用BeanFactoryAware的setBeanFactory()方法
  • 5.调用ApplicationContextAware的setApplicationContext()方法
  • 6.调用BeanPostProcessor的预初始化方法
  • 7.调用InitializingBean的afterPropertiesSet()方法
  • 8.调用订制的初始化方法
  • 9.调用BeanPostProcessor的后初始化方法
  • 10.Spring缓存池中准备就绪(singleton),将准备就绪的Bean交给调用者(prototype)
  • 11.Spring中Bean的销毁
2.2.5 Bean的装配方式

Bean的装配方式(Bean依赖注入的方式)有基于XML的装配基于注解的装配自动装配等。

基于Annotation(注解)的装配

注解作用
@Componnent一个泛化的概念,仅仅代表一个组件(Bean),可以作用在任何层次
@Repository用于将数据访问层的类表示为Spring的Bean
@Service用于将业务层的类表示为Spirng的Bean
@Controller用于将控制层的类表示为Spring的Bean
@Autowired通常用于标注在变量上,完成Bean的自动装配。默认按照Bean的类型进行装配
@Resource与Autowired类似,但默认按照Bean的实例名称进行装配
@Qualifier配合@Autowired使用,改变装配方式
//配置文件需要加入以下几句
<!--使用context命名空间,并在配置文件中开启相应的注解处理器-->
<context:annotation-config />
<!--对包路径下的所有Bean文件进行扫描-->
<context:component-scan base-package="需要装配的Bean所在包路径" />

3. AOP
3.1 什么是AOP

AOP(Aspect-Oriented Programming)表示面向切面编程,是对OOP的一种补充。

在传统的使用OOP思想进行事务处理、日志记录等操作时,一般通过组合或者继承的方法来达到代码的重用,但如果要实现某个功能(如日志记录),同样的代码仍然会分担到各个方法中。这样,如果想要关闭或者修改某个功能,就必须要修改所有的相关方法。这不但增加了开发人员的工作量,而且提高了代码的出错率。

AOP思想就是解决这类问题,AOP采取横向抽取机制,嫁给你分散在各个方法中的重复代码提取出来,然后再册灰姑娘徐编译或运行时,再将这些提取出来的代码应用到需要执行的地方。

3.2 AOP相关术语
  • Aspect(切面):指封装的用于横向插入系统功能(如事务、日志等)。该类要被Spring容器识别为切面,需要在配置文件中通过<bean>元素指定。
  • Joinpoint(连接点):指对象的一个操作,例如方法的调用或异常的抛出。在Spirng AOP容器中,连接点就是指方法的调用。
  • Pointcut(切入点):切面与程序流程的交叉点,即那些需要处理的连接点。通常在程序中,切入点指的是类或者方法名。
  • Advice(通知/增强处理):在定义好的切入点处所有执行的程序代码。可以将其理解为切面类中的方法,它是切面的具体实现。
  • Target Object(目标对象):所有被通知的对象,也称为被增强对象。
  • Proxy(代理):将通知应用到目标对象之后,被动态创建的对象。
  • Weaving(织入):将切面代码插入到目标对象上,从而生成代理对象的过程。
3.3 AOP框架
3.3.1 Spring AOP

动态代理指由AOP框架动态生成一个对象,该对象可以作为目标对象使用。Spring中的AOP代理,由JDK动态代理和CGLIB代理两种方式。

通知类型

  • 环绕通知:在目标方法执行前后实施增强,可以用于日志、事务管理等功能
  • 前置通知:在目标方法执行前实施增强,可以用于权限管理等功能
  • 后置通知:在目标方法执行实施增强,可以用于关闭流、上传文件、删除临时文件等功能
  • 异常通知:在目标方法抛出异常后实施增强,可以用于异常记录日志等功能
  • 引介通知:在目标中加入一些新的方法和属性。
3.3.2 AspectJ

AspectJ是一个基于JAVA语言的AOP框架,Spring在2.0后引入了对它的支持,并建议使用AspectJ开发AOP。

使用AspectJ实现AOP有两种方式,基于XML的声明式AspectJ和基于注解的声明式AspectJ。

//基于XML
<?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"
    xsi:schemaLocation="  
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-2.5.xsd  
            http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
    <!--目标类 -->
    <bean id="customerDao" class="com.mengma.dao.CustomerDaoImpl" />
    <!--切面类 -->
    <bean id="myAspect" class="com.mengma.aspectj.xml.MyAspect"></bean>
    <!--AOP 编程 -->
    <aop:config>
        <aop:aspect ref="myAspect">
            <!-- 配置切入点,通知最后增强哪些方法 -->
            <aop:pointcut expression="execution ( * com.mengma.dao.*.* (..))"
                id="myPointCut" />
            <!--前置通知,关联通知 Advice和切入点PointCut -->
            <aop:before method="myBefore" pointeut-ref="myPointCut" />
            <!--后置通知,在方法返回之后执行,就可以获得返回值returning 属性 -->
            <aop:after-returning method="myAfterReturning"
                pointcut-ref="myPointCut" returning="returnVal" />
            <!--环绕通知 -->
            <aop:around method="myAround" pointcut-ref="myPointCut" />
            <!--抛出通知:用于处理程序发生异常,可以接收当前方法产生的异常 -->
            <!-- *注意:如果程序没有异常,则不会执行增强 -->
            <!-- * throwing属性:用于设置通知第二个参数的名称,类型Throwable -->
            <aop:after-throwing method="myAfterThrowing"
                pointcut-ref="myPointCut" throwing="e" />
            <!--最终通知:无论程序发生任何事情,都将执行 -->
            <aop:after method="myAfter" pointcut-ref="myPointCut" />
        </aop:aspect>
    </aop:config>
</beans>

基于注解的声明式AspectJ

注解描述
@Aspect定义一个切面
@Pointcut用于定义一个切入点表达式。表达式格式为execution(* com.*.*(…)),excution(返回值 包名.类名.方法名(参数)),*代表统配。在使用时还需定义一个返回指为void,且方法体为空的普通的方法。
@Before定义前置通知。
@AfterReturning定义后置通知
@Around定义环绕通知
@AfterThrowing定义异常通知来处理程序中未处理的异常
@After定义最终final通知,不管是否异常,该通知都会执行
@DeclareParents定义引介通知
//案例
package com.itheima.aspectj.annotation;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
/**
 * 切面类,在此类中编写通知
 */
@Aspect
@Component
public class MyAspect {
	// 定义切入点表达式
	@Pointcut("execution(* com.itheima.jdk.*.*(..))")//对象类所在位置
	// 使用一个返回值为void、方法体为空的方法来命名切入点
	private void myPointCut() {
	}

	// 前置通知
	@Before("myPointCut()")
	public void myBefore(JoinPoint joinPoint) {
		System.out.println("前置通知 : 模拟执行权限检查...,");
		System.out.println("目标类是:" + joinPoint.getTarget());
		System.out.println(",被植入增强处理的目标方法为:" + joinPoint.getSignature().getName());

	}
	//后置通知
	@AfterReturning("myPointCut()")
	public void myAfterReturning(JoinPoint joinPoint) {
	System.out.println("后置通知:模拟记录日志...,");
	
	System.out.println("被植入增强处理的方法为:");
	}
	//环绕通知
	@Around("myPointCut()")
	public Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {

		System.out.println("环绕开始:执行目标方法之前,模拟开启事务...");
		// 执行当前目标方法
		Object obj = proceedingJoinPoint.proceed();
		// 结束
		System.out.println("环绕结束:执行目标方法之后,模拟关闭事务...");
		return obj;
	}

	// 异常通知
	@AfterThrowing(value="myPointCut()",throwing="e")
	public void myAfterThrowing(JoinPoint joinPoint, Throwable e) {
		System.out.println("异常通知:" + "出错了" + e.getMessage());

	}

	// 最终通知
	@After("myPointCut()")
	public void myAfter() {

		System.out.println("最终通知:模拟方法结束后的释放资源...");

	}

}

同时需要在spring核心配置文件中开启注解扫描,启动注解声明式AspectJ支持

<!--启动基于注解的声明式AspectJ支持-->
<aop:aspectj-autoproxy />
4.Spring的数据库开发(包含事务管理)

针对数据库的操作,Spring框架提供了JdbcTemplate类,但是数据库操作一般交由MyBatis来做,Spring只进行数据源的配置事务管理

4.1 配置数据源等
<!--配置数据源-->
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
    <!--数据库驱动-->
    <property name="driverClassName" value=""/>
    <!--连接数据库的url-->
    <property name="rul" value=""/>
    <!--连接数据库的用户名-->
    <property name="username" value=""/>
    <!--连接数据库的密码-->
    <property name="password" value=""/>
    <!--最大连接数-->
    <property name="maxTotal" value=""/>
    <!--最大空闲连接-->
    <property name="maxIdle" value=""/>
    <!--初始化来凝结数-->
    <property name="initialSize" value=""/>
</bean>
<!--配置事务管理器,依赖于数据源-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>
<!--开启事务注解-->
<tx:annotation-driven transaction-manager="transactionManager" />
4.2 事务管理
4.2.1 事务管理的核心接口
  • PlatformTransactionManager:Spring提供的平台事务管理器,主要用于管理事务。提供了如下方法
    • getTransaction(TransactionDefinition definition):获取事务状态信息
    • commit(TransactionStatus status):提交事务
    • rollback(TransactionStatus status):回滚事务
  • TransactionDefinition:事务定于(描述)的对象,该对象中定义了事务规则,并提供了获取事务相关信息的方法
    • String getName():获取事务对象名称
    • int getIsolationLevel():获取事务的隔离级别
    • int getPropagationBehavior():获取事务的传播行为
    • int getTimeout():获取事务的超时时间
    • boolean isReadOnly():获取事务是否只读
  • TransactionStatus:事务的状态,它描述了某一时间点上事务的状态信息。
    • void flush():刷新事务
    • boolean hasSavepoint():获取是否存在保存点
    • boolean isCompleted():获取事务是否完成
    • boolean isNewTransaction():获取是否是新事务
    • boolean isRollbackOnly():获取是否回滚
    • void setRollbackOnly():设置事务回滚
4.2.2 事务管理的方式

Spring中的事务管理分为编程式事务管理和声明式事务管理。声明式事务管理是通过AOP技术实现的事务管理,其主要思想是将事务管理作为一个“切面”代码单独编写,然后AOP技术将事务管理的“切面”代码织入到业务目标类中。

4.2.3 声明式事务管理

声明式事务管理由两种实现方式,基于XML的方式和基于Annotation的方式

基于注解的方式

注解为**@Transactional**,可以标注在类或者方法上,标注在类上表示对类中所有方法起作。注解可配置参数如下:

参数描述
value指定需要使用的事务管理器,默认为"",别名为"transactionManager"
transactionManager指定事务的限定字符,默认为""
isolation指定事务的隔离级别,默认为底层事务的隔离级别
noRollbackFor指定遇到特定异常时强制不回滚事务
noRollbackForClassName指定遇到特定的多个异常时强制不回滚事务。属性值可以指定多个异常类名
propagation指定事务的传播行为,默认为Propagation.REQUIRED
read-only指定事务的是否只读,默认为false
rollbackFor指定遇到特定异常时强制回滚事务
rollbackForClassName指定遇到特定的多个异常时强制回滚事务。属性值可以指定多个异常类名
timeout指定事务的超时时长

基于注解的方式进行事务管理需要在配置文件中注册事务驱动,可见上面配置文件。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值