Spring入门基础知识

  • Spring
  • 1.搭建Spring环境
  • 2.编写配置文件
  • 3.开发Spring程序(IOC)
  • 4.SpringIOC发展史:
  • 5.依赖注入的三种方式
  • 6.AOP:例子要求
  • 7.实现步骤
  • 8.AOP:面向方面编程
  • 通过接口实现
  • 通过注解实现aop
  • 通过配置实现aop 类->通知


Spring

1.搭建Spring环境

下载jar包:
http://maven.springframework.org/release/org/springframework/spring springframework/spring/4.3.9.RELEASE-dist.zip
开发Spring至少需要使用的jar:(5+1)
spring-aop.jar :开发AOP特性时需要的jar
spring-beans.jar:处理Bean的jar
spring-context.jar:处理Spring上下文的jar
spring-core.jar:开发Spring的核心jar
spring-expression.jar:Spring表达式
三方提供的日志jar
common-logging.jar

2.编写配置文件

为了编写配置信息时有提示,自动生成一些配置信息
方式一:增加sts插件
可以给eclipse增加支持的spring插件:spring tool suite
(https://spring.io/tools/sts/all)
下载springsource-tool-suite-3.9.9.RELEASE-e4.12.0-updatesite.zip然后在eclipse中安装:
Help->Install new SoftWare… -Add
方式二:直接下载sts工具
https://spring.io/tools/sts/

新建配置文件:bean configuration… -applicationContext.xml

3.开发Spring程序(IOC)

//Spring上下文对象
		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		//执行从springIOC容器中获取一个id为student的对象
		Student student = (Student)context.getBean("student");

可以发现,springioc容器帮助我们new了对象,并且给对象赋了值

4.SpringIOC发展史:

  1. new方式创建对象
Student student = new Student();
student.setXxx();
  1. 简单工厂
  2. IOC(超级工厂)
    IOC(控制反转)也可以称为DI(依赖注入):
    控制反转:将创建对象属性值的方式进行反转,从new,setXX()反转为从springIOC容器getBean()

依赖注入:将属性值注入给了属性,将属性注入给bean,又将bean注入给ioc容器

总结:ioc/di 无论要什么对象,都可以去springioc中获取,而不需要自己操作(new,setXxx)

因此之后ioc分为两步:1.献给springioc中存放对象并赋值 2.拿

DI:依赖注入
Teacher
Course:cname, teacher

IOC容器赋值:如果是简单类型(8个基本+String),value;
如果是对象类型,ref=“需要引用的id值”,因此实现了对象与对象的依赖关系

context.getBean(需要获取的bean的id)

5.依赖注入的三种方式

  1. set方式注入
    赋值,默认使用的是set方法;
    依赖注入底层是通过反射实现
  2. 构造器注入(通过构造方法赋值)
<constructor-arg value="c" type="String" name="courseName" index="0"></constructor-arg>

需要注意:如果参数的顺序与构造方法顺序不一致,可以通过type,index或者name来指定。

  1. 3.p命名空间
    引入命名空间:xmlns:p=“http://www.springframework.org/schema/p”
<bean id="course" class="priv.alisa.entity.Course" p:courseName="java" p:courseHour="200" p:teacher-ref="teacher">

简单类型:p:courseHour=“200”
引用类型:p:teacher-ref=“teacher”(引用的id)
注意:p赋值的时候要有空格
注意:无论是String还是Int/short/long,在赋值时都是value=“值”,因此建议这种情况配合name/type进行区分
示例:注入各种集合数据类型:List,Set,map,properties

<bean name="allCollection" class="priv.alisa.entity.AllCollection">
		<property name="myArry">
			<array>
				<value>足球1</value>
				<value>篮球1</value>
				<value>乒乓球1</value>
			</array>
		</property>
		<property name="myList">
			<list>
				<value>足球2</value>
				<value>篮球2</value>
				<value>乒乓球2</value>
			</list>
		</property>
		<property name="myMap">
			<map>
				<entry>
					<key>
						<value>foot3</value>
					</key>
					<value>足球3</value>
				</entry>
				<entry>
					<key>
						<value>basket3</value>
					</key>
					<value>篮球3</value>
				</entry>
				<entry>
					<key>
						<value>pp3</value>
					</key>
					<value>乒乓球3</value>
				</entry>
			</map>
		</property>
		<property name="myProps">
			<props>
				<prop key="foot4">足球4</prop>
				<prop key="basket4">篮球4</prop>
				<prop key="pp4">乒乓球4</prop>
			</props>
		</property>
		<property name="mySet">
			<set>
				<value>足球5</value>
				<value>篮球5</value>
				<value>乒乓球5</value>
			</set>
		</property>
	</bean>

set 数组和list各自都有自己的标签,三个可以混着使用,建议对号入座
子元素:<![CDATA[各种符号]]> 原义输出符号

实体引用

表示符号

&lt;

<

&amp;

&

&gt;

>

赋空值 null 注意:没有value

<property name="name">
			<null/>
		</property>

赋空值 “”

<property name="name">
			<value></value>
		</property>

或者:

<property name="name" value=""></property>

在ioc中定义bean的前提:必须提供无参构造

自动装配:(只适用于ref类型)使用set方式注入
约定优于配置

<bean id="course" class="priv.alisa.entity.Course" autowire="byName|byType|constructor">

byName本质byId
自动寻找bean的id值=类的属性名:自动装配
byType:其他bean类型(class)是否与该Course类的ref属性类型一致 弊端:两个teacher报错(此种方式必须满足一个条件:只有一个)
constructor:寻找其他bean的类型(class)是否与该course类的构造方法参数的类型一致,本质就是byType
将全部的bean统一设置自动装配
头文件:default-autowire=“byName”
自动装配虽然可以减少代码量,但是会降低代码可读性,谨慎使用

使用注解定义bean:通过注解的形式将bean以及相应的属性值放入ioc容器

<!-- 配置扫描器 -->
<context:component-scan base-package="priv.alisa.dao"></context:component-scan>
启动时,会根据base-package在包中扫描所有类,查找这些类是否有注解

@Component(“studentDao”),如果有则将该类加入ioc容器
@Component细化:
dao层注解:@Repository
service层注解:@Service
控制器层:@Controller

6.AOP:例子要求

使用注解实现事务(声明式事务)
目标:通过事务使以下方法要么全成功,要么全失败
public void addStudent(){
//增加班级
//增加学生
//crdu
}

7.实现步骤

  1. jar包
    spring-tx-4.3.9.RELEASE.jar
    mysql-connector-java-5.1.30.jar
    commons-dbcp.jar 连接池使用的数据源
    commons-pool.jar 连接池
    spring-jdbc-4.3.9.RELEASE.jar
    aopalliance.jar
  2. 配置
    jdbc\mybatis\spring
    增加事务的命名空间:xmlns:tx=“http://www.springframework.org/schema/tx”
<!-- 增加对事务的支持 -->
<tx:annotation-driven transaction-manager="txManager"/>
  1. 使用
    将需要成为事务的方法前增加注解:
    @Transactional(readOnly = false,propagation = Propagation.REQUIRED)

8.AOP:面向方面编程

一个普通的类–>有特定功能的类

  • 继承一个类
  • 实现一个接口
    public class MyFilter extends/implents Xx{

}

  • 添加注解
    public class Xxx{
    @Test
    }
  • 配置

通过接口实现

类–>通知
以前置通知为例的步骤:

  1. jar
    aopaliance.jar
    aspectjweaver.jar
  2. 配置
  3. 编写
    aop:每当执行add()之前自动执行一个方法log();
    add(IStudentService.java中的 addStudent());业务方法
    before();自动执行的通知方法,即aop前置通知。

后置通知:
a.通知类,普通类实现接口变成通知类

public class LogAfter implements AfterReturningAdvice

b.业务类、业务方法
StudentServiceImpl 中的 addStudent()
c.配置
将业务类(切入点)纳入springIOC容器

<!-- addStudent()所在类,切入点 -->
	<bean id="studentService" class="priv.alisa.service.impl.StudentServiceImpl">
		<property name="studentDao" ref="studentDao"></property>
	</bean>

将通知(切面)纳入ioc容器

<!-- 配置通知所在类,切面 -->
	<bean id="logAfter" class="priv.alisa.aop.LogAfter"></bean>
将业务类(切入点)和通知(切面)连接
	<aop:config>
		<!-- 切入点 -->
		<aop:pointcut expression="execution(public void priv.alisa.service.impl.StudentServiceImpl.addStudent(priv.alisa.entity.Student))" id="pointcut2"/>
		<!-- 连线  切面  切入点 -->
		<aop:advisor advice-ref="logAfter" pointcut-ref="pointcut2"/>
	</aop:config>

异常通知:
根据异常通知接口的定义类发现,异常通知的实现类必须编写以下方法:

void afterThrowing([Method, args, target], ThrowableSubclass):

意思是:

void afterThrowing(ThrowableSubclass)//一个参数
		void afterThrowing(Method, args, target, ThrowableSubclass)//四个参数

例如:

public void afterThrowing(Method method,Object args, Object target, Throwable ex)

环绕通知:在目标方法的前后、异常发生时、最终等各个地方都可以进行的通知,最强大的通知,可以获取目标方法的全部控制权。
控制权(目标方法是否执行、执行之前、执行之后、参数、返回值等)(本质:拦截器,通过拦截器实现)
在使用环绕通知时,目标方法的一切信息都可以通过invocation参数获取到
通过invocation.proceed();控制目标方法执行
环绕通知可以改目标方法的返回值

通过注解实现aop

a.jar
与实现接口的方式相同
b.配置
将业务类、通知纳入springIoc容器
开启注解对AOP的支持

<!-- 开启注解对AOP的支持 -->
	<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

业务类addStudent - 通知

c.编写
通知:

@Aspect //声明该类是一个通知
	public class LogBeforeAnnotation {

	}

注意:@Component(“logAnnotation”)需要扫描器

<context:component-scan base-package="priv.alisa.aop"></context:component-scan>

扫描器会将指定包中的@Component,@Service,@Repository,@Controller修饰的类产生的对象增加到ioc容器中

其他的不需要扫描器,例如:@Aspect
@Aspect只需要开启注解对AOP的支持

通过注解形式实现的aop如果想要获取目标对象的一些参数,则需要使用一个对象:JoinPoint
注解形式返回值问题:
需要声明返回值的参数名returning = “returningValue”

@AfterReturning(pointcut = "execution(public * addStudent(..))",returning = "returningValue")

注解形式实现aop时,通知的方法的参数不能多不能少

通过配置实现aop 类->通知

基于Schema配置(头文件)
引入命名空间:

xmlns:aop="http://www.springframework.org/schema/aop"

类似于实现接口的方式

接口方式:

public class LogAfter implements AfterReturningAdvice{...}

Schema方式:
a.编写一个普通类,public class LogAfter{…}
b.将该类通过配置转为一个“通知”

<!-- 将准备转为通知的类纳入ioc容器中 -->
	<bean id="LogSchema" class="priv.alisa.aop.LogSchema"></bean>
	
	<aop:config>
		<aop:pointcut expression="execution(public void priv.alisa.service.impl.StudentServiceImpl.addStudent(priv.alisa.entity.Student))" id="pcSchema"/>
		<aop:aspect ref="LogSchema">
			<!-- 连接线:连接业务addStudent()和通知before/afterReturning -->
			<aop:before method="before" pointcut-ref="pcSchema"/>
			<aop:after-returning method="afterReturning" pointcut-ref="pcSchema"/>
			<aop:after-throwing method="exception" pointcut-ref="pcSchema"/>
		</aop:aspect>
	</aop:config>

如果要获取目标对象的信息:
注解、schema:JoinPoint
接口:Method method, Object args, Object target, Throwable ex

schema形式和注解形式相似
不同之处:注解形式使用注解,schema进行了配置