1、什么是Spring?
总的来说Spring是一个轻量级的开源框架,可以用来简化企业级Java应用开发。
2、Spring的优点
①、轻量:Spring是轻量级的,基本的版本只有几M大小。
②、控制反转:Spring通过控制反转实现了松散耦合,对象们给出它们的依赖,而不是创建或查找依赖的对象们,这避免了硬编码所造成的过度程序耦合。
③、AOP:面向切面编程,将业务逻辑与系统服务分开,AOP支持允许将一些通用任务如安全、事务、日志等进行集中式管理,从而提供了更好的复用。
④、容器:Spring 包含并管理应用中对象的生命周期和配置。
⑤、MVC框架:Spring有自带的MVC框架
⑥、事务管理:Spring 提供一个持续的事务管理接口,可以扩展到上至本地事务下至全局事务(JTA)。
⑦、异常处理:Spring 提供方便的API把具体技术相关的异常(比如由JDBC,Hibernate or JDO抛出的)转化为一致的unchecked 异常。
⑧、方便程序的测试:可以用非容器依赖的编程方式进行几乎所有的测试工作,在Spring里,测试不再是昂贵的操作,而是随手可做的事情。例如:Spring对Junit4支持,可以通过注解方便的测试Spring程序。
⑨、方便集成各种优秀框架:Spring不排斥各种优秀的开源框架,相反,Spring可以降低各种框架的使用难度,Spring提供了对各种优秀框架(如Struts,Hibernate、Hessian、Quartz)等的直接支持。
⑩、降低Java EE API的使用难度:Spring对很多难用的Java EE API(如JDBC,JavaMail,远程调用等)提供了一个薄薄的封装层,通过Spring的简易封装,这些Java EE API的使用难度大为降低。
3、Spring中Bean是什么?
凡是有属性和方法的类都需要实例化,这样这些方法和属性才能被具体的调用,凡是子类及带有方法或属性的类都要加上注册Bean到Spring IoC的注解,把Bean理解为类的代理或代言人(实际上确实是通过反射、代理来实现的),这样它就能代表类拥有该拥有的东西了。
也就是说:组成应用程序的主体及由Spring IoC容器所管理的对象,被称之为bean。
实例化Bean的几种常用方式:
①、使用setter方法:
关键步骤:
public interface UserDao {
void getUser();
}
public class UserDaoImpl implements UserDao{
@Override
public void getUser() {
System.out.println("调用getUser方法");
}
}
public class ActionTest {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void test(){
userDao.getUser();
}
}
<bean class="com.dao.UserDaoImpl" id="userDao"/>
<bean id="actionTest" class="com.test.ActionTest">
<property name="userDao" ref="userDao"/>
</bean>
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
ActionTest actionTest = (ActionTest) applicationContext.getBean("actionTest");
actionTest.test();
②、使用构造器:
对①中的例子改造如下:
//将setter方法改为下面这样
private UserDao userDao;
public ActionTest(UserDao userDao){
this.userDao = userDao;
}
//配置文件改成这样
<bean class="com.dao.UserDaoImpl" id="userDao"/>
<bean class="com.test.ActionTest" id="actionTest">
<constructor-arg name="userDao" ref="userDao"/>
</bean>
③、注解方式:
@Repository
public class UserDao {
public void add(){
System.out.println("add");
}
}
@Service
public class UserService {
@Autowired
private UserDao userDao;
public void add(){
userDao.add();
}
}
@Controller
public class ActionTest {
@Autowired
private UserService userService;
public void test(){
userService.add();
}
}
public class TestSpringBean {
@Test
public void testSpringBean(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
ActionTest actionTest = (ActionTest) applicationContext.getBean("actionTest");
actionTest.test();
}
}
配置文件只扫描包就可以了
<context:component-scan base-package="com.dao"/>
<context:component-scan base-package="com.test"/>
4、Spring中Bean作用域
Spring作用域有五种,如下:
Spring中的bean默认都是单例的,这些单例Bean在多线程程序下如何保证线程安全呢?例如对于Web应用来说,Web容器对于每个用户请求都创建一个单独的Sevlet线程来处理请求,引入Spring框架之后,每个Action都是单例的,那么对于Spring托管的单例Service Bean,如何保证其安全呢? Spring的单例是基于BeanFactory也就是Spring容器的,单例Bean在此容器内只有一个,Java的单例是基于JVM,每个JVM内只有一个实例。
①、当一个bean的作用域为Singleton,那么Spring IoC容器中只会存在一个共享的bean实例,并且所有对bean的请求,只要id与该bean定义相匹配,则只会返回bean的同一实例。Singleton是单例类型,就是在创建起容器时就同时自动创建了一个bean的对象,不管你是否使用,他都存在了,每次获取到的对象都是同一个对象。注意,Singleton作用域是Spring中的缺省作用域。要在XML中将bean定义成singleton,可以这样配置:
<bean id="ServiceImpl" class="cn.csdn.service.ServiceImpl" scope="singleton">
②、当一个bean的作用域为Prototype,表示一个bean定义对应多个对象实例。Prototype作用域的bean会导致在每次对该bean请求(将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法)时都会创建一个新的bean实例。Prototype是原型类型,它在我们创建容器的时候并没有实例化,而是当我们获取bean的时候才会去创建一个对象,而且我们每次获取到的对象都不是同一个对象。根据经验,对有状态的bean应该使用prototype作用域,而对无状态的bean则应该使用singleton作用域。在XML中将bean定义成prototype,可以这样配置:
<bean id="account" class="com.foo.DefaultAccount" scope="prototype"/>
或者
<bean id="account" class="com.foo.DefaultAccount" singleton="false"/>
③、当一个bean的作用域为Request,表示在一次HTTP请求中,一个bean定义对应一个实例;即每个HTTP请求都会有各自的bean实例,它们依据某个bean定义创建而成。该作用域仅在基于web的Spring ApplicationContext情形下有效。考虑下面bean定义:
<bean id="loginAction" class=cn.csdn.LoginAction" scope="request"/>
针对每次HTTP请求,Spring容器会根据loginAction bean的定义创建一个全新的LoginAction bean实例,且该loginAction bean实例仅在当前HTTP request内有效,因此可以根据需要放心的更改所建实例的内部状态,而其他请求中根据loginAction bean定义创建的实例,将不会看到这些特定于某个请求的状态变化。当处理请求结束,request作用域的bean实例将被销毁。
④、当一个bean的作用域为Session,表示在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。考虑下面bean定义:
<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>
针对某个HTTP Session,Spring容器会根据userPreferences bean定义创建一个全新的userPreferences bean实例,且该userPreferences bean仅在当前HTTP Session内有效。与request作用域一样,可以根据需要放心的更改所创建实例的内部状态,而别的HTTP Session中根据userPreferences创建的实例,将不会看到这些特定于某个HTTP Session的状态变化。当HTTP Session最终被废弃的时候,在该HTTP Session作用域内的bean也会被废弃掉。
⑤、当一个bean的作用域为Global Session,表示在一个全局的HTTP Session中,一个bean定义对应一个实例。典型情况下,仅在使用portlet context的时候有效。该作用域仅在基于web的Spring ApplicationContext情形下有效。考虑下面bean定义:
<bean id="user" class="com.foo.Preferences "scope="globalSession"/>
globalsession作用域类似于标准的HTTP Session作用域,不过仅仅在基于portlet的web应用中才有意义。Portlet规范定义了全局Session的概念,它被所有构成某个portlet web应用的各种不同的portlet所共享。在global session作用域中定义的bean被限定于全局portlet Session的生命周期范围内。
推荐阅读:Spring中bean的作用域与生命周期
5、Spring注入集合
<!-- 给数组注入值 -->
<property name="empName">
<list>
<value>小米</value>
<value>小明</value>
<value>小四</value>
</list>
</property>
<!-- 给list注入值 可以有相同的多个对象 -->
<property name="empList">
<list>
<ref bean="emp1" />
<ref bean="emp2"/>
</list>
</property>
<!-- 给set注入值 不能有相同的对象 -->
<property name="empSets">
<set>
<ref bean="emp1" />
<ref bean="emp2"/>
</set>
</property>
<!-- 给map注入值 只要map中的key值不一样就可以装配value -->
<property name="empMap">
<map>
<entry key="1" value-ref="emp1" />
<entry key="2" value-ref="emp2" />
</map>
</property>
其余问题参考阅读:Spring基础知识详解
内容有待扩充 … …