Spring框架

一.Spring是什么

        spring是一个轻量级的控制反转ioc和面向切面aop的容器框架,用来装javabean(java对象);而且也可以作为中间层框架起到一个连接作用,比如Struts和hibernate一起使用,快速简洁开发企业应用。

二、ioc控制反转

1.ioc控制反转

        ioc是spring的核心,对于spring框架来说,就是由spring来负责控制对象的生命周期和对象间的关系。把传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理。所谓的"控制反转"就是对组件对象控制权的转移,控制器从程序代码本身转移到了外部容器,由容器来创建对象并管理对象之间的依赖关系。

        而当我们需要用到容器中的对象时,通过Di依赖注入(autowiredresource等注解,xmlbean节点内的ref属性,项目启动的时候会读取xml节点ref属性根据id注入,也会扫描这些注解,根据类型或id注入;id就是对象名)。

2.如何实现一个ioc容器

        1.配置文件配置包扫描路径

        2.递归包扫描获取.class文件

        3.反射、确定需要交给ioc管理的类

        4.对需要注入的类进行依赖注入

  • 配置文件中指定需要扫描的包路径
  • 定义一些注解,分别表示访问控制层、业务服务层、数据持久层、依赖注入注解、获取配置文件注解
  • 从配置文件中获取需要扫描的包路径,获取到当前路径下的文件信息及文件夹信息,我们将当前路径下所有以.class结尾的文件添加到一个Set集合中进行存储
  • 遍历这个set集合,获取在类上有指定注解的类,并将其交给IOC容器,定义一个安全的Map用来存储这些对象
  • 遍历这个lOC容器,获取到每一个类的实例,判断里面是有有依赖其他的类的实例,然后进行递归注入

3.Di依赖注入

        依赖注入时实现IOC的方法,在iOC容器运行期间,动态地将某种依赖关系注入到对象之中。依赖注入的基本原则是应用组件不应该负责查找资源或者其他依赖的协作对象。配置对象的工作应该由容器负责,查找资源的逻辑应该从应用组件的代码中抽取出来,交给容器来完成。DI是对IoC更准确的描述,即组件之间的依赖关系由容器在运行期决定,形象的来说,即由容器动态的将某种依赖关系注入到组件之中。

4.Di依赖注入的方式

        1、Setter注入 2、构造器Construct注入 3、接口注入

        依赖注入可以通过setter方法注入(设值注入)、构造器注入和接口注入三种方式来实现,Spring支持setter注入和构造器注入,通常使用构造器注入来注入必须的依赖关系,对于可选的依赖关系,则setter注入是更好的选择,setter注入需要类提供无参构造器或者无参的静态工厂方法来创建对象。

三、Aop面向切面

1.什么是AOP

        AOP 面向切面编程(Aspect Oriented Programming),可以说是OOP 面向对象编程(Object Oriented Programming)的补充和完善。OOP引入封装、继承、多态等概念来建立一种对象层次结构,用于模拟公共行为的一个集合。不过OOP允许开发者定义纵向的关系,但并不适合定义横向的关系。例如事务管理、日志、缓存功能,这些代码功能在OOP设计中散布在所有对象层次中,导致了大量代码的重复,而不利于各个模块的重用。

        而AOP技术恰恰相反,它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。

2.AOP的原理是什么

        AOP实现的关键在于AOP框架自动创建的AOP代理,AOP代理主要分为静态代理和动态代理,静态代理的代表为AspectJ;而动态代理则以Spring AOP为代表。通常使用AspectJ的编译时增强实现AOP,AspectJ是静态代理的增强,所谓的静态代理就是AOP框架会在编译阶段生成AOP代理类,因此也称为编译时增强

        Spring AOP中的动态代理主要有两种方式:JDK动态代理和CGLIB动态代理。

        (1) JDK动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口。JDK动态代理的核心是InvocationHandler接口和Proxy类。

        (2) 如果目标类没有实现接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成某个类的子类,注意,CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。

四、Spring中BeanFactory和ApplicationContext的区别是什么

