IOC
1.IOC是什么
Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。
2.谁控制谁
传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对象的创建;谁控制谁?当然是IoC 容器控制了对象;控制什么?那就是主要控制了外部资源获取(不只是对象包括比如文件等)
3.为什么是反转?哪反转了?
有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象;为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。
有无IOC对比
4.IOC能做什么
1)IoC不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合、更优良的程序。传统应用程序都是由我们在类内部主动创建依赖对象,从而导致类与类之间高耦合,难于测试;有了IoC容器后,把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是松散耦合,这样也方便测试,利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。
2)其实IoC对编程带来的最大改变不是从代码上,而是从思想上,发生了“主从换位”的变化。应用程序原本是老大,要获取什么资源都是主动出击,但是在IoC/DI思想中,应用程序就变成被动的了,被动的等待IoC容器来创建并注入它所需要的资源了。
3)IoC很好的体现了面向对象设计法则之一—— 好莱坞法则:“别找我们,我们找你”;即由IoC容器帮对象找相应的依赖对象并注入,而不是由对象主动去找。
DI
1.什么是DI
DI—Dependency Injection,即“依赖注入”:是组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。
2.谁依赖谁
是某个容器管理对象依赖于IoC容器;“被注入对象的对象”依赖于“依赖对象”
3.为什么需要依赖
容器管理对象需要IOC容器来提供对象需要的外部资源;
4.谁注入谁
是IOC容器注入某个对象,也就是注入“依赖对象”
5.注入了什么
是注入某个对象所需要的外部资源(包括对象、资源、常量数据)
6.依赖注入的三种实现方式
构造器注入,Setter方法注入,接口注入
构造器注入
Controller
public class FooController {
private final FooService fooService;
@Autowired
public FooController(FooService fooService) {
this.fooService = fooService;
}
//使用方式上同,略
}
接口注入:依赖项提供了一个注入方法,该方法将把依赖项注入到传递给它的任何客户端中。
public class ClassA {
private InterfaceB clzB;
public void doSomething() {
Ojbect obj=Class.forName(Config.BImplementation).newInstance();
clzB = (InterfaceB)obj;
clzB.doIt()
}
……
}
setter注入
@Controller
public class FooController {
private FooService fooService;
//使用方式上同,略
@Autowired
public void setFooService(FooService fooService) {
this.fooService = fooService;
}
}
7.IOC和DI的关系
它们是同一个概念的不同角度描述,由于控制反转概念比较含糊(可能只是理解为容器控制对象这一个层面,很难让人想到谁来维护对象关系),所以2004年大师级人物Martin Fowler又给出了一个新的名字:“依赖注入”,相对IoC 而言,依赖注入明确描述了被注入对象依赖IOC容器配置依赖对象
AOP
1.什么是AOP
在软件业,AOP为Aspect Oriented Programming的缩写,意味:面向切面编程.通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术,AOP是OOP的延续.将一些共性的内容进行抽取,在需要用到的地方,以动态代理的方式进行插入.在不修 改源码的基础上,还能对源码进行前后增强。
2.解释
我们在WEB项目开发中,通常都遵守三层原则,包括控制层(Controller)->业务层(Service)->数据层(dao),那么从这个结构下来的为纵向,它具体的某一层就是我们所说的横向。我们的AOP就是可以作用于这某一个横向模块当中的所有方法。
3.切面,切点和通知
切面:拦截器类,其中会定义切点以及通知
切点:具体拦截的某个业务点。
通知:切面当中的方法,声明通知方法在目标业务层的执行位置
通知类型:
前置通知:@Before 在目标业务方法执行之前执行
后置通知:@After 在目标业务方法执行之后执行
返回通知:@AfterReturning 在目标业务方法返回结果之后执行
异常通知:@AfterThrowing 在目标业务方法抛出异常之后
环绕通知:@Around 功能强大,可代替以上四种通知,还可以控制目标业务方法是否执行以及何时执行
4.实现原理:动态代理
1)代理模式的定义:给某一个对象提供一个代理,并由代理对象控制对原对象的引用。
2)代理模式包含如下角色:
subject:抽象主题角色,是一个接口。该接口是对象和它的代理共用的接口;
RealSubject:真实主题角色,是实现抽象主题接口的类;
Proxy:代理角色,内部含有对真实对象RealSubject的引用,从而可以操作真实对象。
3)静态代理
静态代理的的代理类是我们自己定义好的,在程序运行之前就已经编译完成
4)动态代理
动态代理的代理类是在程序运行时创建的,相比于静态代理,动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类中的方法。
Spring框架
1.什么是Spring框架
spring是一个开放源代码的设计层面框架,它解决的是业务逻辑层和其他各层的松耦合问题,是一个分层的javaEE一站式轻量级开源框架
2.Spring的作用
方便解耦,简化开发,AOP编程支持,声明式事务支持,集成Junit更加方便的进行分层测试,方便集成各种优秀框架
3.核心
1)IOC(Inversion of Control):控制反转,即对象创建的问题
2)AOP(Aspect Oriented Programming):面向切面编程
4.Spring的优点
Spring 优点
1)高内聚,低耦合
Spring 就是一个大工厂,可以将所有对象创建和依赖关系维护都交给Spring来管理
2)AOP 编程的支持
Spring 提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能
3)声明事物的支持
只需要通过配置就可以完成对事物的管理,而无需手动编程
4)方便程序的测试
Spring 对 Junit4支持,可以通过注解来测试 Spring 程序
5)方便集成各种优秀的框架
Spring 不排斥各种其他开源框架,其内部提供了对各种框架的直接支持
6)降低JavaEE API 的使用难度
Spring 对 JavaEE 开发中非常难用的一些 API(JDBC、JavaMail、远程调用等),都提供了封装,降低了开发难度
5.创建bean的方式
1)默认使用构造函数创建
在Spring的配置文件中使用bean标签,配置 id 和 class 属性后,没有其他属性和标签时,采用的就是默认构造函数创建bean对象,此时如果类中没有默认构造函数,则对象无法创建。
<bean id="helloworld" class="com.gao.Helloworld">
2)类中的方法创建
很多时候我们会使用某个类中的或者jar包中的方法或者普通工厂中的方法来创建对象,并存入到Spring容器中
<bean id="school" class="com.gao.School"></bean>
<bean id="helloworld" factory-bean="school" factory-method="getHelloworld"></bean>
3)类中的静态方法创建
使用某个类中的静态方法创建或者工厂中的或者jar包中的静态方法创建,并存入到Spring容器中
<bean id="school" class="com.gao.School"></bean>
<bean id="helloworld" class="com.gao.School" factory-method="getHelloworld"></bean>
6.获取bean的方式
1)根据 id 获取
Helloworld hello = (Helloworld) ioc.getBean("helloworld");
2)通过 bean 类型获取
如果同一个类型的bean在xml文件中配置了多个,则获取时会抛出异常,所以同一个类型的bean在容器中必须是唯一的
Helloworld hello = ioc.getBean(Helloworld.class);
3)指定bean的 id 值和类型
Helloworld hello = ioc.getBean("helloworld",Helloworld.class);
7.解释Spring支持的几种bean机制
1)singleton : bean在每个Spring ioc 容器中只有一个实例。
2)prototype:一个bean的定义可以有多个实例。
3)request:每次http请求都会创建一个bean,该作用域仅在基于web的Spring ApplicationContext情形下有效
4)session:在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。
5)global-session:在一个全局的HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。
缺省的Spring bean 的作用域是Singleton.
8.Spring支持的事务管理类型
1)编程式事务管理:这意味你通过编程的方式管理事务,给你带来极大的灵活性,但是难维护。
2)声明式事务管理:这意味着你可以将业务代码和事务管理分离,你只需用注解和XML配置来管理事务。
9.bean对象的生命周期
1)单例对象
- 出生:当容器创建的时候bean对象出生
- 活着:只要容器还在,bean对象就一直活着
- 死亡:容器销毁,bean对象就消亡
单例bean对象随容器共存亡
2)多例对象
- 出生:当使用对象时,Spring创建对象
- 活着:对象只要在使用过程中就一直活着
- 死亡:当对象长时间不用且没有其他对象引用时,有Java垃圾回收器回收
10.Spring注解配置
1)创建Spring的配置文件
<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
2)注解配置
创建对象配置
A.@Component
- 作用:用于把当前对象存入Spring 容器中
- 属性:value==>用于指定 bean 的 id,当不写时,默认为当前类名,首写字母改为小写
B.@Controller、@Service、@Repository这三个注解的作用和@Component注解是一样的,他们是Spring框架为我们提供明确的三层使用注解,使三层对象更加清晰
@Controller:一般用于表现层
@Service:一般用于业务层
@Repository:一般用于持久层
注入数据注解
C.@Resource
- 作用:直接按照 bean 的 id 注入,可以独立使用
- 属性:name==>用于指定 bean 的 id
D.@Configuration
- 作用:指定当前类是一个配置类
- 位置:在配置类的的上方
E.@ComponentScan
- 作用:用于指定通过注解指定Spring在创建容器时要扫描的包
- 属性:value 和 basePackages,这两个的作用是一样的,都是用于指定创建容器要扫描的包
- 位置:在配置类的上方
F.@Bean
- 作用:用于把当前方法的返回值作为bean对象存入Spring的IOC容器中
- 属性:name ==> 用于指定 bean的 id,当不写时,默认当前方法的名称
- 位置:在方法的上方