spring 回顾

主要就是它的IOC理念

即:把对象的创建、初始化、销毁等工作交给spring容器来做

依赖jar

通过spring的IOC容器获取bean,执行对应的方法

圈中的内容会启动spring容器,加载spring配置文件,加载过程中会初始化配置文件中对应的bean(用bean的类中的构造函数初始化了对象)

关于注解请看:

http://www.cnblogs.com/luotuoke/p/4544144.html

说明:

   1、  启动spring容器

   2、  spring容器内部会自动创建有注释(@Servic,@Controller,@Repository,@Component)的对象

   3、  当spring容器解析到

      

        启动依赖注入的注解解析器:

   4、  看哪些bean的属性上面是否有Resource(@Autowired)注解    

   5、  如果属性上面有该注解,再次检查是否有name属性

   6、  如果没有name属性,则会把该注解标注的属性的名称获取到和spring容器中的id做匹配,如果匹配成功,则赋值,如果匹配不成功,则按照类型进行匹配,如果匹配成功,则赋值,如果匹配不成功,则报错。

   7、  如果有name属性,则把name属性的值解析出来和spring容器中的id做匹配,如果匹配成功,则赋值,如果匹配不成功,则报错。

   8、  从上述的步骤可以看出注解的效率比较低,xml的效率比较高,注解书写比较简单,xml书写比较复杂。

 

   @Service 用于标注业务层组件,注意得注释在实现类中,不要注释在接口上。在action中引用时用的是接口,这种bean默认是“singleton”的。

   例如:

  

   @Autowired 后不需要getter()和setter()方法,spring也能够自动注入

   当然除了注解方式的生成bean和注解,也可以通过配置文件方式

   在spring的相关配置文件中如下写法:

   由于上面的类HelloWorldFactory中的getInstance方法是静态的所以不用实例化对象去调用,用类名可直接调用

  

    当想要执行对应的上面构造的对象的方法时,根据bean的Id来获取对象然后

    执行此对象的方法

   

    凡是有scope=prototype的,都会出现延迟加载(加载spring容器时对应的bean类不会去构造对象),并且lazy-init的false失效

    如果把lazy-init设置为true,则当spring容器启动的时候,检测不到任何错误,这样会存在很大的安全性隐患,所以一般情况下应该设置lazy-init为default/false。但是如果一个bean中有一个属性,该属性含有大量的数据,

     这个时候不希望该bean过早的停留在内存   中。这个时候需要用到lazy-init为true。

 

   在默认情况下放入到spring中的bean是单例的

         将来service层和dao层所有的类将放入到spring容器中,所以默认情况下这两个层的类的实例都是单例的,所以不能把数据声明到属性中。如果声明在属性中,将会成为共享的。  

       可以想象 ,javabean等封装数据的类是不能放在spring容器中的。

   action的视图层类来接收数据的类,为啥要设计成多例(@scope),原因就在于此吧。

  

   1,  加载spring配置文件时,调用默认的构造函数为每个bean创建一个对象(在非layz-init=true时)。

   2,  如果含有di(对象的属性赋值操作),为初始化的对象赋值

   3,  Bean中声明了init-method方法,执行此方法

   4,  执行getBean()

   5,  执行方法

 说明:

    1、  init方法是由spring内部执行的

    2、  只有当spring容器关闭以后才能执行destroy方法,spring容器一般情况下是不会关闭的。只有当web容器销毁掉的时候才可能关闭掉,所以只要一个对象在spring容器中,在spring容器关闭之前,会一直保留。

    3、  如果一个bean的配置是scope为”prototype”,则spring容器不负责销毁。

  与注解方式的对比:

  

   

   

    当getBean(”person”)时就会去访问容器在扫描类时在内存中解析到的<bean id=”person”  >(解析的过程中会根据注释的Component在内存中生成bean,然后根据resource找到bean并对其相关联的属性进行赋值)

    的对象,然后就可访问其方法了。

   流程分析

    1、  启动spring容器

    2、  Spring容器解析类扫描的注解解析器,在base-package指定的包及子包中查找所有的类

    3、  查看哪些类上面是否含有@Component注解

    4、  如果该注解的value的属性的值为空,则把类名的第一个字母变成小写,作为id值,放入到spring容器中

   5、  如果该注解的value的属性的值不为空,则用value的属性的值作为id值,放入到spring容器中

     6、  再次查找在spring容器中的类的所有的属性,按照@Resource的规则给属性赋值

 说明

       使用了类扫描机制的做法,配置文件中的配置很简单了,但是效率越来越低。

 

spring的东西貌似很多的样子

  简略的写一下 面试可能会问的东西:

    IOC:控制反转(Inversion of Control),将对象的创建,初始化,销毁等工作都交给spring容器;

         你在spring的配置文件(applicationContext.xml)中配置了对应的bean那么就会在加载spring配置文件的时候就去实例化这个bean的对象(注解方式则不用去配置,会根据注解去实例化)(排除延迟加载的情况scope=”prototype”或lazy-init=”true”)。

         spring容器实例化bean的三种方式

             构造函数

             静态工厂是调用的静态方法 所以不需要工厂的对象

             实例工厂要创建对象得调用非静态放,所以先得到工厂的对象  用这个对象去调用方法

DI:主要体现在依赖注入(给属性赋值)方面: 如果要注入的属性是对象,在bean中配置property=”beanid”,利用java的反射机制调用要注入的属性的set方法赋值,或者直接根据注释注入属性对象

    把action调用service,service调用dao等对象的创建交给spring来完成

       非注解方式的话:

                      

       注解方式的话:

                  

        实现了完全的面向接口编程,在代码端没有必要关心一个接口的实现类是什么。

 

