Spring框架

1. Spring框架优点?

(1).方便解耦,简化开发

通过Spring提供的IoC容器,我们可以将对象之间的依赖关系交由Spring进行控制,避免硬编码所造成的过度程序耦合。有了Spring,用户不必再为单实例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。

(2).AOP(面向切面)编程的支持

通过Spring提供的AOP功能,方便进行面向切面的编程,许多不容易用传统OOP实现的功能可以通过AOP轻松应付。

(3).声明式事务的支持

在Spring中,我们可以从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活地进行事务的管理,提高开发效率和质量。

(4).方便程序的测试

可以用非容器依赖的编程方式进行几乎所有的测试工作,在Spring里,测试不再是昂贵的操作,而是随手可做的事情。例如:Spring对Junit4支持,可以通过注解方便的测试Spring程序。

(5).方便集成各种优秀框架

Spring不排斥各种优秀的开源框架,相反,Spring可以降低各种框架的使用难度,Spring提供了对各种优秀框架(如Struts,Hibernate、Hessian、Quartz)等的直接支持。

(6).降低Java EE API的使用难度

Spring对很多难用的Java EE API(如JDBC,JavaMail,远程调用等)提供了一个薄薄的封装层,通过Spring的简易封装,这些Java EE API的使用难度大为降低。

(7).Java 源码是经典学习范例

Spring的源码设计精妙、结构清晰、匠心独用,处处体现着大师对Java设计模式灵活运用以及对Java技术的高深造诣。Spring框架源码无疑是Java技术的最佳实践范例。如果想在短时间内迅速提高自己的Java技术水平和应用开发水平,学习和研究Spring源码将会使你收到意想不到的效果。


2. 谈谈你对spring IOC和DI的理解,它们有什么区别?

IoC, Inversion of Control, 控制反转

  首先想说说IoC(Inversion of Control,控制反转)。这是Spring的核心,贯穿始终。所谓IoC,对于Spring框架来说,就是由Spring来负责控制对象的生命周期和对象间的关系。这是什么意思呢,举个简单的例子,我们是如何找女朋友的?常见的情况是,我们到处去看看找到自己喜欢的,然后打听她们的兴趣爱好、qq号、电话号………,想办法认识她们,投其所好送其所要……这个过程是复杂深奥的,我们必须自己设计和面对每个环节。传统的程序开发也是如此,在一个对象中,如果要使用另外的对象,就必须得到它(自己new一个),使用完之后还要将对象销毁,对象始终会和其他的接口或类耦合起来。

那么IoC是如何做的呢?有点像通过婚介找女朋友,在我和女朋友之间引入了一个第三者:婚姻介绍所。婚介管理了很多男男女女的资料,我可以向婚介提出一个要求的列表,告诉它我想找个什么样的女朋友,然后婚介就会按照我们的要求,提供一个女孩,我们只需要去和她谈恋爱、结婚就行了。简单明了,如果婚介给我们的人选不符合要求,我们就会抛出异常。整个过程不再由我自己控制,而是有婚介这样一个类似容器的机构来控制。Spring所倡导的开发方式就是如此,所有的类都会在Spring容器中登记,告诉Spring你是个什么东西,你需要什么东西,然后Spring会在系统运行到适当的时候,把你要的东西主动给你,同时也把你交给其他需要你的东西。所有的类的创建、销毁都由 Spring来控制,也就是说控制对象生存周期的不再是引用它的对象,而是Spring。对于某个具体的对象而言,以前是它控制其他对象,现在是所有对象都被Spring控制,所以这叫控制反转。

DI(依赖注入)

  IoC的一个重点是在系统运行中,动态的向某个对象提供它所需要的其他对象。这一点是通过DI(Dependency Injection,依赖注入)来实现的。比如对象A需要操作数据库,以前我们总是要在A中自己编写代码来获得一个Connection对象,有了 spring我们就只需要告诉Spring,A中需要一个Connection,至于这个Connection怎么构造,何时构造,A不需要知道。在系统运行时,Spring会在适当的时候制造一个Connection,然后像打针一样,注射到A当中,这样就完成了对各个对象之间关系的控制。A需要依赖 Connection才能正常运行,而这个Connection是由spring注入到A中的,依赖注入的名字就这么来的。那么DI是如何实现的呢? Java 1.3之后一个重要特征是反射(reflection),它允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性,Spring就是通过反射来实现注入的。

