spring是什么?
轻量级的开源的J2EE框架。它是一个容器框架,用来装javabean(java对象),中间层框架(万能胶)可以起一个连接作用,
Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。
spring的配置方式
常见的配置方式有三种:基于XML的配置、基于注解的配置、基于Java API的配置。
Spring 的优点?
- (1)spring属于低侵入式设计,代码的污染极低;
- (2)spring将对象之间的依赖关系交由框架处理,减低组件的耦合性;
- (3)Spring提供了AOP技术,支持将一些通用任务,如安全、事务、日志、权限等进行集中式管理,从而提供更好的复用。
- (4)spring对于主流的应用框架提供了集成支持。
什么是 Spring IOC 容器?
IOC 容器创建和管理对象,将它们装配在一起,配置它们并管理它们的完整生命周期。
IOC控制反转的理解
IOC是一种思想,控制反转的思想。
IOC的实现原理就是工厂模式加反射机制。
谁控制谁,控制什么:
传统设计,如果对象A需要对象B的某个功能,那么我们直接在对象A内部通过new进行创建对象B,是对象A主动去创建依赖对象;是由对象A来控制。
而IOC是有专门一个容器来创建这些对象,即由Ioc容器来控制对象B的创建以及外部资源获取(不只是对象包括比如文件等)。现在由IOC容器来控制
为何是反转,哪些方面反转了:
传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;
而反转则是由容器来帮忙创建及注入依赖对象:由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转,依赖对象的获取被反转了。
DI依赖注入
由容器动态的将某个依赖关系注入到组件之中。
控制反转是目的,依赖注入是手段
●谁依赖于谁:当然是应用程序依赖于IoC容器;
●为什么需要依赖:应用程序需要IoC容器来提供对象需要的外部资源;
●谁注入谁:很明显是IOC容器注入应用程序某个对象,应用程序依赖的对象;
●注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)。
什么是AOP
程序业务有一些通用的功能,比如安全,日志,事务等。
这些通用功能的代码分布在业务代码中,代码大量重复,不利于复用。
AOP就是将这些功能的代码抽离出来,封装成一个切面,然后注入到流程的合适位置。
Spring AOP术语
- Advice(通知)
通知包含两个方面,1,代表方法的执行时间,2,在这个时间上面要做什么事情;
spring中提供了5种通知类型。分别是:前置通知,后置通知,异常通知,环绕通知,返回通知
- Weave(织入)
把一个切面应用到真实对象上面的过程,就叫做织入;
- JoinPoint(连结点)
在程序执行过程中某个特定的点,比如某方法调用的时候或者处理异常的时候。 在Spring AOP中,一个连接点 总是 代表一个方法的执行。
- PointCut(切入点)
要加入业务逻辑的点(在哪些类的哪些方法上面),就是要在哪个连接点上,是连结点的集合.
- Aspect(切面)
一个切入点+一个通知=一个切面(在什么地方,在什么时候,做什么事情);
AOP的工作
通过切入点和通知,定位到连接点。
然后在通知中编写切面代码。
- AOP 逻辑介入 BeanFactory 实例化 bean 的过程
- 根据 Pointcut 定义的匹配规则,判断当前正在实例化的 bean 是否符合规则
- 如果符合,代理生成器将切面逻辑 Advice 织入 bean 相关方法中,并为目标 bean 生成代理对象
- 将生成的 bean 的代理对象返回给 BeanFactory 容器,到此,AOP 逻辑执行结束
AOP如何实现
实现 AOP 的技术,主要分为两大类:
静态代理 指使用 AOP 框架提供的命令进行编译,从而在编译阶段就可生成 AOP 代理类,因此也称为编译时增强;
在编译阶段将切面织入到Java字节码中,运行的时候就是增强之后的AOP 代理类。
· 编译时编织(特殊编译器实现)
· 类加载时编织(特殊的类加载器实现)。
动态代理 不会去修改字节码,而是每次运行时在内存中临时为方法生成一个AOP对象。这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。
什么时候使用
1、如果这个类是实现接口。使用jdk动态代理或者cglib代理
2、如果这个类没有实现接口,使用cglib生成对象子类
总结:
JDK的动态代理只能用来代理接口,
而CGLIB的动态代理既可以代理接口也可以用来代理类
JDK动态代理原理
JDK动态代理的核心是InvocationHandler接口和Proxy类,如果代理的类没有实现InvocationHandler接口时,就会使用CGLIB代理
原理:
通过一个代理类区实现InvocationHandler接口,去实现接口的invoke方法,这个方法有三个参数(类,方法,参数),然后通过反射来调用
//这是接口
public interface A{void hello();}
//这是接口实现类
public class B implements A{
@override
void hello()hello
)}
//JDK动态代理过程
代理类implements InvocationHandler{
invoke(proxy , method , argsX){//类 ,方法, 参数
//代理开始
method.invoke( target , args); //要代理的对象, 参数
//代理结束
}
}
cglib代理原理
cglib是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法。因为是继承,所以该类或方法最好不要声明成final。
原理:待续
Spring通知有哪些类型?
- 前置通知(Before advice)
在某连接点(join point)之前执行的通知,但这个通知不能阻止连接点前的执行(除非它抛出一个异常)。
- 后置通知
后置通知是在连接点完成之后执行的, 即连接点返回结果或者抛出异常的时候, 下面的后置通知记录了方法的终止.
- 返回通知
无论连接点是正常返回还是抛出异常, 后置通知都会执行. 如果只想在连接点返回的时候记录日志, 应使用返回通知代替后置通知.
- 异常通知
只在连接点抛出异常时才执行异常通知
- 环绕通知
环绕通知是所有通知类型中功能最为强大的, 能够全面地控制连接点. 甚至可以控制是否执行连接点.
Spring 框架中都用到了哪些设计模式?
- 工厂模式:
BeanFactory就是简单工厂模式的体现,用来创建对象的实例;
- 单例模式:
Bean默认为单例模式。
- 代理模式:
Spring的AOP功能用到了JDK的动态代理和CGLIB字节码生成技术;
- 模板方法:
用来解决代码重复的问题
- 观察者模式:
定义对象键一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知被制动更新,如Spring中listener的实现–ApplicationListener。
Spring框架中的单例Beans是线程安全的么?
Spring框架中的单例的bean是无状态bean,在多线程的环境下是资源共享的,因此线程不安全.而在Spring中的一些非线程安全状态使用ThreadLocal来处理,让他们也变成线程安全的
Spring自动装配的方式
- no:不进行自动装配,手动设置Bean的依赖关系。
- byName:根据Bean的名字进行自动装配。
- byType:根据Bean的类型进行自动装配。
- constructor:类似于byType,不过是应用于构造器的参数,如果正好有一个Bean与构造器的参数类型相同则可以自动装配,否则会导致错误。
- autodetect:如果有默认的构造器,则通过constructor的方式进行自动装配,否则使用byType的方式进行自动装配。
SpringBean的生命周期
1、实例化一个Bean--也就是我们常说的new;
2、按照Spring上下文对实例化的Bean进行配置--也就是IOC注入;
3、如果这个Bean已经实现了BeanNameAware接口,会调用它实现的setBeanName(String)方法,此处传递的就是Spring配置文件中Bean的id值
4、如果这个Bean已经实现了BeanFactoryAware接口,会调用它实现的setBeanFactory(setBeanFactory(BeanFactory)传递的是Spring工厂自身(可以用这个方式来获取其它Bean,只需在Spring配置文件中配置一个普通的Bean就可以);
5、如果这个Bean已经实现了ApplicationContextAware接口,会调用setApplicationContext(ApplicationContext)方法,传入Spring上下文(同样这个方式也可以实现步骤4的内容,但比4更好,因为ApplicationContext是BeanFactory的子接口,有更多的实现方法);
6、如果这个Bean关联了BeanPostProcessor接口,将会调用postProcessBeforeInitialization(Object obj, String s)方法,BeanPostProcessor经常被用作是Bean内容的更改,并且由于这个是在Bean初始化结束时调用那个的方法,也可以被应用于内存或缓存技术;
7、如果Bean在Spring配置文件中配置了init-method属性会自动调用其配置的初始化方法。
8、如果这个Bean关联了BeanPostProcessor接口,将会调用postProcessAfterInitialization(Object obj, String s)方法、;
注:以上工作完成以后就可以应用这个Bean了,那这个Bean是一个Singleton的,所以一般情况下我们调用同一个id的Bean会是在内容地址相同的实例,当然在Spring配置文件中也可以配置非Singleton,这里我们不做赘述。
9、当Bean不再需要时,会经过清理阶段,如果Bean实现了DisposableBean这个接口,会调用那个其实现的destroy()方法;
10、最后,如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的销毁方法。