Spring--IOC
来源:互联网 发布:虚拟机下安装linux 编辑:程序博客网 时间:2024/06/06 00:12
经典讲述IOC的博客:http://blog.csdn.net/qq_22654611/article/details/52606960
1 控制反转(Inversion of Control)简称IOC,IOC的思想是:Spring容器来实现这些相互依赖对象的创建、协调工作。对象只需要关系业务逻辑本身就可以了。由spring来负责控制对象的生命周期和对象间的关系。从这方面来说,对象如何得到他的协作对象的责任被反转了(IOC、DI)。IoC的一个重点是在系统运行中,动态的向某个对象提供它所需要的其他对象。这一点是通过DI(Dependency Injection,依赖注入)来实现的。比如对象A需要操作数据库,以前我们总是要在A中自己编写代码来获得一个Connection对象,有了 spring我们就只需要告诉spring,A中需要一个Connection,至于这个Connection怎么构造,何时构造,A不需要知道。org.springframework.beans及org.springframework.context包 是Spring IoC容器的基础,ApplicationContext 是BeanFactory的扩展,功能得到了进一步增强,比如更易 与Spring AOP集成、资源处理(国际化处理)、事件传递及各种不同应用层的context实现 BeanFactory 是Spring IoC容器的实际代表者,IoC容器负责容纳此前所描述的bean,并对bean进行管理。BeanFactory是IoC容器的核心接口。 它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。Spring为我们提供了许多易用的BeanFactory实现, XmlBeanFactory就是最常用的一个。
2 XML的配置元数据的基本结构:
<bean name="hello" class="cn.sxt.bean.Hello"> <property name="name" value="张三"></property> </bean>
Spring IoC容器的实例化:
public class Hello { private String name; public void setName(String name) { this.name = name; } public void show(){ System.out.println("hello,"+name); }}//解析beans.xml文件 生成管理相应的bean对象 ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml"); Hello hello=(Hello)context.getBean("hello"); hello.show();
3.2 实例化bean
3.2.1 构造器实例化Bean:
beans.xml:<bean id="u" class="cn.sxt.vo.User"/>ApplicationContext ac=new ClassPathXmlApplicationContext("beans.xml"); User user=(User)ac.getBean("u"); System.out.println(user);
需要注意的是一定要存在一个默认的构造器。
3.2.2 使用静态工厂方法实例化
<!-- factory-method指定创建对象的静态方法 --> <bean id="u" class="cn.sxt.vo.User" factory-method="newinstance"/>测试:ApplicationContext ac=new ClassPathXmlApplicationContext("beans.xml"); User user=(User)ac.getBean("u"); System.out.println(user);
3.2.3 使用实例化方法实例
<bean id="userFactory" class="cn.sxt.factory.UserDynamicFactory"/> <!-- factory-bean设置创建对象的工厂 factory-method指定创建对象的方法--> <bean id="user" factory-bean="userFactory" factory-method="newinstance"/>
3.2.4 使用容器:
Resource res=new FileSystemResource("src/beans.xml");BeanFactory bean=new XmlBeanFactory(res);User user=(User)bean.getBean("user");System.out.println(user.getName());<bean id="u" class="cn.sxt.vo.User" factory-method="newinstance"/>
4 注入依赖
依赖注入(DI)背后的基本原理是对象之间的依赖关系(即一起工作的其它对象)只会通过以下几种方式来实现:构造器的参数、工厂方法的参数,或给由构造函数或者工厂方法创建的对象设置属性。因此,容器的工作就是创建bean时注入那些依赖关系。
4.1 构造器注入
基于构造器的DI通过调用带参数的构造器来实现,每个参数代表着一个依赖。
4.1.1 构造器参数解析
构造器参数解析根据参数类型进行匹配,如果bean的构造器参数类型定义非常明确,那么在bean被实例化的时候,bean定义中构造器参数的定义顺序就是这些参数的顺序,依次进行匹配。
public class Foo { public Foo(Bar bar, Baz baz) { // ... }}<bean name="foo" class="x.y.Foo"> <constructor-arg> <bean class="x.y.Bar"/> </constructor-arg> <constructor-arg> <bean class="x.y.Baz"/> </constructor-arg> </bean>
4.1.2 构造器参数类型匹配
<bean id="user" class="cn.sxt.vo.User"> <!-- 通过参数类型进行匹配 --> <constructor-arg type="java.lang.String" value="tang"/> </bean>
4.1.3 构造参数索引
<bean id="user" class="cn.sxt.vo.User"> <!-- 根据参数的位置设置为索引来对指定位置的数进行注入 从0开始--> <constructor-arg index="0" value="tang"/> </bean>
4.2 Setter注入
4.2.1 通过调用无参构造器或无参static工厂方法实例化bean之后,调用该bean的setter方法,即可实现基于setter的DI。
<bean id="mysqlDao" class="cn.sxt.dao.impl.UserDaoMySqlImpl"/> <bean id="oralceDao" class="cn.sxt.dao.impl.UserDaoOracleImpl"/> <bean id="service" class="cn.sxt.service.impl.UserServiceImpl"> <!-- ref引用对象,通过Id引用对象注入 --> <!-- 随着此处位置的引用的不同ID,而UserDaoMySqlImpl和UserDaoO racleImpl均实现UserDao接口,将注入不同的对象 --> <property name="userDao" ref="oralceDao"></property> </bean>public class UserDaoMySqlImpl implements UserDao{ @Override public void getUser() { System.out.println("mysql获取用户数据"); }}public class UserDaoOracleImpl implements UserDao{ @Override public void getUser() { // TODO Auto-generated method stub System.out.println("orac获取用户数据"); }}public interface UserService { public void getUser();}public class UserServiceImpl implements UserService{ private UserDao userDao=null; public void setUserDao(UserDao userDao) { this.userDao = userDao; } @Override public void getUser() { userDao.getUser(); }}
4.2.2 注入到构造器
<bean id="service" class="cn.sxt.service.impl.UserServiceImpl"> <constructor-arg> <ref bean="oralceDao"/> </constructor-arg> </bean>
4.2.3 采用static工厂方法返回对象实例:
<!-- 在BeanFactoryCustom中定义一个bean静态方法, --> <bean id="service" class="cn.sxt.service.impl.BeanFactoryCustom" factory-method="createInstance"> <!-- 注入到bean静态方法中 --> <constructor-arg ref="oralceDao"/> </bean>public class UserServiceImpl implements UserService{ private UserDao userDao=null; public UserServiceImpl(UserDao userDao) { this.userDao = userDao; } public void setUserDao(UserDao userDao) { this.userDao = userDao; } @Override public void getUser() { userDao.getUser(); }}public static UserServiceImpl createInstance(UserDao userDao){ //根据参数创建对象 return new UserServiceImpl(userDao); }
5 集合:
需要注意的是,数据注入时,Spring的底层会强制发生强制转换。没有value值时,将设置为“ ”值,即空字符串。
<bean id="addr" class="cn.sxt.vo.Address"> <property name="address" value="北京西三旗"></property> </bean> <bean id="student" class="cn.sxt.vo.Student"><!-- 注入属性 --> <property name="name" value="张三丰"></property><!-- 注入对象 --> <property name="addr" ref="addr"/><!-- 注入数组 --> <property name="books"> <array> <value>傲慢与偏见</value> <value>仲夏之梦</value> <value>雾都孤儿</value> </array> </property> <!-- 注入List集合 --> <property name="hobbies"> <list> <value>羽毛球</value> <value>乒乓球</value> <value>玻璃球</value> </list> </property> <!-- 注入Map集合 --> <property name="cards"> <map> <entry key="中国银行" value="1212121"></entry> <entry key="建设银行" value="1223232"></entry> <entry key="交通银行" value="1323232"></entry> </map> </property> <!-- 注入Set集合 --> <property name="games"> <set> <value>lol</value> <value>dota</value> <value>cs</value> <value>dnf</value> </set> </property> <!-- 注入字符 --> <property name="wife"> <null/> </property> <!-- 注入配置信息 --> <property name="info"> <props> <prop key="学号">20150512601</prop> <prop key="sex">男</prop> <prop key="name">小乔</prop> </props> </property> </bean>
还可以使用p名称空间配置属性如下:
<bean name="john-classic" class="com.example.Person"> <property name="name" value="John Doe"/> <property name="spouse" ref="jane"/> </bean> <bean name="john-modern" class="com.example.Person" p:name="John Doe" p:spouse-ref="jane"/> <bean name="jane" class="com.example.Person"> <property name="name" value="Jane Doe"/> </bean></beans>
需要说明的是集合支持合并,子集合将会覆盖父集合中的数据。List集合由于是有序存在的。父集合中的数据将在子集合元素之前。不同集合类型之间是不能合并的。
如:
<beans><bean id="parent" abstract="true" class="example.ComplexObject"> <property name="adminEmails"> <props> <prop key="administrator">administrator@example.com</prop> <prop key="support">support@example.com</prop> </props> </property></bean><bean id="child" parent="parent"> <property name="adminEmails"> <!-- the merge is specified on the *child* collection definition --> <props merge="true"> <prop key="sales">sales@example.com</prop> <prop key="support">support@example.co.uk</prop> </props> </property></bean><beans>
6 depends-on属性
depends-on属性可以用于当前bean初始化之前显式地强制一个或多个bean被初始化。防止出现依赖的对象没有生成。
7 方法注入:
7.1 在大部分情况下,容器中的bean都是singleton类型的。如果一个singleton bean要引用另外一个singleton bean,或者一个非singleton bean要引用另外一个非singleton bean时,通常情况下将一个bean定义为另一个bean的property值就可以了。对于不同周期的Bean,当一个singleton类型的Bean A中的方法需要使用另一个全新的非singleton类型的Bean B时,那么只能通过实现BeanFactoryAware接口,在需要的地方使用getBean(” “)请求一个Bean实例。
如下:
public class CommandManager implements BeanFactoryAware { private BeanFactory beanFactory; public Object process() { System.out.println("process"); //获取一个实例 Command command = createCommand(); //执行Command中的方法 return command.execute(); } /** * 获取一个command实例 * @return Command对象 */ protected Command createCommand() { return (Command) this.beanFactory.getBean("command"); } public void setBeanFactory(BeanFactory beanFactory) throws BeansException { System.out.println("setBeanFactory"); this.beanFactory = beanFactory; }}
其中setBeanFactory方法,在Bean的属性初始化后调用。
执行结果:
参考:http://blog.csdn.net/heyutao007/article/details/5981555
7.2 通过lookup方式:
定义一个抽象类,包含一个抽象方法,访问级别必须是public或protected,保证能被子类重载,可以是抽象方法,必须有返回值,必须是无参数方法,用于创建需要注入的方法的Bean。
public abstract class HelloImpl5 implements HelloApi { private Printer printer; //放回一个全新的对象。 public abstract Printer createPrototypePrinter(); } <bean id="prototypePrinter" class="cn.javass.spring.chapter3.bean.Printer" scope="prototype"/> <bean id="singletonPrinter" class="cn.javass.spring.chapter3.bean.Printer" scope="singleton"/> <bean id="helloApi1" class="cn.javass.spring.chapter3.HelloImpl5" scope="singleton"> <property name="printer" ref="prototypePrinter"/> //生成一个bean对应的对象作为createPrototypePrinter的返回值。<lookup-method name="createPrototypePrinter" bean="prototypePrinter"/> </bean>
7.3 方法替换
1 定义一个类实现MethodReplacer接口,实现reimplement方法,参数obj为被替换方法的对象,method为被替换方法,args为方法参数;
2 配置
,使用< replaced-method >标签来指定要进行替换方法,属性name指定替换的方法名字,replacer指定该方法的重新实现者,子标签< arg-type >用来指定原来方法参数的类型,必须指定否则找不到原方法,如下将print替换:
<bean id="replacer" class="cn.javass.spring.chapter3.bean.PrinterReplacer"/> <bean id="printer" class="cn.javass.spring.chapter3.bean.Printer"> <replaced-method name="print" replacer="replacer"> <arg-type>java.lang.String</arg-type> </replaced-method> </bean>
参考博客:http://jinnianshilongnian.iteye.com/blog/1415461,感谢大神的分享。
8 Bean的作用域
创建一个bean定义,其实质是用该bean定义对应的类来创建真正实例的“配方(recipe)”。把bean定义看成一个配方很有意义,它与class很类似,只根据一张“处方”就可以创建多个实例。你不仅可以控制注入到对象中的各种依赖和配置值。
可自定义bean的作用域,步骤如下:
8.1 继承org.springframework.beans.factory.config.Scope接口,接口中的方法说明:
第一个方法可以从作用域中获取对象。
Object get(String name, ObjectFactory objectFactory)
第二个方法可以从作用域中移除对象。例如,session作用域的实现可以从session中移除并返回session-scoped bean(如果没有找到相应名称的对象昂,则可以返回null)。
Object remove(String name)
第三个方法是注册作用域析构的回调方法,当作用域销毁或作用域中的某个对象销毁时候会执行。。
void registerDestructionCallback(String name, Runnable destructionCallback)
最后一个方法处理作用域的会话标识。对每一个作用域来说标识是不一样的。例如,对于session,将获得session标识。
String getConversationId()
8.2 使用自定义作用域
让Spring容器装配你的作用域,把一个新的Scope 注册到Spring 容器中的核心方法定义在ConfigurableBeanFactory接口中
void registerScope(String scopeName, Scope scope);
registerScope(..) 方法的第一个参数是一个作用域的唯一名称,例如,Spring 容器中的’singleton’和’prototype’。registerScope(..) 方法的第二个参数是你要注册和使用的自定义Scope的实例。
例如:
Scope customScope = new ThreadScope();beanFactory.registerScope("thread", scope);
使用作用域:
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer"> <property name="scopes"> <map> <entry key="thread"> <bean class="com.foo.ThreadScope"/> </entry> </map> </property> </bean> <bean id="bar" class="x.y.Bar" scope="thread"> <property name="name" value="Rick"/> <aop:scoped-proxy/> </bean> <bean id="foo" class="x.y.Foo"> <property name="bar" ref="bar"/> </bean>
部分摘自官方文档。
未完待续。。。
- IOC、Spring的IOC
- Spring IoC
- [Spring]IoC
- Spring IOC
- Spring IOC
- spring IOC
- Spring IOC
- Spring IOC
- Spring Ioc
- Spring IoC
- spring ioc
- Spring IOC
- spring IOC
- Spring Ioc
- Spring IoC
- Spring IOC
- Spring IOC
- Spring IoC
- 第一个Kotlin程序
- SpringMVC--JSON数据
- 2016 第七届 蓝桥杯 国赛 路径之谜
- 2016 第七届 蓝桥杯 国赛 碱基
- 系统研发随记
- Spring--IOC
- 2016 第七届 蓝桥杯 国赛 机器人塔
- 9. Palindrome Number
- 用好你的Control键(针对类Unix系统用户)
- 【python开发】利用PIP3的时候出现的问题Fatal error in launcher: Unable to create process using '"'
- Python学习笔记(三)
- CompletionService
- 找出不在预定数组中的自然数
- Devops学习实践(二) Jenkins安装、配置、任务构建