转 http://melorogee.iteye.com/blog/2208841
本文由 ImportNew - 一直在路上 翻译自 howtodoinjava。欢迎加入翻译小组。转载请见文末要求。
1、什么是Spring框架?Spring框架有哪些主要模块?
2、使用Spring框架能带来哪些好处?
- Dependency Injection(DI) 方法使得构造器和JavaBean properties文件中的依赖关系一目了然。
- 与EJB容器相比较,IoC容器更加趋向于轻量级。这样一来IoC容器在有限的内存和CPU资源的情况下进行应用程序的开发和发布就变得十分有利。
- Spring并没有闭门造车,Spring利用了已有的技术比如ORM框架、logging框架、J2EE、Quartz和JDK Timer,以及其他视图技术。
- Spring框架是按照模块的形式来组织的。由包和类的编号就可以看出其所属的模块,开发者仅仅需要选用他们需要的模块即可。
- 要测试一项用Spring开发的应用程序十分简单,因为测试相关的环境代码都已经囊括在框架中了。更加简单的是,利用JavaBean形式的POJO类,可以很方便的利用依赖注入来写入测试数据。
- Spring的Web框架亦是一个精心设计的Web MVC框架,为开发者们在web框架的选择上提供了一个除了主流框架比如Struts、过度设计的、不流行web框架的以外的有力选项。
- Spring提供了一个便捷的事务管理接口,适用于小型的本地事物处理(比如在单DB的环境下)和复杂的共同事物处理(比如利用JTA的复杂DB环境)。
3、什么是控制反转(IOC)?什么是依赖注入?
- 构造器注入
- Setter方法注入
- 接口注入
5、BeanFactory和ApplicationContext有什么区别?
- 提供了支持国际化的文本消息
- 统一的资源文件读取方式
- 已在监听器中注册的bean的事件
6、Spring有几种配置方式?
- 基于XML的配置
- 基于注解的配置
- 基于Java的配置
7、如何用基于XML配置的方式配置Spring?
- <beans>
- <!-- JSON Support -->
- <bean name="viewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
- <bean name="jsonTemplate" class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"/>
- <bean id="restTemplate" class="org.springframework.web.client.RestTemplate"/>
- </beans>
下面这个web.xml仅仅配置了DispatcherServlet,这件最简单的配置便能满足应用程序配置运行时组件的需求。
- <web-app>
- <display-name>Archetype Created Web Application</display-name>
- <servlet>
- <servlet-name>spring</servlet-name>
- <servlet-class>
- org.springframework.web.servlet.DispatcherServlet
- </servlet-class>
- <load-on-startup>1</load-on-startup>
- </servlet>
- <servlet-mapping>
- <servlet-name>spring</servlet-name>
- <url-pattern>/</url-pattern>
- </servlet-mapping>
- </web-app>
8、如何用基于Java配置的方式配置Spring?
- @Configuration
- public class AppConfig
- {
- @Bean
- public MyService myService() {
- return new MyServiceImpl();
- }
- }
对于上面的@Beans配置文件相同的XML配置文件如下:
- <beans>
- <bean id="myService" class="com.howtodoinjava.services.MyServiceImpl"/>
- </beans>
上述配置方式的实例化方式如下:利用AnnotationConfigApplicationContext 类进行实例化
- public static void main(String[] args) {
- ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
- MyService myService = ctx.getBean(MyService.class);
- myService.doStuff();
- }
要使用组件组建扫描,仅需用@Configuration进行注解即可:
- @Configuration
- @ComponentScan(basePackages = "com.howtodoinjava")
- public class AppConfig {
- ...
- }
- <web-app>
- <!-- Configure ContextLoaderListener to use AnnotationConfigWebApplicationContext
- instead of the default XmlWebApplicationContext -->
- <context-param>
- <param-name>contextClass</param-name>
- <param-value>
- org.springframework.web.context.support.AnnotationConfigWebApplicationContext
- </param-value>
- </context-param>
- <!-- Configuration locations must consist of one or more comma- or space-delimited
- fully-qualified @Configuration classes. Fully-qualified packages may also be
- specified for component-scanning -->
- <context-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>com.howtodoinjava.AppConfig</param-value>
- </context-param>
- <!-- Bootstrap the root application context as usual using ContextLoaderListener -->
- <listener>
- <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
- </listener>
- <!-- Declare a Spring MVC DispatcherServlet as usual -->
- <servlet>
- <servlet-name>dispatcher</servlet-name>
- <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
- <!-- Configure DispatcherServlet to use AnnotationConfigWebApplicationContext
- instead of the default XmlWebApplicationContext -->
- <init-param>
- <param-name>contextClass</param-name>
- <param-value>
- org.springframework.web.context.support.AnnotationConfigWebApplicationContext
- </param-value>
- </init-param>
- <!-- Again, config locations must consist of one or more comma- or space-delimited
- and fully-qualified @Configuration classes -->
- <init-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>com.howtodoinjava.web.MvcConfig</param-value>
- </init-param>
- </servlet>
- <!-- map all requests for /app/* to the dispatcher servlet -->
- <servlet-mapping>
- <servlet-name>dispatcher</servlet-name>
- <url-pattern>/app/*</url-pattern>
- </servlet-mapping>
- </web-app>
9、怎样用注解的方式配置Spring?
- <beans>
- <context:annotation-config/>
- <!-- bean definitions go here -->
- </beans>
- @Required:该注解应用于设值方法。
- @Autowired:该注解应用于有值设值方法、非设值方法、构造方法和变量。
- @Qualifier:该注解和@Autowired注解搭配使用,用于消除特定bean自动装配的歧义。
- JSR-250 Annotations:Spring支持基于JSR-250 注解的以下注解,@Resource、@PostConstruct 和 @PreDestroy。
10、请解释Spring Bean的生命周期?
- 初始化之后调用的回调方法。
- 销毁之前调用的回调方法。
- InitializingBean和DisposableBean回调接口
- 针对特殊行为的其他Aware接口
- Bean配置文件中的Custom init()方法和destroy()方法
- @PostConstruct和@PreDestroy注解方式
- <beans>
- <bean id="demoBean" class="com.howtodoinjava.task.DemoBean"
- init-method="customInit" destroy-method="customDestroy"></bean>
- </beans>
11、Spring Bean的作用域之间有什么区别?
- singleton:这种bean范围是默认的,这种范围确保不管接受到多少个请求,每个容器中只有一个bean的实例,单例的模式由bean factory自身来维护。
- prototype:原形范围与单例范围相反,为每一个bean请求提供一个实例。
- request:在请求bean范围内会每一个来自客户端的网络请求创建一个实例,在请求完成以后,bean会失效并被垃圾回收器回收。
- Session:与请求范围类似,确保每个session中有一个bean的实例,在session过期后,bean会随之失效。
- global-session:global-session和Portlet应用相关。当你的应用部署在Portlet容器中工作时,它包含很多portlet。如果你想要声明让所有的portlet共用全局的存储变量的话,那么这全局变量需要存储在global-session中。
12、什么是Spring inner beans?
- public class Customer
- {
- private Person person;
- //Setters and Getters
- }
- public class Person
- {
- private String name;
- private String address;
- private int age;
- //Setters and Getters
- }
内部bean的声明方式如下:
- <bean id="CustomerBean" class="com.howtodoinjava.common.Customer">
- <property name="person">
- <!-- This is inner bean -->
- <bean class="com.howtodoinjava.common.Person">
- <property name="name" value="lokesh" />
- <property name="address" value="India" />
- <property name="age" value="34" />
- </bean>
- </property>
- </bean>
13、Spring框架中的单例Beans是线程安全的么?
14、请举例说明如何在Spring中注入一个Java Collection?
- <list> : 该标签用来装配可重复的list值。
- <set> : 该标签用来装配没有重复的set值。
- <map>: 该标签可用来注入键和值可以为任何类型的键值对。
- <props> : 该标签支持注入键和值都是字符串类型的键值对。
- <beans>
- <!-- Definition for javaCollection -->
- <bean id="javaCollection" class="com.howtodoinjava.JavaCollection">
- <!-- java.util.List -->
- <property name="customList">
- <list>
- <value>INDIA</value>
- <value>Pakistan</value>
- <value>USA</value>
- <value>UK</value>
- </list>
- </property>
- <!-- java.util.Set -->
- <property name="customSet">
- <set>
- <value>INDIA</value>
- <value>Pakistan</value>
- <value>USA</value>
- <value>UK</value>
- </set>
- </property>
- <!-- java.util.Map -->
- <property name="customMap">
- <map>
- <entry key="1" value="INDIA"/>
- <entry key="2" value="Pakistan"/>
- <entry key="3" value="USA"/>
- <entry key="4" value="UK"/>
- </map>
- </property>
- <!-- java.util.Properties -->
- <property name="customProperies">
- <props>
- <prop key="admin">admin@nospam.com</prop>
- <prop key="support">support@nospam.com</prop>
- </props>
- </property>
- </bean>
- </beans>
15、如何向Spring Bean中注入一个Java.util.Properties?
- <bean id="adminUser" class="com.howtodoinjava.common.Customer">
- <!-- java.util.Properties -->
- <property name="emails">
- <props>
- <prop key="admin">admin@nospam.com</prop>
- <prop key="support">support@nospam.com</prop>
- </props>
- </property>
- </bean>
16、请解释Spring Bean的自动装配?
- <bean id="employeeDAO" class="com.howtodoinjava.EmployeeDAOImpl" autowire="byName" />
除了bean配置文件中提供的自动装配模式,还可以使用@Autowired注解来自动装配指定的bean。在使用@Autowired注解之前需要在按照如下的配置方式在Spring配置文件进行配置才可以使用。
- <context:annotation-config />
也可以通过在配置文件中配置AutowiredAnnotationBeanPostProcessor 达到相同的效果。
- <bean class ="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
配置好以后就可以使用@Autowired来标注了。
- @Autowired
- public EmployeeDAOImpl ( EmployeeManager manager ) {
- this.manager = manager;
- }
17、请解释自动装配模式的区别?
- no:这是Spring框架的默认设置,在该设置下自动装配是关闭的,开发者需要自行在bean定义中用标签明确的设置依赖关系。
- byName:该选项可以根据bean名称设置依赖关系。当向一个bean中自动装配一个属性时,容器将根据bean的名称自动在在配置文件中查询一个匹配的bean。如果找到的话,就装配这个属性,如果没找到的话就报错。
- byType:该选项可以根据bean类型设置依赖关系。当向一个bean中自动装配一个属性时,容器将根据bean的类型自动在在配置文件中查询一个匹配的bean。如果找到的话,就装配这个属性,如果没找到的话就报错。
- constructor:造器的自动装配和byType模式类似,但是仅仅适用于与有构造器相同参数的bean,如果在容器中没有找到与构造器参数类型一致的bean,那么将会抛出异常。
- autodetect:该模式自动探测使用构造器自动装配或者byType自动装配。首先,首先会尝试找合适的带参数的构造器,如果找到的话就是用构造器自动装配,如果在bean内部没有找到相应的构造器或者是无参构造器,容器就会自动选择byTpe的自动装配方式。
18、如何开启基于注解的自动装配?
- <beans>
- <context:annotation-config />
- </beans>
2、在bean配置文件中直接引入AutowiredAnnotationBeanPostProcessor
- <beans>
- <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
- </beans>
19、请举例解释@Required注解?
- public class EmployeeFactoryBean extends AbstractFactoryBean<Object>
- {
- private String designation;
- public String getDesignation() {
- return designation;
- }
- @Required
- public void setDesignation(String designation) {
- this.designation = designation;
- }
- //more code here
- }
但是如果没有属性被用 @Required 注解过的话,后置处理器会抛出一个BeanInitializationException 异常。
20、请举例解释@Autowired注解?
@Autowired注解对自动装配何时何处被实现提供了更多细粒度的控制。@Autowired注解可以像@Required注解、构造器一样被用于在bean的设值方法上自动装配bean的属性,一个参数或者带有任意名称或带有多个参数的方法。
比如,可以在设值方法上使用@Autowired注解来替代配置文件中的 <property>元素。当Spring容器在setter方法上找到@Autowired注解时,会尝试用byType 自动装配。
当然我们也可以在构造方法上使用@Autowired 注解。带有@Autowired 注解的构造方法意味着在创建一个bean时将会被自动装配,即便在配置文件中使用<constructor-arg> 元素。
下面是没有构造参数的配置方式:
21、请举例说明@Qualifier注解?
下面我们要在配置文件中来配置Person类。
- <bean id="customer" class="com.howtodoinjava.common.Customer" />
- <bean id="personA" class="com.howtodoinjava.common.Person" >
- <property name="name" value="lokesh" />
- </bean>
- <bean id="personB" class="com.howtodoinjava.common.Person" >
- <property name="name" value="alex" />
- </bean>
Spring会知道要自动装配哪个person bean么?不会的,但是运行上面的示例时,会抛出下面的异常:
- public class Customer
- {
- @Autowired
- @Qualifier("personA")
- private Person person;
- }
22、构造方法注入和设值注入有什么区别?
- 在设值注入方法支持大部分的依赖注入,如果我们仅需要注入int、string和long型的变量,我们不要用设值的方法注入。对于基本类型,如果我们没有注入的话,可以为基本类型设置默认值。在构造方法注入不支持大部分的依赖注入,因为在调用构造方法中必须传入正确的构造参数,否则的话为报错。
- 设值注入不会重写构造方法的值。如果我们对同一个变量同时使用了构造方法注入又使用了设置方法注入的话,那么构造方法将不能覆盖由设值方法注入的值。很明显,因为构造方法尽在对象被创建时调用。
- 在使用设值注入时有可能还不能保证某种依赖是否已经被注入,也就是说这时对象的依赖关系有可能是不完整的。而在另一种情况下,构造器注入则不允许生成依赖关系不完整的对象。
- 在设值注入时如果对象A和对象B互相依赖,在创建对象A时Spring会抛出sObjectCurrentlyInCreationException异常,因为在B对象被创建之前A对象是不能被创建的,反之亦然。所以Spring用设值注入的方法解决了循环依赖的问题,因对象的设值方法是在对象被创建之前被调用的。
23、Spring框架中有哪些不同类型的事件?
- public class AllApplicationEventListener implements ApplicationListener < ApplicationEvent >
- {
- @Override
- public void onApplicationEvent(ApplicationEvent applicationEvent)
- {
- //process event
- }
- }
- 上下文更新事件(ContextRefreshedEvent):该事件会在ApplicationContext被初始化或者更新时发布。也可以在调用ConfigurableApplicationContext 接口中的refresh()方法时被触发。
- 上下文开始事件(ContextStartedEvent):当容器调用ConfigurableApplicationContext的Start()方法开始/重新开始容器时触发该事件。
- 上下文停止事件(ContextStoppedEvent):当容器调用ConfigurableApplicationContext的Stop()方法停止容器时触发该事件。
- 上下文关闭事件(ContextClosedEvent):当ApplicationContext被关闭时触发该事件。容器被关闭时,其管理的所有单例Bean都被销毁。
- 请求处理事件(RequestHandledEvent):在Web应用中,当一个http请求(request)结束触发该事件。
- public class CustomApplicationEvent extends ApplicationEvent
- {
- public CustomApplicationEvent ( Object source, final String msg )
- {
- super(source);
- System.out.println("Created a Custom event");
- }
- }
为了监听这个事件,还需要创建一个监听器:
- public class CustomEventListener implements ApplicationListener < CustomApplicationEvent >
- {
- @Override
- public void onApplicationEvent(CustomApplicationEvent applicationEvent) {
- //handle event
- }
- }
之后通过applicationContext接口的publishEvent()方法来发布自定义事件。
- CustomApplicationEvent customEvent = new CustomApplicationEvent(applicationContext, "Test message");
- applicationContext.publishEvent(customEvent);
24、FileSystemResource和ClassPathResource有何区别?
25、Spring 框架中都用到了哪些设计模式?
- 代理模式—在AOP和remoting中被用的比较多。
- 单例模式—在spring配置文件中定义的bean默认为单例模式。
- 模板方法—用来解决代码重复的问题。比如. RestTemplate, JmsTemplate, JpaTemplate。
- 前端控制器—Spring提供了DispatcherServlet来对请求进行分发。
- 视图帮助(View Helper )—Spring提供了一系列的JSP标签,高效宏来辅助将分散的代码整合在视图里。
- 依赖注入—贯穿于BeanFactory / ApplicationContext接口的核心理念。
- 工厂模式—BeanFactory用来创建对象的实例。