Spring简介

Spring是一个开源的控制反转(Inversion of Control,IOC)和面向切面(AOP)的容器框架,它的组要目的就是简化企业开发。


IOC控制反转

public class UserServiceImpl {

	/*创建Dao*/
	private IUserDao userDao = new UserDaoImpl();
	
	public void save(){
		/*保存用户*/
		userDao.delete(1);
	}
}
注:UserDaoImpl是在应用内部创建及维护的。所谓控制反转就是应用本身不负责依赖对象的创建及维护,依赖对象的创建及维护是由外部容器负责的,这样控制权就由应用转移到了外部容器,控制权的转移就是所谓的反转。


依赖注入(Dependency Injection)

当我们把依赖对象交给外部容器负责创建,那么UserServiceImpl类可以改成如下:

public class UserServiceImpl {

	/*创建Dao*/
	private IUserDao userDao;
	
	/**
	 * 通过构造函数,让容器把创建好的依赖对象注入进UserServiceImpl
	 * 也可以使用setter的方法进行注入
	 * @param userDao
	 */
	public UserServiceImpl(IUserDao userDao) {
		this.userDao = userDao;
	}


	public void save(){
		/*保存用户*/
		userDao.delete(1);
	}
}

注:所谓的依赖注入就是指:在运行期,由外部容器动态的将依赖对象注入到组件中。


在项目中引入Spring的好处:

1.降低组件之间的耦合度,实现软件各层之间的解耦。


2.可以使用容器的众多服务,如:事物管理服务,消息服务等等。当我们使用容器管理事物时,开发人员就不需要手工控制事物,也不需要处理复杂的事物传播。

3.容器提供单例模式支持,开发人员不再需要自己编写实现代码。

4.容器提供AOP技术,利用它很容易实现如权限拦截、运行期监控等功能。

5.容器提供的众多辅助类,使用这些类能够加快应用的开发,如:JdbcTemplate、HibernateTemplate。

6.Spring对于主流的应用框架提供了集成支持,如:集成Hibernate、JPA(一种规范,非框架)、Struts等,这样更便于应用的开发。

Springle提供的众多服务:



轻量级框架和重量级框架的划分标准:

划分一个应用框架是轻量级还是重量级,主要是看它使用了多少服务,使用的服务越多,容器要为普通Java对象做的工作就越多,必然会影响到应用的发布时间或者是运行性能,即依赖的服务多,就表示重量级。对于Spring而言,他提供了很多服务默认是不开启的,应用到某种服务时,还需要指明使用某种服务,如果应用使用的服务很少,如:只使用Spring核心服务,那么我们可以认为此时应用属于轻量级的,如果应用使用了Spring提供的大部分功能服务,这时应用就属于重量级。目前EJB容器就因为它默认应用提供了EJB规范中所有的功能,所以它就属于重量级。


Spring的jar包说明(Spring3.x和2.x的不一样,新版本把原来的包分解了,功能分工明确):

org.springframework.aop-3.1.1.RELEASE.jar:spring 的面向切面编程,提供AOP(面向切面编程)实现,

org.springframework.asm-3.1.1.RELEASE.jar:Spring独立的asm程序, Spring2.5.6的时候需要asmJar 包,3.0开始提供他自己独立的asm.jar 。ASM是小巧轻便的 Java 字节码操控框架 ,它能方便地生成和改造 Java 代码。 Hibernate 和 Spring 在底层都用到了 ASM(CgLib 底层用的 asm)。

org.springframework.aspects-3.1.1.RELEASE.jar:spring整合了aspectjrt.jar,也可以使用aspectjrt.jar来代替。

org.springframework.beans-3.1.1.RELEASE.jar:springIoC(依赖注入)的基础实现,所有应用都要用到的,它包含访问配置
文件、创建和 管理bean以及进行Inversion of Control / Dependency Injection(IoC/DI)操作相关的所有类。

org.springframework.context.support-3.1.1.RELEASE.jar:spring-context 的扩展支持,包含支持缓存Cache(ehcache)、JCA、JMX、邮 件服务(Java Mail、COS Mail)、任务计划Scheduling(Timer、Quartz)方面的类。

org.springframework.context-3.1.1.RELEASE.jar:spring 提供在基础 IoC 功能上的扩展服务,此外还提供许多企业级服务的支持,如 邮件 服务、任务调度、JNDI定位、EJB 集成、远程访问、 缓存以及各种视图层框架的封装等。