Aop: 经典的面向切面编程,其底层原理是动态代理。

            在开发中的一些日志记录,事务,异常处理等都可以看成是aop的切面。

             以spring的声明自己的事务处理为例子,beginTrasaction();就是一个前置通知,commit()就是一个后置通知,其中还有环绕通知,能够控制切入点(目标方法)是否执行。异常通知等。

           

           切面<aop:aspect,,,>中配置的方法会伴随着切入点表达式<aop pointcut,expression=”packge.*.*”,>中的方法。

          

    

    配置事物管理器:对目标方法进行事物管理,当在执行目标方法时,出现异常,则目标方法中的操作数据库的语句是不会提交的。

     

 

   事物实例:

       

       为什么要用事物举例;

             应用层面的事务是在业务级的,这种事务数据库管不着。要是一个应用没有事务,自己点点刷刷是没有问题的,但真正到生产环境中就不一定行了。
             比如你去银行取钱,银行把钱给你,然后在你帐户中把你的余额修改,这是一个事务的,能保证你拿到钱后去你再去查你的帐户,你能立刻看到你的账户余 额减少,如果没有事务,你可能去查看到的余额没有变,你会有什么感觉。这只是很简章的一方面。

 

       可以用作权限,可以决定目标方法是否执行

               ProceedingJoinPoint join

               Object obj = join.proceed();//决定代理对象的调用方法(连接点)是否执行,,obj为连接点的返回值。

        aop的优劣

              (1).好处:

                  1).在编写service的时候,不用管譬如权限之类的业务要求

                  2).切面负责除了业务逻辑的其他内容,而且切面中的通知(权限控制)和业务逻辑方法没有任何关系,做到了完全松耦合

                  3).最后产生的代理对象吧通知和目标结合在一起

             (2).不好之处

                  切入点和通知相互交织,有复杂的嫌疑。并不像struts那样具有像栈一样的模块

SSH的整合:与hibernate,在spring配置文件中配置产生dataSource的bean(有数据库配置信息)

                 配置产生sessionFactory的bean,sessionFactory依赖dataSource

                在dao实现类声明sessionFactory对象(这个dao继承了HibernateDaoSuport)

                与struts的结合 ,action的产生交给了spring容器;

 

 

1、  服务器启动通过web.xml的ContextLoaderListener监听器类,

    1) 并且调用ContextLoaderListener监听器的contextInitialized()方法,在其中调用了createContextLoader()方法实例化了一个ContextLoader的contextLoader对象。

    2)  用这个ContextLoader对象去加载spring的配置文件

        首先在web.xml中找<context-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring/applicationContext.xml

        如果有此配置则根据此配置来加载spring配置文件,没有则默认去加载web-info/applicationContext.xml(此方法不推荐)

    3)  继续用contextLoader对象调用它的initWebApplicationContext()方法,

        在此方法中用createWebApplicationContext()创建了WebApplicationContext容器(spring容器),并将此容器放到了servletContext域中(web应用域)

        在此容器中实例化dao,service等一些实例化对象。

-----------------------===================================

通过StrutsPrepareAndExecuteFilter过滤器

             调用此过滤器的init()方法//在此init方法中用InitOperations的对象init去调用InitOperations的initDispatcher()方法

          此init()方法执行过程中加载了default.properties文件(包含一些常量信息比如同一编码,默认utf-8,还有文件上传的默认大小为2M,都有默认值,但都是可以改变的)

          struts-default.xml(配置了启动struts容器时默认加载的一些jar包,结果集类型定义,默认拦截器的声明,拦截器栈的声明,要加载好多bean这也是struts容器启动慢的原因)、

          struts-plugin.xml(改写了action的生成方式,改为按照StrutsSpringObjectFactory 里的buildAction方式生成action)、这里的声明将action的创建交给了spring容器

    struts.xml文件

 

2、  当url请求时通过StrutsPrepareAndExecuteFilter过滤器

         调用都doFiler()方法执行过程中

               首先利用容器启动时创建的对象prepare和execute

               1)       调用(default.priperties)的配置(文件中的struts编码默认UTF-8)设置编码

               2) 创建了值栈valuestack

               3) 初始化值栈,将request,session,application对象放入到值栈中的map栈中

               4) 还创建了一个actionContext,将valuestack值栈中的map栈赋值给actionContext的context,所以值栈中map栈与actionContext中的context存在着同一个引用。

               5) 将actionContext放入到了当前线程(threadLocal)中,保证线程的一致性

               6)  创建action代理(与struts有所不同)

               7)  创建action,将action放到栈顶

               8)  执行action代理的invoke()方法

               9)  顺序执行配置的所有拦截器

               10)执行所需的action中的方法,执行结果集(反馈给浏览器),倒序执行拦截器

               11)清空struts容器中的数据环境(清空了actionContext中的所有数据)

   

当结合spring容器后,创建action的方式发生了改变,

当用户请求道action时,

根据struts.xml中对应action配置的class=””值去在spring容器找bean的name值(这个actionbean配置了scope=”prototype”,一般此项必须配置,不然可能形成数据共享,这样确保多个action操作的不是同一个实例),创建action对象

其他过程不变

 

posted @ 2015-07-23 14:46  ~清风煮酒~  阅读(432)  评论(0编辑  收藏  举报