总结:

IOC是一种叫做“控制反转”的设计思想。

a、较浅的层次——从名字上解析
“控制”就是指对 对象的创建、维护、销毁等生命周期的控制,这个过程一般是由我们的程序去主动控制的,如使用new关键字去创建一个对象(创建),在使用过程中保持引用(维护),在失去全部引用后由GC去回收对象(销毁)。
“反转”就是指对 对象的创建、维护、销毁等生命周期的控制由程序控制改为由IOC容器控制,需要某个对象时就直接通过名字去IOC容器中获取。

b、更深的层次——提到DI,依赖注入,是IOC的一种重要实现
一个对象的创建往往会涉及到其他对象的创建,比如一个对象A的成员变量持有着另一个对象B的引用,这就是依赖,A依赖于B。IOC机制既然负责了对象的创建,那么这个依赖关系也就必须由IOC容器负责起来。负责的方式就是DI——依赖注入,通过将依赖关系写入配置文件,然后在创建有依赖关系的对象时,由IOC容器注入依赖的对象,如在创建A时,检查到有依赖关系,IOC容器就把A依赖的对象B创建后注入到A中(组装,通过反射机制实现),然后把A返回给对象请求者,完成工作。

c、IOC的意义何在?
IOC并没有实现更多的功能,但它的存在使我们不需要很多代码、不需要考虑对象间复杂的耦合关系就能从IOC容器中获取合适的对象,而且提供了对 对象的可靠的管理,极大地降低了开发的复杂性。


3. Spring配置bean实例化有哪些方式?

3.1通过无参构造

xml文件中配置:

需要被Spring来管理的类:

3.2通过有参构造:

xml配置文件:

需要被Spring来管理的类:

3.3通过静态工厂

静态工厂对象

xml配置文件

3.4通过实例(非静态)工厂

工厂对象:

xml配置文件:


4. 请介绍一下Spring框架中bean的生命周期和作用域

 在Spring中,简单地讲,bean就是由IoC容器初始化、装配及管理的对象,除此之外,bean就与应用程序中的其他对象没有什么区别了。

默认情况下, 同一个<bean>只会创建一个对象.,即Spring默认的作用域是singleton

作用域:

bean的生命周期:

Spring中bean的实例化过程(不好意思,我盗图了):

与上图类似,bean的生命周期流程图:

bean实例生命周期的执行过程如下:

0、Spring对bean进行实例化,默认bean是单例;

1、Spring对bean进行依赖注入(DI);

2、如果bean实现了BeanNameAware接口,spring将bean的id传给setBeanName()方法;

3、如果bean实现了BeanFactoryAware接口,spring将调用setBeanFactory方法,将BeanFactory实例传进来;

4、如果bean实现了ApplicationContextAware接口,它的setApplicationContext()方法将被调用,将应用上下文的引用传入到bean中;

5、如果bean实现了BeanPostProcessor接口,它的postProcessBeforeInitialization方法将被调用;

6、如果bean实现了InitializingBean接口,spring将调用它的afterPropertiesSet接口方法,类似的如果bean使用了init-method属性声明了初始化方法,该方法也会被调用;

7、如果bean实现了BeanPostProcessor接口,它的postProcessAfterInitialization接口方法将被调用;

8、此时bean已经准备就绪,可以被应用程序使用了,他们将一直驻留在应用上下文中,直到该应用上下文被销毁;

9、若bean实现了DisposableBean接口,spring将调用它的distroy()接口方法。同样的,如果bean使用了destroy-method属性声明了销毁方法,则该方法被调用;

总结:

 其实很多时候我们并不会真的去实现上面说描述的那些接口,那么下面我们就除去那些接口

单例模式(singleton),默认情况下

scope=”singleton”,即默认情况下,会在启动容器时(即实例化容器时)时实例化(创建)。但我们可以指定bean节点的lazy-init=”true”,懒加载,来延迟初始化bean,这时候,只有在第一次获取bean时才会初始化bean,即第一次请求该bean时才初始化。如下配置:

<bean id="serviceImpl" class="com.chenpeng.service.ServiceImpl" lazy-init="true"/> 

<bean>标签详解:

<bean>用于管理对象(创建对象) 
1. id 
    当前bean的唯一标识, 尽量遵循规范: 字母, 数字, 下划线 