org.springframework.core-3.1.1.RELEASE.jar:包含Spring框架基本的核心工具类,Spring其它组件要都要使用到这个包里的类,是其它组 件的基本核心。

org.springframework.expression-3.1.1.RELEASE.jar:spring 表达式语言。

org.springframework.instrument.tomcat-3.1.1.RELEASE.jar:spring3.1 对 Tomcat 的连接池的基成。

org.springframework.instrument-3.1.1.RELEASE.jar:spring3.1 对服务器的代理接口。

org.springframework.jdbc-3.1.1.RELEASE.jar:包含对Spring对JDBC数据访问进行封装的所有类。

org.springframework.jms-3.1.1.RELEASE.jar:提供了对JMS 1.0.2/1.1的支持类。

org.springframework.orm-3.1.1.RELEASE.jar:包含Spring对DAO特性集进行了扩展,使其支持 iBATIS、JDO、OJB、TopLink,因为Hibernate 已经独立成包了,现在不包含在这个包里了。这个jar文件里大部分的类都要依赖spring-dao.jar里的类,用这个包时你需要同时包含spring-dao.jar包 。

org.springframework.oxm-3.1.1.RELEASE.jar:spring 对Object/XMI 的映射的支持,可以让JAVA与XML之间来回切换。

org.springframework.test-3.1.1.RELEASE.jar:spring 对Junit 等测试框架的简单封装。

org.springframework.transaction-3.1.1.RELEASE.jar:为为JDBC、Hibernate、JDO、JPA等提供的一致的声明式和编程式事务管理。

org.springframework.web.portlet-3.1.1.RELEASE.jar:springMVC 的增强,支持portlet标准(JSR168/JSR286)。

org.springframework.web.servlet-3.1.1.RELEASE.jar:对 J2EE6.0 Servlet3.0 的支持。

org.springframework.web.struts-3.1.1.RELEASE.jar:整合 Struts 的支持。

org.springframework.web-3.1.1.RELEASE.jar:包含Web应用开发时,用到Spring框架时所需的核心类,包括自动载入WebApplicationContext 特性的类、Struts与JSF集成类、文件上传的支持类、Filter类和大量工具辅助类。




实例化Spring容器

方法一(重点),在类路径下寻找配置文件来实例化容器:

/*实例化Spring容器*/
		ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[]{"beans.xml"});

方法二,在文件系统路径下寻找配置文件来实例化容器:

/*实例化Spring容器*/
		ApplicationContext ctx = new FileSystemXmlApplicationContext(new String[]{"d:\beans.xml"});

注:从上述两种方式的代码中,我们就可以看出Spring的配置文件可以指定多个,然后通过String数组的形式传入。


从Spring容器中获取bean对象

当Spring容器启动后,它可以管理bean对象的创建,销毁等声明周期,所以我们只需要从容器中获取Bean对象就行,而不用编写一句代码来创建bean对象。从容器中获取bean对象的代码:

/*实例化Spring容器*/
		ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[]{"beans.xml"});
		/*从容器中获取bean对象*/
		IUserDao userDao = (IUserDao) ctx.getBean("userServiceImpl");

注:getBean(XXX)是根据id(在beans.xml文件中配置)来获取bean对象,也可以根据名称去获取。


Spring容器的实现原理比较简单,我们可以构造自己Spring容器:

首先构造一个Bean的对象模型:

public class MyBean {

	/*bean的id*/
	private String id;
	/*类的名称*/
	private String className;
	
	/*无参构造函数【如果声明带参数的构造函数,无参构造函数必须显示声明】*/
	public MyBean() {
	}
	/*构造函数*/
	public MyBean(String id, String className) {
		this.id = id;
		this.className = className;
	}
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getClassName() {
		return className;
	}
	public void setClassName(String className) {
		this.className = className;
	}
	
	
}

构造工厂:

public class BeanFramework {

	/* 保存XML文件中解析出来的MyBean对象,保存id和类名 */
	private List<MyBean> lists = new ArrayList<>();
	/* 保存所有bean中所映射的类对象 */
	private Map<String, Object> beans = new HashMap<String, Object>();

	/*无参构造函数*/
	public BeanFramework() {
	}

	/*构造函数*/
	public BeanFramework(String filename){
		/*初始化*/
		init(filename);
		/*初始化、实例化所有的Bean所映射的类对象*/
		initObject();
	}


