Spring_01_IoC初级总结

1.IoC简介 (转载)

(原文:http://jinnianshilongnian.iteye.com/blog/1413846)  via:@jinnianshilongnian

1.1、IoC是什么


  Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。如何理解好Ioc呢?理解好Ioc的关键是要明确“谁控制谁,控制什么,为何是反转(有反转就应该有正转了),哪些方面反转了”,那我们来深入分析一下:

  ●谁控制谁,控制什么:传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对 象的创建;谁控制谁?当然是IoC 容器控制了对象;控制什么?那就是主要控制了外部资源获取(不只是对象包括比如文件等)。

  ●为何是反转,哪些方面反转了:有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象;为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。

1.2、IoC能做什么

  IoC 不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合、更优良的程序。传统应用程序都是由我们在类内部主动创建依赖对象,从而导致类与类之间高耦合,难于测试;有了IoC容器后,把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是 松散耦合,这样也方便测试,利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。

其实IoC对编程带来的最大改变不是从代码上,而是从思想上,发生了“主从换位”的变化。应用程序原本是老大,要获取什么资源都是主动出击,但是在IoC/DI思想中,应用程序就变成被动的了,被动的等待IoC容器来创建并注入它所需要的资源了。

IoC很好的体现了面向对象设计法则之一—— 好莱坞法则:“别找我们,我们找你”;即由IoC容器帮对象找相应的依赖对象并注入,而不是由对象主动去找。

1.3、IoC和DI

  DI—Dependency Injection,即“依赖注入”:组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。

  理解DI的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么”,那我们来深入分析一下:

  ●谁依赖于谁:当然是应用程序依赖于IoC容器;

  ●为什么需要依赖:应用程序需要IoC容器来提供对象需要的外部资源;

  ●谁注入谁:很明显是IoC容器注入应用程序某个对象,应用程序依赖的对象;

  ●注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)。

  IoC和DI由什么关系呢?其实它们是同一个概念的不同角度描述,由于控制反转概念比较含糊(可能只是理解为容器控制对象这一个层面,很难让人想到谁来维护对象关系),所以2004年大师级人物Martin Fowler又给出了一个新的名字:“依赖注入”,相对IoC 而言,“依赖注入”明确描述了“被注入对象依赖IoC容器配置依赖对象”。

2、代码实现(原创)

2.1准备工作

2.1.1jar包与项目目录结构

spring原项目下

spring\ 1.aopalliance-1.0.jar 2.aopalliance-alpha1.jar 3.aspectjrt.jar aspectjweaver.jar 4.commons-logging.jar

Spring\spring-framework-3.0.0.RELEASE\dist里的所有jar

2.1.2vo包,dao包,service包代码

public calss student{//vo
    private String name;
    private Integer age;
    /** getter and setter */
}
public interface IStudentDao {//dao
	public void add(Student student);
}
public interface IStudentDaoByMybatis {
	public void add(Student student);
}
public class StudentDaoImpl implements IStudentDao{//dao.impl
	@Override
	public void add(Student student) {
		System.out.println(student.getName()+"成功通过JDBC添加");
	}
}
public class StudentDaoByMybatisImpl implements IStudentDaoByMybatis{//dao.impl
	@Override
	public void add(Student student) {
		System.out.println(student.getName()+"成功通过Mybatis添加");
	}
}
public interface IStudentService {//service包
	public void add(Student student);
}

2.1.3 spring.xml

<?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:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/aop 
           http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
	<!-- xmlns:aop="http://www.springframework.org/schema/aop"  声明要用aop的标签
	 xsi:schemaLocation= aop的标签地址
	 "http://www.springframework.org/schema/aop 
     http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"  
	 -->
</beans>

2.2注入IoC(通过spring.xml)

  2.2.1重点标签与属性解释


 (一)bean的生命周期,两个常用属性:lazy-init和scope
  1.懒加载属性lazy-init,每次启动IoC时,通常需要启动的大的数据库启动很耗时(比如数据库连接池),用再加载,通过这种方式提高速度,true是开启,false是关闭,default是默认,beans的全局没有设置时default默认是false关闭 
  2.scope,设置模式,singleton是单例,prototype是多例,每次用到IoC容器里的bean时,单例用的是一个,多例可用多个,singleton是单例的,整个项目共用一个对象,应用很多(锤子);prototype是多例的,项目会用多个对象,多用于Controller注入(钉子)
  3.init-method,bean初始化时调用的方法,参数里写bean对应的类里的方法名,多用于初始化字典值
