Spring中三个重要概念 IOC AOP Bean
首先讲解一下Spring框架,以及为什么要使用Spring 框架?
spring 是一个很好的容器框架, 是轻量级的IoC和AOP的容器框架,主要是针对javaBean的生命周期进行管理的轻量级容器,一般在传统的Java开发中具有高度的耦合性,一个项目中或者一个逻辑功能的实现时,往往一个对象需要依赖很多的对象来完成自己的操作,这样就造成了两个类的依赖关系太强,改一个地方,往往牵扯很多类牵扯大量的代码。
此时Spring就被开发出来, 它可以管理对象和对象之间的依赖关系,我们不需要自己建立对象,把这部分工作全部转交给容器完成,具有低耦合,对代码没有侵略性,对服务器没有依赖性特点的框架
一个简单的例子说明使用和不使用框架的区别:
1 public classUserService{ 2 private UserDao userdao; 3 public void insert(User user){ 4 userdao = new UserDao(); // 需要自己new一个UserDao类型的对象 5 userdao.insert(user); 6 } 7 }
1 public classUserService{ 2 private UserDao userdao; 3 // 设置 set和get函数,在运行时,Spring会将UserDao对象会自动注入到该类中 4 public UserDao getUserdao() { 5 return userdao; 6 } 7 public void setUserdao(UserDao userdao) { 8 this.userdao= userdao; 9 } 10 11 public void insert(User user){ 12 userdao.insert(user); // 不需要自己new对象了 13 } 14 }
IOC DI
在Spring之中,始终最为重要的两个思想就是 控制反转IOC, 和依赖注入DI 有人认为 DI(依赖注入)是实现IoC的一种方法,也有人认为DI 只是IoC的另一种说法。没有IoC的程序中我们使用面向对象编程对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了。
java程序中的每个业务逻辑至少需要两个或以上的对象来协作完成,通常,每个对象在使用他的合作对象时,自己均要使用像new object() 这样的语法来完成合作对象的申请工作。你会发现:对象间的耦合度高了。而IOC的思想是:Spring容器来实现这些相互依赖对象的创建、协调工作。对象只需要关系业务逻辑本身就可以了。从这方面来说,对象如何得到他的协作对象的责任被反转了(IOC、DI)
引用一个网上比较火的例子,
那么IoC是如何做的呢?有点像通过婚介找女朋友,在我和女朋友之间引入了一个第三者:婚姻介绍所。婚介管理了很多男男女女的资料,我可以向婚介提出一个列表,告诉它我想找个什么样的女朋友,比如长得像李嘉欣,身材像林熙雷,唱歌像周杰伦,速度像卡洛斯,技术像齐达内之类的,然后婚介就会按照我们的要求,提供一个mm,我们只需要去和她谈恋爱、结婚就行了。简单明了,如果婚介给我们的人选不符合要求,我们就会抛出异常。整个过程不再由我自己控制,而是有婚介这样一个类似容器的机构来控制。Spring所倡导的开发方式就是如此,所有的类都会在spring容器中登记,告诉spring你是个什么东西,你需要什么东西,然后spring会在系统运行到适当的时候,把你要的东西主动给你,同时也把你交给其他需要你的东西。所有的类的创建、销毁都由 spring来控制,也就是说控制对象生存周期的不再是引用它的对象,而是spring。对于某个具体的对象而言,以前是它控制其他对象,现在是所有对象都被spring控制,所以这叫控制反转。
IoC的一个重点是在系统运行中,动态的向某个对象提供它所需要的其他对象。这一点是通过DI(Dependency Injection,依赖注入)来实现的。比如对象A需要操作数据库,以前我们总是要在A中自己编写代码来获得一个Connection对象,有了 spring我们就只需要告诉spring,A中需要一个Connection,至于这个Connection怎么构造,何时构造,A不需要知道。在系统运行时,spring会在适当的时候制造一个Connection,然后像打针一样,注射到A当中,这样就完成了对各个对象之间关系的控制。A需要依赖 Connection才能正常运行,而这个Connection是由spring注入到A中的,依赖注入的名字就这么来的。
那么DI是如何实现的呢? 反射实现(reflection),它允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性,spring就是通过反射来实现注入的。
在上面的例子中,使用框架之后在classUserService类中不需要new一个UserDao对象了,取而代之的是 生成set和get方法,这样在程序运行的时候Spring就可以自己从容器中生成一个UserDao对象,利用反射的方式注入到 该类中。
Spring IOC 实现的一个小例子, 该例子转载自博客:
http://blog.csdn.net/frightingforambition/article/details/47974775
spring IOC容器的关键点:
* 必须将被管理的对象定义到spring配置文件中
* 必须定义构造函数或setter方法,让spring将对象注入过来
1 Spring IOC具体如何实现? 2 3 上文中的婚介所就是ioc管理对象的容器,实际上是一个xml文件,将对象配置在xml里面,通过spring的工厂类进行解析,以“反射”的方式创建对象。 4 5 我们可以通过下面这里例子理解spring ioc的实现。本例使用spring 3.2 6 1.配置applicationContext.xml 7 8 <beans xmlns="http://www.springframework.org/schema/beans" 9 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 10 xsi:schemaLocation="http://www.springframework.org/schema/beans 11 http://www.springframework.org/schema/beans/spring-beans-3.2.xsd"> 12 <bean id="userDao4MySqlImpl" class="com.bjsxt.spring.dao.UserDao4MySqlImpl"/> 13 <bean id="userDao4OracleImpl" class="com.bjsxt.spring.dao.UserDao4OracleImpl"/> 14 <bean id="userManager" class="com.bjsxt.spring.manager.UserManagerImpl"> 15 <!-- 构造方法注入 16 <constructor-arg ref="userDao4OracleImpl"/> 17 --> 18 <!-- setter方法注入 而且指定注入的对象为userDao4OracleImpl类型对象--> 19 <property name="userDao" ref="userDao4OracleImpl"/> 20 </bean> 21 </beans> 22 23 2.注入的类: 24 25 package com.bjsxt.spring.dao; 26 27 public interface UserDao { 28 29 public void save(String username, String password); 30 } 31 32 package com.bjsxt.spring.dao; 33 34 public class UserDao4MySqlImpl implements UserDao { 35 36 public void save(String username, String password) { 37 System.out.println("--------UserDao4MySqlImpl.save()-------"); 38 } 39 } 40 41 package com.bjsxt.spring.dao; 42 43 public class UserDao4OracleImpl implements UserDao { 44 45 public void save(String username, String password) { 46 System.out.println("--------UserDao4OracleImpl.save()-------"); 47 } 48 } 49 50 3.被注入的类: 51 52 package com.bjsxt.spring.manager; 53 54 public interface UserManager { 55 public void save(String username, String password); 56 } 57 58 package com.bjsxt.spring.manager; 59 60 import com.bjsxt.spring.dao.UserDao; 61 62 public class UserManagerImpl implements UserManager { 63 /** 64 * 两种方式:如果这个类中需要注入对象,先建立对象属性, 65 * 在写构造方法或者set方法。 66 * 67 */ 68 private UserDao userDao; 69 70 /* 构造方法实现 71 public UserManagerImpl(UserDao userDao) { 72 this.userDao = userDao; 73 } */ 74 75 public void save(String username, String password) { 76 this.userDao.save(username, password); 77 } 78 // set方式实现 79 public void setUserDao(UserDao userDao) { 80 this.userDao = userDao; 81 } 82 } 83 84 4.测试类: 85 86 package com.bjsxt.spring.client; 87 88 import org.springframework.beans.factory.BeanFactory; 89 import org.springframework.context.support.ClassPathXmlApplicationContext; 90 91 import com.bjsxt.spring.manager.UserManager; 92 93 public class Client { 94 95 public static void main(String[] args) { 96 /* 传统的通过new对象建立类之间的关系 97 * UserManager userManager = new UserManagerImpl(new UserDao4OracleImpl()); 98 UserManager userManager = new UserManagerImpl(new UserDao4MySqlImpl()); 99 userManager.save("张三", "123");*/ 100 /** 101 * IOC思想 通过工厂类解析xml文件,以“反射”的方式创建对象: 102 */ 103 BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml"); 104 UserManager userManager = (UserManager)factory.getBean("userManager"); 105 userManager.save("张三", "123"); 106 /** 107 * IOC思想 实际的执行过程,这也是为什么需要setter方法或构造方法的原因: 108 */ 109 // UserManagerImpl userManager = new UserManagerImpl(); 110 // userManager.setUserDao(new UserDao4OracleImpl()); 根据配置文件可知,这里set的对象是UserDao4OracleImpl对象 111 // userManager.save("张三", "123"); 112 } 113 }
面向Bean
Spring 是面向 Bean 的编程(Bean Oriented Programming, BOP),Bean 在 Spring 中才是真正的主角。Bean 在 Spring 中作用就像 Object 对 OOP 的意义一样,Spring 中没有 Bean 也就没有 Spring 存在的意义。Spring 提供了 IoC容器通过配置文件或者注解的方式来管理对象之间的依赖关系。
Spring 设计的核心 org.springframework.beans 包(架构核心是org.springframework.core包),它的设计目标是与 JavaBean 组件一起使用。这个包通常不是由用户直接使用,而是由服务器将其用作其他多数功能的底层中介。下一个最高级抽象是 BeanFactory 接口,它是工厂设计模式的实现,允许通过名称创建和检索对象。BeanFactory 也可以管理对象之间的关系。
BeanFactory 支持两个对象模型。 1,单例:模型提供了具有特定名称的对象的共享实例,可以在查询时对其进行检索。Singleton 是默认的,也是最常用的对象模型。对于无状态服务对象很理想。 2,原型:模型确保每次检索都会创建单独的对象。在每个用户都需要自己的对象时,原型模型最适合。 bean 工厂的概念是 Spring 作为 IoC容器的基础。IoC则将处理事情的责任从应用程序代码转移到框架。
AOP 面向切面编程 Aspect Oriented Programming
Aop,是一种编程技术,它允许程序员对横切关注点或横切典型的职责分界线的行为(例如日志和事务管理)进行模块化。Aop的核心构造是方面,它将那些影响多个类的行为封装到可重用的模块中。Aop的功能完全集成到了 Spring 事务管理、日志和其他各种特性的上下文中。
举个例子说明一下吧,比如——————银行会有这样的两个流程, 取款和显示余额, 然而在这两个流程中有着同样的一个操作:用户验证,那么可不可以把用户验证封装成一个模块取出来呢? 然后在需要的时候注入到这两个流程中?
这就是AOP的作用了,有了AOP,你写代码时不要把这个验证用户步骤写进去,即完全不考虑验证用户,你写完之后,在另我一个地方,写好验证用户的代码,然后告诉Spring你要把这段代码加到哪几个地方,Spring就会帮你加过去,而不要你自己Copy过去,这样的好处是当流程变的越来越多时,只需要写一遍用户验证程序,可以节省写代码的时间,不过最主要的是你写代码的时候,事先只需考虑主流程,而不用考虑那些不重要的流程,在事后就使用AOP就可以给所有流程一次性加入验证代码,而你只需要写一次验证代码
所以 AOP的本质是在一系列纵向的控制流程中,把那些相同的子流程提取成一个横向的面,面向这些横向的面进行操作。
本文参考了:
https://my.oschina.net/yanquan345/blog/203415
http://blog.csdn.net/frightingforambition/article/details/47974775
http://blog.csdn.net/woshiluoye9/article/details/72770717