第二章IOC
- Spring的第一个核心功能 ioc Ico:控制反转,是一个理论,思想
控制:创建对象,对象的属性赋值,对象之间的关系管理
反转:把原来的开发人员管理,创建对象的权限转移给代码之外的容器实现,由容器代替开发人员管理对象,代理对象
正转:由开发人员在代码中,使用new构造方法创建对象,开发人员主动管理对象
容器:是一个服务器软件,一个框架(Spring)
为什么要使用ioc:目的就是减少对代码的改成,也能实现不同的功能,实现解耦合
类似于servlet, servlet对象不是自己创建的,是Tomcat创建的,Tomat也称为容器(存放着servlet Listener Filter对象等)
什么样的对象放在容器中:dao类,service类,controller类,工具类
什么样的对象不放在容器中:实体类对象实体类数据是来自数据库中,servlet,listener,filter
- IoC的技术实现:
DI 是ioc的技术实现
DI:依赖注入,只需要在程序中提供要使用的对象名称就可以了,至于对象如果在容器中创建,赋值,查找都由容器内部实现
Spring是使用的di实现了ioc的功能,Pring底层创建对象,使用的是反射机制
Spring是一个容器,管理对象,给属性赋值,底层是反射机制
- pom加入spring的依赖 5.2.5版本
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.20.RELEASE</version>
</dependency>
Spring使用步骤 ①创建maven项目
②加入maven依赖
③创建类 impl是实现类(接口和他的实现类)
④创建Spring需要使用的配置文件,生命类的信息,这些类由Spring创建和管理,并通过spring的语法,完成属性的赋值
⑤测试Spring创建的
在resource中创建Spring需要使用的配置文件 XML Configuration File-Spring Config (跟mybatis的主配置文件差不多)
基于xml的di(在xml配置文件中完成对象的创建和属性的赋值)
创建容器就会自动执行setXXXX进行赋值
- DI:依赖注入,表示创建对象,给属性赋值
简单类型:spring中规定java的基本数据类型和string都是简单类型
Di的实现语法有两种: (经常改用xml,不经常改用注解)
①在spring的配置文件中,使用标签和属性完成,叫做基于XML的di实现
②使用spring中的注解,完成属性赋值,叫做基于注解的di实现
DI的语法分类:
①set注入(设置注入):spring调用类的set方法,在set方法可以实现属性的的赋值
- 简单类型的set注入
<bean id=”” class=””>
<property name=”属性名字” value=”此属性的值”> (一个Property只能给一个属性赋值)
</bean>
- 引用类型的set注入:spring调用类的set方法
<bean>
<property name=”属性名称” ref=”bean的id(对象的名称)”/> (会找set属性名称的方法执行)
</bean>
②构造注入,spring调用类的有参构造方法,创建对象。在构造方法中完成给属性赋值
构造注入使用<constructor-arg>标签 (有这个标签会执行有参构造方法,否则会执行无参构造方法)
<bean>
<constructor-arg name=”某形参名” value=”传的值”></constructor-arg>
</bean>
一个标签表示构造方法的一个参数,如果有三个参数那么要有三个这个标签
标签的属性: name:表示构造方法的形参名
或者
Index:表示构造方法的参数的位置,参数从左往右的位置是0,1,2..
value:构造方法的形参类型是简单类型的,使用value
ref:构造方法的形参类型是引用类型的,使用ref
- 引用类型的自动注入:spring框架可以根据某些规则给引用数据类型进行赋值
(普通数据类型必须要手动赋值)
①byName(按名称注入):java类中引用类型的属性名和spring容器中(配置文件)<bean>中的id名称一样,且数据类型是一样的,这样的容器中bean,spring能够赋值给引用类型
语法规则:<bean id=”xx” class=”yyy” autowire=” byName”>
简单类型属性赋值
</bean>
(某对象的引用数据类型的属性缺值了 就自动的去srpingxml文件中去找
如果是byName,就找id和自己属性名相同的bean对象,
如果是byType,就找class和自己类型相同或者是自己类型子类的bean对象)
(如果缺值的是一个接口,那么就通过byType,找class是自己实现类的bean对象)
②byType(按类型注入):java类中引用类型的数据类型和spring容器中(配置文件)<bean>中的class属性是同源关系,这样的容器中bean,spring能够赋值给引用类型
同源关系:1)java类中引用类型的数据类型和bean的class的值是一样的
- java类中引用类型的数据类型和bean的class的值父子类关系
- java类中引用类型的数据类型和bean的class的值接口和实现类关系的
语法规则:<bean id=”xx” class=”yyy” autowire=” byType”>
简单类型属性赋值
</bean>
- 多模块进行操作的时候,往往有多个springxml配置文件,而且还有一个主配置文件,主配置文件主要是用来包含其他配置文件的信息,一般不定义对象
语法:<import resource=”其他配置文件的路径”/>
关键字:”classpath:”表示类路径(target class文件所在的目录),
在spring的配置文件中要指定其他文件的位置,需要使用classpath,告诉spring到哪去加载读取文件
<import resource=”classpath:路径”/>
基于注解的di (通过注解完成对象的创建和属性赋值 不需要执行Set方法)
- 使用注解的步骤:①加入maven依赖 Spring-context,在你加入spring-context的同时,间接加入spring-aop的依赖,使用注解必须使用spring-aop依赖
②在类中加入spring的注解(多个不同功能的注解)
③在spring的配置文件中,加入一个组件扫描器的标签,说明注解在你的项目中的位置
④使用注解创建对象,创建容器ApplicationContext
学习的注解:@Component 这几个注解语法一致
@Respotory :用在持久层的上面,放在dao的实现类上面,表示创建dao对象,dao对象是能访问数据库
@Service:用在业务层类的上面,放在service的实现类上面,创建service对象,service对象是做业务处理的,可以有事务等功能的
@Controller:用在控制器的上面,放在控制器(处理器)的上面,创建控制器对象的,控制器对象能够接受用户提交的参数,显示请求的处理结果
@Value
@Autowired
@Resource
①@Component注解放在 需要被创建对象的类中 在类的上面@Component(value=”myStudent”) value值就是对象的名称也就是原id值 (value可以省略)
这个等同于<bean id=”myStudent” class=”xxxxxx...”></bean>
还需要在springxml主配置文件中加入组件扫描器的标签,就是告诉spring去某个包下找注解才能创建对象
声明组件扫描器(component-scan)
<context : component-scan base-package=”项目所在的包的位置”> component-scan工作方式:spring会扫描遍历base-package指定的包,把包中和子包中的所有类,找到类中的注解,按照注解的功能创建对象,或者给属性赋值
②@value 可以放在简单属性的上面为属性赋值 是直接赋值不会调用Set方法 或者放在setXXX方法上为该set属性赋值
@Component(“myText”) myText是id名 通过getbean获取对象
public class Text(){
@value(“张三”)
private String name;
@value(“20”)
private int age;
}
③@Autowired:springk框架提供的注解,实现引用类型的赋值
spring中通过注解给引用类型赋值,使用的是自动注入原理,支持byName,byType
@Autowired默认使用的是byType自动注入
@Autowired中还有个required属性,是一个boolean类型,默认true
required=true:表示引用类型赋值失败(如找不到该类型该名称等),程序报错,并终止执行
required=false:引用类型如果赋值失败,程序正常执行,引用类型值为Null
位置:1)在属性定义的上面,无需set方法,推荐使用
2)在set方法的上面
会自动去xml配置文件中去找bean 如果没有bean标签 就找组件扫描器 然后去找@Component(因为有它就是对象)然后找Type同源的
如果要使用byName自动注入 需要在属性上面再加入一个@Qualifier(“要寻找的对象的Id名”)
④@Resource:来自jdk中的注解,spring框架提供了对这个注解的功能支持,可以使用它给引用类型赋值,使用的也是自动注入原理,支持byName,byType.默认是byName
位置:1.在属性的上面,无需set方法 2.在set方法的上面
默认是byName,先使用byName自动注入(找和该属性名相同的id),如果注入失败则采用byType自动注入
- AOP
- 动态代理
实现方式:jdk动态代理,使用jdk中Proxy ,Method,InvocationHanderl创建代理对象,jdk 动态代理要求目标类必须实现接口
cglib动态代理,第三方的工具库,创建代理对象,原理是继承。通过继承目标类,创建子类,子类就是代理对象,要求目标类不能是final的,方法也不能是final的
- 动态代理的作用:
- 在目标类源代码(业务逻辑代码)不改变的情况下,增加功能
- 减少重复代码的使用
- 专注业务逻辑代码
- 解耦合,让你的业务功能和日志,事务非业务功能分离
- 什么时候考虑用aop技术①当你要给一个类增加功能且不修改原有类的时候
②你要给项目中的多个类,增加一个相同的功能(使用切入点表达式)
③给业务方法增加事务,日志输出
Aop:面向切面编程,基于动态代理的,可以使用jdk,cglib两种代理方式
Aop就是动态代理的规范化,把动态代理的实现步骤,方式都定义好了,让开发人员以一种统一的方式,用动态代理
A:切面,给你的目标类增加的功能,就是切面。像上面用的日志,事务都是切面
切面的特点:一般都是非业务方法,独立的
O:面向 P:编程
OOP:面向对象编程
常见的切面功能有日志,事务,统计信息,参数检查,权限验证
术语:目标类中的一个方法就是一个连接点joinpoint 多个方法就是pointcut是连接点的一个集合
advice表示切面的执行时间,是放在目标方法之前,还是目标方法之后
AOP的技术实现框架:1.spring:spring在内部实现了aop规范,能做aop的工作,但是由于spring的aop比较笨重 所以很少用
- aspectJ:一个开源的专门做aop的框架 spring框架中集成了aspectJ框架
aspectJ框架实现aop有两种方式: ①使用xml的配置文件
②使用注解,一般都使用注解,aspectJ有5个注解
- 学习aspectJ框架的使用
①切面的执行时间,这个执行时间在规范中叫做advice
在aspectJ框架中使用注解表示的,可以使用xml配置文件中的标签
1)@Before(在目标方法执行之前通知)
2)@AfterReturning
3)@Around
4)@AroundThrowing
5)@After
②表示切面执行的位置,使用的是切入点表达式
Execution(访问权限 方法返回值 方法声明(参数) 异常类型) 红色字体是必须有的
在切入点表达式中可以使用 * 0至多个任意字符
.. 用在方法参数中,表示任意多个参数,用在包名后,表示当前包及其子包路径
举例:execution(public * *(..)) 指定切入点为:任意公共方法
execution(* set*(..)) 指定切入点为:任意一个以set开始的方法
Execution(* com.xyz.service.*.*(..)) 指定切入点为:定义在service包里的任意类的任意方法
Execution(* com.xyz.service..*.*(..)) 指定切入点为:定义在service包或者子包里的任意类的任意方法,”..”出现在类名中时,后面必须跟”*”,表示包、子包下的所有类
使用aspectj时间aop的基本步骤:
①新建maven项目
②加入依赖 spring,aspectj(spring-aspectj),junit依赖
③创建目标类:接口和他的是实现类
要做的是给类中的方法增加功能
④创建切面类:普通类
- 在类的上面加入@Aspect (来表示他是切面类)
- 在类中定义方法,方法就是切面要执行的功能代码
在方法的上面加入aspectj中的通知注解,例如@Before
还需要指定切入点表达式execution()
⑤创建spring的配置文件:声明对象,把对象交给容器统一管理
可以使用xml或者注解声明对象
声明目标对象,声明切面类对象,声明aspectJ框架中的自动代理生成器标签
(自动代理生成器,用来完成代理对象的自动创建功能的)
⑥创建测试类,从spring容器中获取目标对象(实际上就是代理对象)
通过代理执行方法,实现aop的功能增强
- @Pointcut:管理切入点,如果你的项目中有多个切入点表达式是重复的 可以使用Pointcut
@Pointcut(value=”execution(........)”)
public void mypt(){
//无需代码 此时在value=”mypt()” 就相当于这个定义的切入点表达式
}
- 如果有接口spring会Jdk动态代理 没有接口spring会cglib动态代理
- mybatis spring整合
- 通过ioc把二者 整合
- 要使用dao对象,需要使用getMapper()方法
怎么能使用getMapper()方法,需要哪些条件
①获取sqlSession对象,需要使用sqlSessionFactory的openSssion()方法
②创建sqlSessionFactory对象,通过获取mybatis的主配置文件,能创建sqlSessionFactory对象
需要sqlSessionFactory对象,使用Factory能获取sqlSession,有了Sqlsession就能有dao,目的就是获取dao对象Factory创建需要读取主配置文件
我们会使用独立的连接池替换掉原mybatis主配置文件中的连接数据库的代码,把连接池类也交给spring创建
通过说明,我们需要spring创建一下对象
1.独立的连接池类的对象,使用阿里的druid连接池
2.sqlSessionFactory对象
3.创建出dao对象
需要学的就是上面三个对象的创建语法,使用xml的bean标签(因为没有源代码不饿能用注解)
步骤:
- 新建maven项目
- 加入maven依赖 1)spring依赖
- mabatis依赖
- mysql驱动
- spring的事务的依赖
- mybatis和spring集成的依赖:mybatis官方体用的,用来在Spring项目中创建mybatis的sqlsessionfactory,dao对象的
- 创建实体类
- 创建dao接口和mapper文件
- 创建mybatis主配置文件
- 创建service接口和实现类,属性是dao
- 创建Spring的配置文件:声明mybatis的对象交给spring创建
- 数据源 DataSource
- SqlsessionFactory
- Dao对象
- 声明自定义的service
- 创建测试类,获取service对象,通过service调用dao完成数据库的访问
Pom文件需要的依赖
<!---junit依赖-->
<!--spring核心ioc依赖-->
<dependency>
<groupId>org.springframework</group>
<artifactId>spring-context</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<!--做spring事务用到的-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<!--mybatis依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.1</version>
</dependency>
<!--Spring mybatis集成依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
<!--数据库驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.9</version>
</dependency>
<!--druid 阿里的数据库连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.12</version>
</dependency>
<!--resource插件-->
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
<!--指定jdk版本-->
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>