您的位置:首页 > 其它

IoC: 控制反转

2016-11-23 13:45 302 查看
:将传统的由程序代码直接操控对象的调用权交给容器.通过容器控制对象的装配及生命周期管理.

(一下这两段话摘自http://blog.csdn.net/m13666368773/article/details/7802126)

IOC中最基本的技术就是“反射(Reflection)”编程,目前.Net C#、Java和PHP5等语言均支持,其中PHP5的技术书籍中,有时候也被翻译成“映射”。有关反射的概念和用法,大家应该都很清楚,通俗来讲就是根据给出的类名(字符串方式)来动态地生成对象。这种编程方式可以让对象在生成时才决定到底是哪一种对象。反射的应用是很广泛的,很多的成熟的框架,比如象Java中的hibernate、Spring框架,.Net中 NHibernate、Spring.NET框架都是把“反射”做为最基本的技术手段。

我们可以把IOC容器的工作模式看做是工厂模式的升华,可以把IOC容器看作是一个工厂,这个工厂里要生产的对象都在配置文件中给出定义,然后利用编程语言的的反射编程,根据配置文件中给出的类名生成相应的对象。从实现来看,IOC是把以前在工厂方法里写死的对象生成代码,改变为由配置文件来定义,也就是把工厂和对象生成这两者独立分隔开来,目的就是提高灵活性和可维护性。

控制反转的两种实现方式:

1.依赖查找(DL)

2.依赖注入(DI): 程序在运行时,若需要调用另一个对象协助,无需在代码中创建而是依赖外部容器,由容器创建后传递给程序.

依赖注入是最优秀的解耦方式,依赖注入让Spring的bean 之间以配置文件方式组织在一起而不是硬编码的方式.

控制反转Demo1:
/*dao层接口*/
public interface IStudentDao {
public void selectStudent(int cid);
}
/*dao层实现类*/
public class StudentDaoImpl implements IStudentDao {
public StudentDaoImpl() {
super();
System.out.println("构造函数执行!");
}
@Override
public void selectStudent(int cid) {
System.out.println("查找学生"+cid);
}
/*Sping配置文件中注册实现类bean*/
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- bean definitions here -->
<bean id="sdImpl" class="com.xiehe.dao.StudentDaoImpl"/>
</beans>
/*测试类中*/
public class MyTest {
@Test
public void test01(){
//1.获取容器
ApplicationContext context = new ClassPathXmlApplicationContext("applicationSpring.xml");
//2.从容器中获取对象
IStudentDao sdImpl = (IStudentDao) context.getBean("sdImpl");
sdImpl.selectStudent(1);
}
:结果截图

本例中可以明显看出,在测试类中获取StudentDaoImpl 是通过容器(调用了构造)而不是依赖于StudentDaoImpl


ApplicationContext 用于加载Spring 配置文件,在程序中充当容器.其实现类有两



a)基于xml的注入:

Bean的初始化由容器完成称为注入.根据注入方式不同分为 设值注入 和 构造注入

1)设值注入 : 通过setter 方法传入被调用者的实例中

2)构造注入 : 调用构造函数完成注入

/*实体类:schol*/
public class School {
private String name;
private String addr;
public School(String name, String addr) {
super();
this.name = name;
this.addr = addr;
}
public School() {
super();
}
Getter/setter
}
/*实体类:Student*/
public class Student {
private String name;
private int age;
private School mySchool;
public Student() {
super();
}
public Student(String name, int age, School mySchool) {
super();
this.name = name;
this.age = age;
this.mySchool = mySchool;
}
Getter/setter
}
/*spring配置文件*/
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- bean definitions here -->
<!-- 设值注入 -->
<bean id="mySchool" class="com.xiehe.dao.School">
<property name="name" value="北京大学"></property>
<property name="addr" value="海淀区"></property>
</bean>
<!-- 设值注入 -->
<bean id="sdImpl" class="com.xiehe.dao.Student" >
<property name="name" value="张赛"/>
<property name="age" value="58"/>
<!-- 域类型注入方式1:-- >
<!-- <property name="mySchool" ref="mySchool"/> -->
<!-- 域类型注入方式2:-- >
<property name="mySchool">
<ref bean="mySchool"/>
</property>
</bean>
<!-- 构造注入 -->
<bean id="sdImpl2" class="com.xiehe.dao.Student">
<constructor-arg name="name" value="张赛"/>
<constructor-arg name="age" value="58"/>
<constructor-arg name="mySchool" ref="mySchool"/>
</bean>
</beans>
/*测试类*/
public class MyTest {
@Test
public void test01(){
//1.获取容器
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationSpring.xml");
//2.从容器中获取对象(设值注入)
Student dao = (Student) context.getBean("sdImpl");
System.out.println(dao);
}
@Test
public void test02(){
//1.获取容器
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationSpring.xml");
//2.从容器中获取对象(构造注入)
Student dao = (Student) context.getBean("sdImpl2");
System.out.println(dao);
}
}


Test01 结果截图:
Test02 结果截图:



b)基于注解的注入:

在Spring 配置文件中添加组件扫描器:

<context:component-scan base-package="com.xiehe.dao"/>

在xml配置了这个标签后,spring可以自动去扫描base-pack下面或者子包下面的Java文件,如果扫描到有@Component (普通bean)@Controller(控制器)@Service(服务器)等这些注解的类,则把这些类注册为bean.

/*注解式注入 */
@Component("school1")
public class School {
@Value("清华大学")
private String name;
@Value("海淀区")
private String addr;
}
/*注解式注入*/
@Component(value="stu1")
public class Student {
@Value("张嘴")
private String name;
@Value("44")
private int age;
//默认 byType
@Autowired
private School mySchool;
}
/*spring 配置文件*/
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- bean definitions here -->
<!-- 配置组件扫描器 -->
<context:component-scan base-package="com.xiehe.dao"/>
</beans>
/*测试类*/
public class MyTest {
@Test
public void test01(){
//1.获取容器
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("com/xiehe/dao/applicationSpring.xml");
//2.从容器中获取对象
Student dao = (Student) context.getBean("stu1");
System.out.println(dao);
}
}


运行截图:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: