应届生找工作要点总结(5)Spring相关

依赖注入:在运行期间由容器将依赖关系注入到组件中,就是在运行期,由spring根据配置文件将其它对象的引用通过组将提供的setter方法进行设定。
控制反转:容器控制程序对象之间的关系,而不是传统实现中,由程序代码之间的控制,又名依赖注入。所有类的创建,销毁都由spring来控制,也就是说控制对象生命周期的不是引用他的对象,而是spring。对于某个对象而言,以前是他控制其他对象,现在所有对象都由spring控制,这就叫控制反转。

IoC能做什么:把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是松散耦合,这样也方便测试,利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活;IoC很好的体现了面向对象设计法则之一 – 好莱坞法则。

Spring IOC的初始化过程:(1)Resource文件的定位,即找到bean的配置文件。(2)通过特定的reader解析该bean配置文件,抽象成beanDefinition类。(3)将beanDefinition向容器注册,写入到一个大的HashMap中,供实例化请求的时候使用。

依赖注入的思想是由反射机制实现的,在实例化一个类时,它通过反射调用类中的set方法将事先保存在hashmap中的类属性注入到类中。
依赖注入发生在getbean方法中,getbean又调用dogetbean方法。getbean是依赖注入的起点,之后调用createbean方法,创建过程又委托给了docreatebean方法。在docreatebean中有两个方法:createbeaninstance,生成bean包含的java对象;populatebean完成注入。

在创建bean的实例中,getinstantiationstrategy方法挺重要,该方法的作用是获得实例化对象策略,也就是指通过哪种方案进行实例化的过程。
spring当中提供两种方案进行实例化:beanutil和cglib。beanutil实现机制是java反射,cglib是一个第三方类库,采用的是一种字节码加强方式。spring中默认实例化策略为cglib。populatebean进行依赖注入,获得beandefinition中设置的property信息,简单理解依赖注入的过程就是对这些property进行赋值的过程,在配置bean的属性时,属性可能有多种类型,我们在进行注入的时候,不同类型的属性我们不能一概而论的进行处理。集合类型属性和非集合类型差距很大,对不同的类型应有不同的处理过程。所以要先判断value类型,再调用具体的方法。

AOP面向切面编程。我觉得他是对OOP编程方式的补充。切面表示从业务逻辑中分离出来的横切逻辑,比如性能监控,日志记录等。我们需要完成这样功能的时候都可以把他们从核心代码中抽离出去。AOP可以解决代码耦合问题。比如有某个方法执行具体的业务逻辑,我们想在统计统计一下这个方法执行的时间,那我们就可以利用AOP来让原来方法的代码不做任何的改变来完成。使用模块技术,aop把软件系统分成两部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。
静态代理:比如我要统计一个函数的运行时间,那么最sb的方法是在这个函数运行的前后记录当前时间,然后作差,但这样就在原来的函数上进行了修改。所谓静态代理,就是比如A类有一个函数fun();那我现在做一个代理类AProxy,这个类持有A类对象的引用,我们再执行A的fun()方法的时候就不直接用A类对象了,而是是AProxy这个代理对象,这个代理对象里面因为有A对象的引用,可以调用A的fun()方法。当然可以在fun()方法前后统计这个方法执行的时间了。但是静态代理有个问题,随着需要代理的类越来越多,那每一个需要代理的类都有一个XXProxy,我们要想办法将代理类减少。这个时候动态代理就派上用场了。
JDK动态代理:要实现JDK动态代理,需要编写类并实现InvocationHandler接口并重写Invoke方法。但是这样不是还是多了一个类代理类吗?假设我们现在有个函数在使用A类的某个函数在通过IO读写文件,想统计执行时间,那我们就写一个上述的动态代理类,现在我有多了一个类B的某个函数在执行BIO,也想统计时间,这个时候B类就不再需要再写一个动态代理类,直接用刚刚创建的动态代理类就不再需要再创建代理类了,假设现在还有更多其他函数想查看运行时间,都不再需要自己写代理类了,一个就够了。那动态代理相比静态代理的优势就体现在此处。但是JDK动态代理仍然有自己的缺点,JDK给我们提供的动态代理只能代理接口,而不能代理没有接口的类。CGLib动态代理就来弥补这个缺陷了。
CGLib动态代理:开源的CGLib类库可以代理没有接口的类,这样就弥补了JDK动态代理的不足。CGLib动态代理需要实现MethonInterceptor接口并重写intercept方法。