4.destroy-method,bean销毁时用的方法 ,参数里写bean对应的类里的方法名,多用于数据库连接的关流(现在开始可以自动关了).注意:这个bean的scope用prototype的时候(也就是多例时),不调用该bean的destroy-method

(二)依赖注入, autowire自动装载可省略以下<property>,通过反射的方式,获取这个bean对应的类里的各种信息
1.byName通过set方法的名称注入(装载)(原理是反射),根据ServiceImpl里得到的set方法的名称
2.byType通过实现的接口类型注入(装载), 比如上面这个org.jsoft.dao.IStudentDao
3.no是不自动注入(装载)

<?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-3.0.xsd">
           <!-- default-autowire-candidates=""如果写在beans标签里的属性为默认的全局aotowire -->
           <!-- default-lazy-init="" 如果写在beans标签里的属性为默认的全局aotowire -->
<!-- 名称必须规范,后缀的Dao必须和该类后缀一样(包括大小写) -->
  
  <bean id="studentDao" class="org.jsoft.dao.impl.StudentDaoImpl">
  </bean>
  
  <bean id="studentDaoByMybatis" lazy-init="true"  class="org.jsoft.dao.impl.StudentDaoByMybatisImpl">
  </bean>
  
  <bean id="studentService" class="org.jsoft.service.impl.StudentServiceImpl" scope="singleton" init-method="a" destroy-method="b" autowire="byType">
  <!-- 包含了另一个bean“studentDAO” 
  	<property name="studentDao">
  		<ref bean="studentDao"/>
  	</property> -->
  </bean>
  
  <!-- more bean definitions go here -->

</beans>

2.2.2 java代码

StudentServiceImpl里的代码

public class StudentServiceImpl implements IStudentService{
	
	private IStudentDao studentDao;
	private IStudentDaoByMybatis studentDaoByMybatis;
	
//	public IStudentDao getStudentDaoByMybatis() {//对比ByName用法时用
//		return studentDao;
//	}
//	public void setStudentDaoByMybatis(IStudentDao studentDaoByMybatis) {
//		this.studentDao = studentDaoByMybatis;
//	}
	//需要写getset方法
	public IStudentDaoByMybatis getStudentDaoByMybatis() {
		return studentDaoByMybatis;
	}
	public void setStudentDaoByMybatis(IStudentDaoByMybatis studentDaoByMybatis) {
		this.studentDaoByMybatis = studentDaoByMybatis;
	}
	public IStudentDao getStudentDao() {
		return studentDao;
	}
	public void setStudentDao(IStudentDao studentDao) {
		this.studentDao = studentDao;
	}

//	@Override
//	public void add(Student student) {
//		studentDao.add(student);
//		//System.out.println(student.getName());
//		
//	}
	
	@Override
	public void add(Student student) {
		studentDaoByMybatis.add(student);
		//System.out.println(student.getName());
		
	}
//	@Override
//	public void add(Student student) {
//		studentDaoByMybatis.add(student);
//		//System.out.println(student.getName());
//		
//	}
	public void a(){//bean初始化时调用
		System.out.println("StudentServiceImpl.a(),初始化");
	}
	
	public void b(){//bean销毁时调用
		System.out.println("StudentServiceImpl.b(),销毁");
	}
}
//测试用的Main方法
//ApplicationContext 是接口,下面的ClassPathXmlApplicationContext也可以用,后者可以用.close()方法
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"spring/spring.xml"});
Student s = new Student();
s.setName("Joy");
IStudentService studentService = context.getBean("studentService",IStudentService.class);
IStudentService studentService2 = context.getBean("studentService",IStudentService.class);
		
//scope的属性
//singleton是单例,只用一个,studentService和studentService2被赋予的是一个bean对象,内存地址一样,所以会返回true;
//而prototype是多例,会给studentService赋予来自一个bean的不同的对象
System.out.println(studentService == studentService2);//对比对象在内存里的地址,一样就返回true,
		