	/**
	 * Dom4j解析XML文件
	 * @param filename
	 */
	private void init(String filename) {
		SAXReader saxReader = new SAXReader();
		Document document = null;
		try {
			URL xmlpath = this.getClass().getClassLoader().getResource(filename);
			document = saxReader.read(xmlpath);
			Map<String, String> nsMap = new HashMap<String, String>();
			nsMap.put("ns", "http://www.springframework.org/schema/beans");// 加入命名空间
			XPath xsub = document.createXPath("//ns:beans/ns:bean");// 创建beans/bean查询路径
			xsub.setNamespaceURIs(nsMap);// 设置命名空间
			List<Element> beans = xsub.selectNodes(document);// 获取文档下所有bean节点
			for (Element element : beans) {
				/*从配置文件中读取id的属性值*/
				String id = element.attributeValue("id");
				/*从配置文件汇总 获取class的属性值*/
				String clazz = element.attributeValue("class");
				/*构造一个MyBean对象*/
				MyBean bean = new MyBean(id, clazz);
				/*把MyBean对象存放在list集合中*/
				lists.add(bean);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 实例化对象
	 */
	private void initObject(){
		
		/*遍历lis集合,从中取出每个MyBean对象*/
		for (MyBean bean : lists){
			/*获取id*/
			String key = bean.getId();
			/*通过反射获取类的实例*/
			Object obj = null;
			try {
				/*获取类名,然后通过反射机制利用类名构造出类的实例对象*/
				obj = Class.forName(bean.getClassName()).newInstance();
			} catch (Exception e) {
				e.printStackTrace();
			} 
			/*把bean对象存储到Map集合中*/
			beans.put(key, obj);
		}
	}
	
	/**
	 * 获取Bean
	 * @param id
	 * @return
	 */
	public Object getBean(String id){
		if (beans.containsKey(id)){
			return beans.get(id);
		}
		return null;
	}
}

测试类:

public class SpringTest {

	public static void main(String[] args) {
		/*初始化Spring容器*/
		BeanFramework ctx = new BeanFramework("beans.xml");
		/*ctx.getBean("userServiceImpl")获取Bean*/
		System.out.println(ctx.getBean("userServiceImpl"));
	}
}

实例化Bean有三种方式

1.使用类构造器实例化(在beans.xml文件中配置)

<bean id="userServiceImpl" class="com.lixue.service.impl.UserServiceImpl"></bean>
注:这种方式是最常用的,但是这种方式有一个前提条件,那就是必须要提供无参的构造方法(上述代码就表示在UserServiceImpl类中必须要有无参构造方法),其实原因很简单,我们之前在构造自己的Spring容器的时候,有一句关键代码:
 Class.forName(bean.getClassName()).newInstance()
可以看出,Spring内部是根据无参构造函数来创建实例对象的。

注:其他两种方式不讲,因为用的非常少。

Bean的作用域:

<bean id="userServiceImpl" class="com.lixue.service.impl.UserServiceImpl" scope="prototype"></bean>
1.singleton表示在每个Spring IOC容器中一个bean定义只有一个对象实例即单例模式。

2.prototy每次从容器获取的bean都是新的对象。

注:根据经验,通常情况下,有状态(所谓有状态通俗的讲就是该类中有属性)的bean就应该使用prototype,无状态(所谓无状态通俗的讲就是该类中没有属性,只有方法)的bean应该使用singleton。

3.request表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTPrequest内有效。

4.Session表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP Session内有效。

5.globalSession仅仅在基于portlet的web应用中才有意义。


bean的延迟加载

在beans结点中加上:

default-lazy-init="true"
就表示所有的bean都会延迟加载(项目启动的时候并不会马上实例化bean,知道访问的时候才去实例化).

同样的我们可以单独为某一个bean结点设置延迟加载属性:

<bean id="userServiceImpl" class="com.lixue.service.impl.UserServiceImpl" lazy-init="true"></bean>


另外可能会有这种需求:在某个bean实例化或者销毁的时候搞点业务!这时候我们可以在bean结点中使用init-method和destroy-method属性,如下:

<bean id="userServiceImpl" class="com.lixue.service.impl.UserServiceImpl" init-method="init" destroy-method="close"></bean>
注:这两个属性的值都是方法名,然后我们可以在这个bean对应的类中定义init()和close()方法。这两个方法必须是无参的,可以有返回值。


手动关闭Spring容器:

AbstractApplicationContext ctx= new ClassPathXmlApplicationContext(new String[]{"beans.xml"});
		ctx.close();

从代码中可以看出,我们用的是AbstractApplicationContext而不是ApplicationContext,我是吃饱了没事干才会用它的吗?显然不是的,因为ApplicationContext对象是么有close()方法的,所以我们只能用那个。


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值