ApplicationContext是BeanFactory的子类,由于Spring不断地更新,BeanFactory无法支持spring插件,例如:AOP、Web应用等功能。ApplicationContext就以一种更面向框架的工作方式以及对上下文进行分层和实现继承,并在这个基础上对功能进行扩展:

        ①继承MessageSource,提供国际化的消息访问
        ②统一的资源文件访问方式(如URL和文件)
        ③提供在监听器中注册bean的事件。
        ④同时加载多个配置文件。
        ⑤载入多个(有继承关系)上下文 ,使得每一个上下文都专注于一个特定的层次,比如应用的web层。
区别:
        1 ApplicationContext,会在容器启动时,一次性创建了所有的Bean如果配置的bean是singleton单例模式,ApplicationContext启动后预载入所有的单实例Bean,通过预载入单实例bean。好处是可以预先加载,坏处是浪费内存。
        2 BeanFactory,当使用BeanFactory实例化对象时,配置的bean不会马上被实例化,而是等到你使用该bean的时候(getBean)才会被实例化。好处是节约内存,坏处是速度比较慢。多用于移动设备的开发。
        3 BeanFactoryApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor使用,但两者之间的区别是:BeanFactory需要手动注册,而ApplicationContext则是自动注册

五、Spring Bean

1.Spring Bean的生命周期

        1、解析类得到BeanDefinition
        2、如果有多个构造方法,则要推断构造方法
        3、确定好构造方法后,进行实例化得到一个对象
        4、对对象中的加了@Autowired注解的属性进行属性填充
        5、回调Aware方法,比如BeanNameAwareBeanFactoryAware
        6、调用BeanPostProcessor的初始化前的方法
        7、调用初始化方法
        8、调用BeanPostProcessor的初始化后的方法,在这里会进行AOP
        9、如果当前创建的bean是单例的则会把bean放入单例池
        10、使用bean
        11、Spring容器关闭时调用DisposableBeandestory()方法

2.Spring支持的几种bean的作用域。

        singleton:默认,每个容器中只有一个bean的实例,单例的模式由BeanFactory自身来维护。该对象的生命周期是与Spring IOC容器一致的(但在第一次被注入时才会创建)。
        prototype:原型,每次从容器中调用Bean时,都会返回一个新的实例        
        application:bean被定义为在ServletContext的生命周期中复用一个单例对象。
        websocket:bean被定义为在websocket的生命周期中复用一个单例对象。
WebApplicationContext新增了3个作用域:
        1. request:bean被定义为在每次HTTP请求都会创建一个新的Bean,也就是说在单个请求中都会复用这一个单例对象。
        2. session:与request范围类似,确保每个session中都有一个bean的实例,同一个HttpSession共享同一个Bean,不同的HttpSession使用不同的Bean在session过期后,bean会随之失效。
        3. global-session:全局作用域,同一个全局Session共享一个Beanglobal-session和Portlet应用相关。当你的应用部署在Portlet容器中工作时,它包含很多portlet。如果你想要声明让所有的portlet共用全局的存储变量的话,那么这全局变量需要存储在global-session中。全局作用域与Servlet中的session作用域效果相同。

3.Spring框架中的单例Bean是线程安全的么?

        Spring中的Bean默认是单例模式的,框架并没有对bean进行多线程的封装处理。如果Bean是有状态的(有数据存储功能),那就需要开发人员自己来进行线程安全的保证,最简单的办法就是改变bean的作用域 把 "singleton"改为’‘protopyte’ 这样每次请求Bean就相当于是 new Bean() 这样就可以保证线程的安全了。
        有状态就是有数据存储功能。
        无状态就是不会保存数据, controllerservicedao层本身并不是线程安全的,如果只是调用里面的方法,而且多线程调用一个实例的方法,会在内存中复制变量,这是自己的线程的工
作内存,是安全的。

        注意:不要在bean中声明任何有状态的实例变量或类变量,如果必须如此,那么就使用ThreadLocal把变量变为线程私有的,如果bean的实例变量或类变量需要在多个线程之间共享,那么就只能使用 synchronized、lockCAS等这些实现线程同步的方法了。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值