2. class 
     用于描述类型的全限定路径 
3. factory-bean 
     用于引用要使用的实例工厂对象 
4. factory-method 
     用于指定要使用的工厂中的方法名 
5. name 
     用于定义别名(外号, 昵称), 支持特殊符号(不要出现#$) 
     别名可以通过: 空格, 逗号, 分号进行分隔 
6. init-method 
    初始化方法, 在创建对象后, 使用对象(getBean)前, spring自动调用的方法 
7. destroy-method 
    销毁时自动调用的方法. 
8. parent 
    用于描述继承关系, 常用于简化配置 
9. abstract 
    用于描述抽象的bean. 表示这个bean标签不能通过getBean得到对象, 通常要配合parent使用 
    可选值:  
        true: 当前bean为抽象bean 
        false:默认值, 当前bean为非抽象bean 
10. lazy-init 
     延迟初始化. 默认情况下, Spring在容器被加载时就创建对象. 延迟初始化表示在容器被加载时, Spring不创建该对象, 而是在getBean获取对象时才去创建. 可选值: 
      true: 
      false:默认值 
11. scope 
      作用域, 用于表示对象的创建个数和使用范围.可选值: 
          singleton: 默认值, 表示只创建一个对象 
          prototype: 容器加载时不创建对象, getBean的时候创建对象, 表示每次获取对象都重新创建一个新的对象 
          request: 需要配合spring-web.jar包使用, 表示一次客户端请求中, 对象是单例的. 
          session: 需要配合spring-web.jar包使用, 表示一次会话中, 对象是单例的. 
          global session: 需要配合spring-web.jar, spring-webmvc-portlet.jar包使用, 表示在同一个globalsession中, 对象是单例的 
          application: 需要配合spring-web.jar包使用, 表示整个应用程序中, 对象是单例的. 


5. Bean注入属性有哪几种方式?

1.Set注入

类中:

xml配置文件中:

2.构造器注入(这种方式的注入是指带有参数的构造函数注入

类中:

xml配置文件:

3.静态工厂的方法注入( 静态工厂: 不需要创建工厂对象, 直接通过工厂类, 调用静态方法就可以得到目标对象

类中

/** 
* 静态工厂: 不需要创建工厂对象, 直接通过工厂类, 调用静态方法就可以得到目标对象 
* 
* @author chenpeng
* 
*/ 
public class UserStaticFactory { 


        public static User getInstance() { 
                System.out.println("静态工厂获取对象"); 
                return new User(); 
        } 
} 

xml配置文件:

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd"> 


        <!-- 配置使用静态工厂创建User对象 --> 
        <bean id="user" 
                class="com.chenpeng.factory.UserStaticFactory" 
                factory-method="getInstance" /> 


</beans> 

4.实例工厂的方法注入

类:

/** 
* 实例工厂 
*         必须先创建工厂对象, 然后通过工厂对象调用方法得到目标对象 
* 
* @author chenpeng
* 
*/ 
public class UserInstanceFactory { 


        public UserInstanceFactory() { 
                System.out.println("实例工厂对象创建"); 
        } 


        public User getInstance(String name) { 
                System.out.println("实例工厂获取对象..."); 
                return new User(name); 
        } 


} 

xml配置文件:

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd"> 


        <!-- 配置工厂对象 --> 
        <bean id="factory" class="com.chenpeng.factory.UserInstanceFactory"></bean> 


        <!-- 配置使用工厂创建User对象 --> 
        <bean id="user" factory-bean="factory" factory-method="getInstance"> 
                <constructor-arg name="name" value="李四" /> 
        </bean> 


</beans>  

总结:

Spring IOC注入方式用得最多的是(1)(2)种


6. @Autowired和@Resource之间的区别

@Resource和@Autowired都是做bean的注入时使用,

其实@Resource并不是Spring的注解,它的包是javax.annotation.Resource,需要导入,但是Spring支持该注解的注入。

@AutoWired: 是spring提供的注解, 默认先按类型进行注入, 如果找到则注入, 找不到再按照名称进行注入; 如果找到多个匹配的类型, 抛出异常.

@Resource: 是javax.annotation包中提供的注解, 默认先按照名称注入, 名称一致则注入, 如果没有同名的, 再按照类型注入.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值