Spring简单入门
IOC 控制反转(DI:依赖注入)
控制反转和依赖注入其实就是一回事,这里先讲一下,后面我们会详细解释
- 搭建spring环境
下载jar包
地址:http://maven.springframework.org/release/org/springframework/spring/
Dist存放二进制文件
Docs存放说明文档
此次我们下载的版本是 spring-framework-4.3.9.RELEASE-dist.zip在其中的lib文件夹目录下包含许多有用的jar包
现在需要使用的5+1个jar包
- spring-aop-4.3.9.RELEASE.jar 开发Aop特性需要的jar
- spring-beans-4.3.9.RELEASE.jar 处理bean的jar <bean>
- spring-context-4.9.RELEASE.jar 处理spring上下文的jar <context>
- spring-core-3.9.RELEASE.jar spring的核心jar 必需
- spring-expression-4.3.9.RELEASE.jar spring的表达式所需要的jar
将这些jar包放到类路径里面去
以及第三方提供的日志jar
- commons-logging-1.1.1.jar 2
- 编写配置文件
为了编写时有些提示,自动生成一些配置信息,可以给eclipse增加一些支持spring的插件:spring tool suite(地址:https://spring.io/tools/sts/all) 版本和eclipse前面版面的两个数字尽量相同,第三位不那么重要在eclipse中help的选项install new software->add 安装时需要联网,下载一些约束信息以及一些其他的资料,然后在eclipse中安装
方式二:如果插件无法使用,可以直接下载带插件的sts工具(就相当于一个自动集成了sts的eclipse工具),专门用于开发spring的sts(地址:https://spring.io/tools/sts/),其中eclipsec.exe时一个调试工具,主要便些程序的地方在sts.exe
一个beans本身就是一个xml文件,不过这个xml文件太空了,所以我们需要对xml进行一些文件配置,xml文件的名字一般是applicationContext.xml,可以在namespace中勾选配置文件,在xml文件中便会自动添加
新建:bean configuration 名字applicationcontext.xml
- 正式来开发程序(IOC)
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Student student = (Student)context.getBean("student");
可以发现springIOC容器不仅给我们new了对象,而且还帮我们赋了值
SpringIOC的发展史
Student student = new Student();
Student.setXxx();
2. 简单工厂
3. IoC(超级工厂)
SpringIOC被称为一个超级工厂,能存放任何一个对象,对象都存放在xml文件中
IOC:控制反转
反转的是获取对象的方式
以前我们获取对象的方式是直接new一个对象,自己去产生一个对象,
现在我们可以直接通过容器的getBean方法便可以获得想要的对象,直接从容器中拿对象就行
IOC容器简单的说其实就是一个applicationContext.xml配置文件
为了更加清晰的理解IOC,Spring在一次大会上更名为DI(依赖注入)
控制反转:将创建对象,属性赋值的方式进行了翻转,从new,getXXX(),翻转为了从SpringIOC容器中getbean()
依赖注入:将属性值注给了属性,又将属性注给了bean,又将bean注给了IOC容器
总结:DI/IOC 无论需要什么,都什么直接去SpringIOC容器中获取,而不需要自己操作
因此之后的IOC分为两步:1.先给SpringIOC容器中存放对象并赋值 2.拿
DI:依赖注入,·
Teacher:
Course: cname teacher
IOC容器赋值:如果是简单类型(8个基本+String),用val; 如果是对象类型,直接用ref,ref指向容器中另一个对象的id值,因此实现了对象与对象之间的依赖关系
Context.getBean(需要获取的ID值)
依赖注入的三种方式
- Set注入:通过set方法赋值
赋值,默认使用的是setXXX()方法
依赖注入底层是通过反射实现的
2. 构造器注入:通过构造方法赋值
<constructor-arg value="ls" type="String" name="name"></constructor-arg>
需要注意:如果<constructor-arg>的顺序与构造方法参数的顺序不一致,则需要通过type或者index或者name指定
3: 通过p命名空间
- 引入p命名空间
Xmlns:p=http://www.springframework.org/schema/p
<bean id="course" class="org.lanqiao.entity.Course" p:courseHour="300" p:courseName="hadoop" p:teacher-ref="teacher">
简单类型
P:属性名=”属性值”
引用类型
P:属性名-ref=”引用的ID”
注意:
无论是String还是int/short/long,在赋值的时候都是value=”值”,因此建议此种情况配合name/type进行区分
示例:
注入各种集合 类型的数据:List Set map properties
Set list 数组各自都有自己的空间<set><array>,但是也可以混着用
给对象类型赋值null : 注意没有value
<property>
<null/>
</property>
在ioc中定义bean的前提: 该bean的类必须提供了无参构造
自动装配:约定优于配置
自动装配只适合与引用类型,对简单类型无效
自动装配:<bean … class=”…” autowire=”byName”>
自动寻找; 其他bean的id值=该类的属性名
就直接将该类直接注入到这个对象的属性中来
Autowire=”byName|byType|constructor|no”
byName其实就是byId
autowire=”byType” 根据类型自动装配
byType:其他bean的类型(class)是否与该类的ref的属性是否一致 ,若存在多个类型一致的对象,程序将直接报错(当前ioc容器中只能有一个bean满足条件)
constructor:其他bean的类型(class)是否与该course类的构造方法参数的类型一致,此种方式的本质就是byName
可以在头文件中,一次性将该ioc容器的所有bean 统一设置成自动装配
<beans xmlns=http://www.springframework.org/schema/beans…
Default-autowire=”byName”>
自动装配虽然可以减少代码量,但是会降低程序的可读性,使用时需要谨慎点
使用注解定义bean: 通过注解的形式 将bean以及相应的属性值 放入ioc容器
<context:component-scan base-package="org.lanqiao.dao"></context:component-scan>Spring在启动的时候,会扫描base-package在该包中扫描所有类,查找这些类是否有注解,如果有,则将其纳入Ioc容器中,
@Component细化:
Dao层注解: @Repository
Service层注解: @Service
控制层注解: @Controller
使用注解实现声明式事务(事务L要么全部成功,要么全部失败)
目标:通过事务 使以下方法 要么全成功,要么全失败
Public void addStudent(){
//增加班级
//增加学生
//crdu
}
- jar包
spring-tx-4.3.9.RELEASE.jar
ojdbc7-12.1.0.2.jar
commons-dbcp.jar 连接池使用到数据源
commons-pool.jar 连接池
spring-jdbc-4.3.9.RELEASE.jar
aopalliance.jar
b 配置
jdbc\mybatis\spring
增加事务的命名空间
<!-- 增加对事务的支持 -->
<tx:annotation-driven transaction-manager="txManager"/>
将需要成为事务的方法前增加注解
@Transactional(readOnly=false,propagation=Propagation.REQUIRED) //声明为不是只读事务 设置为具有传播属性
2.AOP(面向切面编程)
一个普通的类->有特定功能的类
a.继承一个类 b.实现一个接口 c.加一个注解 d.配置
类->”通知“:实现接口
前置通知实现步骤:
- jar
aopalliance.jar
aspectjwearer.jar 是一个面向切面的框架,定义了AOP语法
- 配置
- 编写
Aop: 每当执行add()方法之前 自动执行的一个方法
Add(): 业务方法(IStudentService.addStudent (Student student) )
Log(): 自动执行的通知,即aop前置通知
Before(): 前置通知方法
后置通知:
a:通知类 实现普通接口
b:业务类 业务方法 StudentServiceImpl中的addStudent()
c:配置:
将业务类,通知 纳入springIOC容器
定义切入点(一端),定义通知类(另一端),通过pointcut-ref将两端进行相连
异常通知:
根据异常通知接口的定义可以发现,异常通知的实现类,必须编写以下方法void afterThrowing([Method, args, target], ThrowableSubclass);
[]中的参数代表可选,要么都有,要么都没
即a: void afterThrowing(Method, args, target, ThrowableSubclass);
B: void afterThrowing(ThrowableSubclass);
环绕通知:在目标方法的前后 异常发生时 最终等各个地方都可以进行的通知 最强大的一个通知 可以获得目标方法的全部控制权
可以获得目标方法的全部控制权(目标方法是否执行 执行之前 执行之后 参数 返回值等)
在使用环绕通知时:目标方法的一切信息都可以通过invocation参数获取到
环绕通知底层是通过拦截器实现的
二:实现注解实现通知 aop
A:jar包
与实现接口的方式相同
B:配置
将业务类 通知 纳入IOC容器
开启对注解的支持 <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
默认注解是不支持AOP
C:编写
通知:
@Aspect //声明该类是一个通知
Public class LogBeforeAnnotation(){
}
//注意:通过注解形式 将对象增加到IOC容器时,需要设置扫描器<context:component-scan base-package="org.lanqiao.aop"></context:component-scan>
扫描器会将指定的包中的 @Component @Service @Respository @Controller修饰的类产生的对象增加到IOC容器中
通过注解形式实现的AOP,如果想获取目标对象的一些参数,则需要使用一个对象:
@Aspect不需要加入扫描器,只需要开启即可: <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
通过注解形式实现的AOP,如果想获取目标对象的一些参数,则需要使用一个对象:JointPoint
注解形式的返回值
A:声明返回值的参数名
@AfterReturning( pointcut="execution(public void org.lanqiao.service.StudentServiceImple.addStudent(org.lanqiao.entity.Student))",returning="returningValue") //returning声明接收值得参数名
public void myAfter(JoinPoint jp,Object returningValue) {
//方法结束后,程序自动将返回值放入Object对象中
System.out.println("注解形式-后置通知,返回值:" + returningValue);
}
以上声明返回值的参数名就叫returningValue
注解实现AOP时,通知方法的参数不能多也不能少
实现接口形式 注解形式 只捕获声明的特定类型的异常 而其它类型不捕获
三:通过配置将类变成一个通知
基于Schema 其实就是基于头文件的配置
需要一个AOP的命名空间
类似于实现接口的方式
接口方式public class LogAfter implements AfterReturningAdvice {}
Schema方式的通知
- 编写一个普通的类public class LogAfter{}
- 将该类通过配置,转为一个通知
如果要获取目标对象信息
注解 Schema:JoinPoint
接口:Object returnValue, Method method, Object[] args, Object target
Schema形式和注解形式很像,不同形式就是注解形式使用了注解@After,Schema进行了多余的配置
Java Web程序: 如何初始化IOC容器?
启动Web,项目将IOC容器初始化
监听器:监听tomcat是否启动,一旦启动 立即实例化一个IOC容器对象
Public class MyListener extends/implements 监听器{
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
}