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发展史:
- new方式创建对象
Student student = new Student();
student.setXxx();
- 简单工厂
- 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.依赖注入的三种方式
- set方式注入
赋值,默认使用的是set方法;
依赖注入底层是通过反射实现 - 构造器注入(通过构造方法赋值)
<constructor-arg value="c" type="String" name="courseName" index="0"></constructor-arg>
需要注意:如果参数的顺序与构造方法顺序不一致,可以通过type,index或者name来指定。
- 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[各种符号]]> 原义输出符号
实体引用 | 表示符号 |
<; | < |
&; | & |
>; | > |
赋空值 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.实现步骤
- 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 - 配置
jdbc\mybatis\spring
增加事务的命名空间:xmlns:tx=“http://www.springframework.org/schema/tx”
<!-- 增加对事务的支持 -->
<tx:annotation-driven transaction-manager="txManager"/>
- 使用
将需要成为事务的方法前增加注解:
@Transactional(readOnly = false,propagation = Propagation.REQUIRED)
8.AOP:面向方面编程
一个普通的类–>有特定功能的类
- 继承一个类
- 实现一个接口
public class MyFilter extends/implents Xx{
}
- 添加注解
public class Xxx{
@Test
} - 配置
通过接口实现
类–>通知
以前置通知为例的步骤:
- jar
aopaliance.jar
aspectjweaver.jar - 配置
- 编写
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进行了配置