方面(Aspect):一个关注点的模块化,这个关注点实现可能另外横切多个对象。事务管理是J2EE应用中一个很好的横切关注点例子。方面用Spring的Advisor或拦截器实现。
连接点(Joinpoint): 程序执行过程中明确的点,如方法的调用或特定的异常被抛出;
通知(Advice): 在特定的连接点,AOP框架执行的动作。许多AOP框架包括Spring都是以拦截器做通知模型,维护一个“围绕”连接点的拦截器链。Spring中定义了四个advice: BeforeAdvice, AfterAdvice, ThrowAdvice和DynamicIntroductionAdvice;
切入点(Pointcut): 指定一个通知将被引发的一系列连接点的集合。AOP框架必须允许开发者指定切入点:例如,使用正则表达式。 Spring定义了Pointcut接口,用来组合MethodMatcher和ClassFilter,可以通过名字很清楚的理解,MethodMatcher是用来检查目标类的方法是否可以被应用此通知,而ClassFilter是用来检查Pointcut是否应该应用到目标类上;
切点标志符(designator):execution、within、this 与 target、bean、args、@annotation;

Spring ioc容器,beanfactory是最原始的ioc容器,有以下方法:getbean,containsbean,isSingleton。beanfactory只对ioc容器最基本行为做了定义,而不关系bean是怎样定义和加载的。如果我们知道一个工厂具体产生对象的过程,则要看这个接口的实现类。在spring中实现这个接口有很多类,其中一个xmlbeanfactory。xmlbeanfactory的功能是建立在defaultlistablexmlbeanfactory这个基本容器基础上的,并在这个基本容器的基础上实行了其他诸如xml读取的附加功能。xmlbeanfactory构造函数,resource是spring中对于外部资源的抽象,最常见是文件的抽象,特别是xml文件,而且resource里通常是保存了spring使用者的bean定义,eg.applicationContext.xml在被加载时,就会被抽象为resource处理。
ioc容器建立过程:建立ioc配置文件的抽象资源,这个资源包含了beandefinition的定义信息。创建一个beanfactory,这里使用的是defaultlistablexmlbeanfactory。创建一个beandefinition的读取器,这里使用xmlbeandefinitionreader来载入xml文件形式的beandefinition。然后将上面定义好的resource通过一个回掉配置给beanfactory。从资源里读入配置信息,具体解析过程由xmlbeandefinitionreader完成。ioc容器建立起来。
beandefinition类似于resource接口的功能,起到的作用就是对所有的bean进行一层抽象的统一,把形式各样的对象封装为一个便于spring内部进行协调管理和调度的数据结构。beandefinition屏蔽了不同对象对于spring框架的差异。解析xml,获得document对象,接下来只要再对document结构进行分析便可知道bean在xml中是怎么定义的,就可以将其转化为beandefinition对象。我们配置的bean的信息经过解析,在spring内部已经转化为beandefinition这种统一的结构,但这些数据还不能供ioc容器直接使用,需要在ioc容器中为这些beandefinition进行注册,注册完成的beandefinition,都会以beanname为key,beandefinition为value,交由map管理。注册完之后,一个ioc容器就可以用了。
好处:降低组件间的耦合性。

introduction是给一个已有类添加方法或字段属性,introduction还可以在不改变现有类代码的情况下,让现有java类实现新的接口,或为其指定一个父类实现多继承,相对于advice可以动态改变程序的功能流程来说,introduction用来改变类的静态结构。

拦截器,是对连接点进行拦截,从而在连接点前后加入自定义的切面模块功能。作用于同一个连接点的多个拦截器组成一个拦截器链,拦截器链上的每个拦截器,通常会调用下一个拦截器。

@controller@service@requestmapping@transactional@requestbody@compnent@autowired@cookievalue@repository@restcontroller。
其中@controller@service负责注册一个bean到spring上下文,bean的id默认为类名称开头字母小写。@autowired根据bean的类型从spring上下文进行查找,注册类型必须唯一。@pathvariable一个函数里有一个输入参数,就是{seckillid}的值就用pathvariable。