studentService.add(s);
context.close();

2.3注入IoC(通过注解)

2.3.1spring.xml的配置

注意:

1.beans的xmlns:context="http://www.springframework.org/schema/context"这句话一定要有,声明要用注解

2.beans的xsi:schemaLocation属性里一定要有"http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-3.0.xsd "注解的地址

3.下面的context标签,写上,注解才会生效

<?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-3.0.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-3.0.xsd">
           <!-- -->

 <context:annotation-config/>
 <!-- 扫描组件 -->
 <context:component-scan base-package="org.jsoft"/>
 
</beans>

2.3.2注解

1@Component("这个bean的id")都可以用,写在声明类名的上边

2.@Service("这个bean的id")用在serviceimpl里声明类名的上边

3@Repository("这个bean的id")dao持久层里声明类名的上边

4.@Autowired 写在serviceImpl里的声明过的dao的set方法上   @Qualifier("用到的dao层的bean的id")写在这个方法声明参量的括号里参量类型的前边           *不常用*

5.@Controller 用在C层里

6.@Resource("用到的bean的id"),声明的Service或者Dao上面,里面写对应的bean的id

2.3.3Demo(没有@Controller)

1.dao层,只需要写在实现类里,

@Repository("studentDaoImpl")//注入bean
public class StudentDaoImpl implements IStudentDao{//实现了IStudentDao
	@Override
	public void add(Student student) {
		System.out.println(student.getName()+"成功通过JDBC添加");
	}
}
@Repository("studentDaoByHibernateImpl")
public class StudentDaoByHibernateImpl implements IStudentDao{//也实现了IStudentDao
	@Override
	public void add(Student student) {
		System.out.println(student.getName()+"成功通过Hibernate添加");
	}
}
@Repository("studentDaoByMybatisImpl")
public class StudentDaoByMybatisImpl implements IStudentDaoByMybatis{//实现了另外一个
	@Override
	public void addByMybatis(Student student) {
		System.out.println(student.getName()+"成功通过Mybatis添加");
	}
}

2.service层,同样地只需要写在实现类里

@Service(value="studentService")
public class StudentServiceImpl implements IStudentService{
	//@Resource(name="studentDaoImpl")
	private IStudentDao studentDao;
	private IStudentDao studentDaoByHibernate;
	
	@Resource(name="studentDaoByMybatisImpl")
	private IStudentDaoByMybatis studentDaoMyBatis;

	//@Resource会通过暴力反射找到的bean名字,没有用getset方法
//	public IStudentDao getStudentDao() {
//		return studentDao;
//	}
//	public void setStudentDao(IStudentDao studentDao) {
//		this.studentDao = studentDao;
//	}

//	@Override
//	public void add(Student student) {
//		studentDao.add(student);
//		
//	}
	@Override
	public void add(Student student) {
		studentDaoByHibernate.add(student);
		
	}

	@Override
	public void addByMybatis(Student student) {
		studentDaoMyBatis.addByMybatis(student);
		
	}

	public IStudentDao getStudentDao() {
		return studentDao;
	}
	//也可以自动装载,无需写@Resource

	public void setStudentDao(IStudentDao studentDao) {
		this.studentDao = studentDao;
	}

	public IStudentDao getStudentDaoByHibernate() {
		return studentDaoByHibernate;
	}
	@Autowired
	public void setStudentDaoByHibernate(@Qualifier("studentDaoByHibernateImpl")IStudentDao studentDaoByHibernate) {
		this.studentDaoByHibernate = studentDaoByHibernate;
	}

	public IStudentDaoByMybatis getStudentDaoMyBatis() {
		return studentDaoMyBatis;
	}

	public void setStudentDaoMyBatis(IStudentDaoByMybatis studentDaoMyBatis) {
		this.studentDaoMyBatis = studentDaoMyBatis;
	}

3.main方法的测试与结果

ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"spring/spring.xml"});
Student s = new Student();
s.setName("Joy");
IStudentService studentService = context.getBean("studentService",IStudentService.class);
studentService.add(s);
context.close();

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值