spring用事务管理器来管理事务,有一套统一的api,对于不同持久化方式有不同实现,比如jdbc,hibernate。事务声明基于aop,配置事务:@transaction+事务管理器。
1.基于XML配置(使用较多)
(1)配置事务管理类
<!-- 定义事务管理器 --> 
<bean id="transactionManager" 
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
    <property name="dataSource" ref="dataSource" /> 
</bean>
在spring的配置中配置数据源(dataSource)、事务管理器,事务管理器使用不同的orm框架事务管理器类就不同,mybatis 是org.springframework.jdbc.datasource.DataSourceTransactionManager  。而hibernate事务管理器为org.springframework.orm.hibernate3.HibernateTransactionManager。
(2)配置事务属性
<!-- 配置事务的属性 --> 
    <tx:advice id="TestAdvice" transaction-manager="transactionManager"> 
        <!--配置事务传播性,隔离级别以及超时回滚等问题 --> 
        <tx:attributes> 
            <tx:method name="search*" propagation="REQUIRED" read-only="true" isolation="DEFAUT" TIMEOUT="-1" /> 
            <tx:method name="del*" propagation="REQUIRED" /> 
            <tx:method name="update*" propagation="REQUIRED" /> 
            <tx:method name="add*" propagation="REQUIRED" /> 
        </tx:attributes> 
    </tx:advice>
事务有以下几个常用属性:a.read-only:设置该事务中是否允许修改数据。(对于只执行查询功能的事务,设置为TRUE可以提高事务的执行速度)。b.propagation:事务的传播机制。一般设置为required。可以保证在事务中的代码只在当前事务中运行,防止创建多个事务。c.isolation:事务隔离级别。不是必须的。默认值是default。d.timeout:允许事务运行的最长时间,以秒为单位。e.rollback-for:触发回滚的异常。f.no-rollback-for:不会触发回滚的异常。***实际开发中,对于只执行查询功能的事务,要设置read-only为TRUE,其他属性一般使用默认值即可。
(3)配置事务的AOP切入点
<aop:config> 
        <!--配置事务切点 --> 
        <aop:pointcut id="services" 
            expression="execution(public* com.pb.service.*.*(..))" /> 
        <aop:advisor pointcut-ref="services" advice-ref="TestAdvice" /> 
 </aop:config>
该设置的含义是:对于com.pb.service.impl包及子包下的所有类的所有公共方法进行切入。(被切入的 方法经过<tx:method>筛选)web应用程序最合适的事务切入点是Service的方法上。----通过以上三个步骤设置好声明式事务后,当Service中 的业务方法被调用之前,Spring会获取事务对象并启动事务。并使用try-catch-finally来处理异常。业务方法执行成功则会提交事务,默认情况下如果抛出了RuntimeException 或者Rrror 对象就会回滚事务。(注意: 这里注意一下,在tx:method中配置了rollback_for 中配置的Exception 这个是运行时的异常才会回滚不然其他异常是不会回滚的!)
2.使用annotation配置
1.在事务管理的dao实现类之前标注@Transactional。
2.在要进行事务管理的方法前加上@Transactional(propagation= Propagation.REQUIRED)。
3.在配置文件中指定驱动:<tx:annotation-driven transaction-manager="transactionManager" />
@transactiondefinition类用来定义事务。传播行为有7中,propgation_required:支持当前事务,若当前没有事务,则创建一个事务;propgation_supports:支持当前事务,若当前没有事务,则抛出异常;propgation_required_new:新建事务,若存在当前事务,把当前事务挂起;propgation_nerver:以非事务方式运行,若存在当前事务,则抛异常;propgation_nexted:若当前事务存在,则嵌套事务执行。隔离级别。它是否为只读事务。事务超时:为了使程序良好的运行,事务不能运行太长事件,因为事务可能涉及到对后端数据库的锁定,所以长时间的事务会不必要的占用数据库资源,事务超时就是事务的一个定时器,在特定时间内事务没有完成,就会自动回滚,而不是一直等待结束。回滚规则:默认情况下,事务只会遇到runtimeexception才回滚。

mvc:model entity 业务逻辑;view 视图,用户交互界面;controller 根据用户的输入,控制用户界面显示和更新model对象状态,功能模块和显示模块分离,提高可维护性,可复用性,可扩展性。

springmvc运行原理:
首先用户发送请求——>DispatcherServlet,前端控制器收到请求后自己不进行处理,而是委托给其他的解析器进行处理,作为统一访问点,进行全局的流程控制;
DispatcherServlet——>HandlerMapping,HandlerMapping 将会把请求映射为 HandlerExecutionChain 对象(包含一个 Handler 处理器(页面控制器)对象、多个 HandlerInterceptor 拦截器)对象,通过这种策略模式,很容易添加新的映射策略;
DispatcherServlet——>HandlerAdapter,HandlerAdapter 将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器;
HandlerAdapter——>处理器功能处理方法的调用,HandlerAdapter 将会根据适配的结果调用真正的处理器的功能处理方法,完成功能处理;并返回一个 ModelAndView 对象(包含模型数据、逻辑视图名);
ModelAndView 的逻辑视图名——> ViewResolver, ViewResolver 将把逻辑视图名解析为具体的 View,通过这种策略模式,很容易更换其他视图技术;
View——>渲染,View 会根据传进来的 Model 模型数据进行渲染,此处的 Model 实际是一个 Map 数据结构,因此很容易支持其他视图技术;
返回控制权给 DispatcherServlet,由 DispatcherServlet 返回响应给用户,到此一个流程结束。

相互依赖怎么办:用setter方式单例,是先把bean实例化再设置的对象属性。

spring启动初始化流程:
首先,对于一个web应用,其部署在web容器中,web容器提供其一个全局的上下文环境,这个上下文就是ServletContext,其为后面的spring IoC容器提供宿主环境;
其次,在web.xml中会提供有contextLoaderListener。在web容器启动时,会触发容器初始化事件,此时contextLoaderListener会监听到这个事件,其contextInitialized方法会被调用,在这个方法中,spring会初始化一个启动上下文,这个上下文被称为根上下文,即WebApplicationContext,这是一个接口类,确切的说,其实际的实现类是XmlWebApplicationContext。这个就是spring的IoC容器,其对应的Bean定义的配置由web.xml中的context-param标签指定。在这个IoC容器初始化完毕后,spring以WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE为属性Key,将其存储到ServletContext中,便于获取;
再次,contextLoaderListener监听器初始化完毕后,开始初始化web.xml中配置的Servlet,这个servlet可以配置多个,以最常见的DispatcherServlet为例,这个servlet实际上是一个标准的前端控制器,用以转发、匹配、处理每个servlet请求。DispatcherServlet上下文在初始化的时候会建立自己的IoC上下文,用以持有spring mvc相关的bean。在建立DispatcherServlet自己的IoC上下文时,会利用WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE先从ServletContext中获取之前的根上下文(即WebApplicationContext)作为自己上下文的parent上下文。有了这个parent上下文之后,再初始化自己持有的上下文。这个DispatcherServlet初始化自己上下文的工作在其initStrategies方法中可以看到,大概的工作就是初始化处理器映射、视图解析等。这个servlet自己持有的上下文默认实现类也是mlWebApplicationContext。
初始化完毕后,spring以与servlet的名字相关的属性为属性Key,也将其存到ServletContext中,以便后续使用。这样每个servlet就持有自己的上下文,即拥有自己独立的bean空间,同时各个servlet共享相同的bean,即根上下文定义的那些bean。

spring懒加载:表示该bean在容器初始化的时候不进行初始化。

简单的mvc框架实现逻辑:1.框架解析用户的配置文件。2.获取类加载器。3.提供几个方法:获取指定类的Class对象,获取指定包下的Class对象集合。4.获取基础包下的所有Class对象的集合,然后利用反射创建该Class的对象,然后将Class和与之对应的对象存入BeanMap中,以便之后的读取。5.创建注解类,例如:Controller inject action等。(例如之后可以遍历 查看哪些成员变成是有inject的注解,进行DI)。6.创建用于反射的ReflectUtil 用于获得该Class对象对应的对象,用于给该Class中的成员变量赋值,用于调用该CLass对应对象的成员函数。7.遍历所有的CLass对象,查看哪些是有Controller注解的,然后获取该类中所有有Action注解的方法。

猜你喜欢

转载自blog.csdn.net/SEUSUNJM/article/details/86568601