案例学编程系列:案例认识 Spring IOC

本文spring libs 地址:https://github.com/yizhiamumu/springlibs Spring 能帮我们做什么 ①.Spring 能帮我们根据配置文件创建及组装对象之间的依赖关系。 ②.Spring 面向切面编程能帮助我们无耦合的实现日志记录,性能统计,安全控制。 ③.Spring 能非常简单的帮我们管理数据库事务。 ④.Spring 还提供了与第三方数据访问框架(如Hibernate、JPA)无缝集成,而且自己也提供了一套JDBC访问模板来方便数据库访问。 ⑤.Spring 还提供与第三方Web(如Struts1/2、JSF)框架无缝集成,而且自己也提供了一套Spring MVC框架,来方便web层搭建。 ⑥.Spring 能方便的与Java EE(如Java Mail、任务调度)整合,与更多技术整合(比如缓存框架)。 Spring 的优势 低侵入 / 低耦合 (降低组件之间的耦合度,实现软件各层之间的解耦) 声明式事务管理(基于切面和惯例) 方便集成其他框架(如MyBatis、Hibernate) 降低 Java 开发难度 Spring 框架中包括了 J2EE 三层的每一层的解决方案(一站式) Spring IoC 是什么 IoC:Inverse of Control(控制反转) 读作“反转控制”更好理解。将原本在程序中手动创建对象的控制权,交由Spring框架来管理。 正控:若要使用某个对象,需要自己去负责对象的创建 反控:若要使用某个对象,只需要从 Spring 容器中获取需要使用的对象,不关心对象的创建过程,也就是把创建对象的控制权反转给了Spring框架 在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。 ●谁控制谁? 我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对象的创建; ●控制什么? 主要控制了外部资源获取。 ●为何是反转? 有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象; 为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转; ●反转了什么? 依赖对象的获取被反转了。 案例1:认识springIOC 正控 1.创建员工类 Employee.java 复制代码 public class Employee { /** 系统id */ private int id; /** 员工编号 */ private String employeeNo; /** 员工姓名 */ private String employeeName; /** 员工性别 */ private String sex; /** 出生日期 */ private Date birthDay; /** 部门编号 */ private String officeNo; /** 岗位编号 */ private String postNo; /** 入职时间 */ private Date entryTime; /** 特长 */ private String speciality; /** 兴趣爱好 */ private String hobby; /** setter and getter */ } 复制代码 2.创建测试方法,并调用构造函数创建对象。 TestSpringEmp.java 复制代码 public class TestSpringEmp { public static void main(String[] args) { Employee emp = new Employee(); System.out.println(emp); } } 复制代码 springIOC 控制反转 环境搭建: 1.idea 工程添加Spring相关jar包。【libs 上传至git 地址,操作方法见附录】 2.创建配置文件,可以自定义文件名spring.xml。 3.调用API。 程序思路: 1.在spring.xml中配置bean标签,IOC容器通过加载bean标签来创建对象。 2.调用API获取IOC创建的对象。 两种方式 2.1 通过id获取对象 复制代码 //1.加载spring.xml配置文件 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml"); //2.通过id值获取对象 Employee emp = (Employee) applicationContext.getBean("emp"); System.out.println(emp); 复制代码 2.2 通过运行时类获取对象 注意: 当spring.xml中配置两个Employee的bean时程序报错,因为此时两个bean都是由Employee类生成的,IOC容器无法将两个bean都返回。 必须指定一个唯一的bean spring.xml 复制代码 复制代码 TestSpringEmp.java 复制代码      //1.加载spring.xml配置文件 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml"); //2.通过运行时类获取对象 Employee emp = applicationContext.getBean(Employee.class); System.out.println(emp); 复制代码 无参构造代码 spring.xml 复制代码 复制代码 TestSpringEmp.java 复制代码 import com.spring.model.Employee; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestSpringEmp { public static void main(String[] args) { //1.加载spring.xml配置文件 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml"); //2.通过id值获取对象 Employee emp = (Employee) applicationContext.getBean("emp"); System.out.println(emp); } } 复制代码 第一步:加载spring.xml配置文件,生成ApplicationContext对象。 第二步:调用ApplicationContext的getBean方法获取对象,参数为配置文件中的id值。 程序在加载spring.xml时创建stu对象,通过反射机制调用无参构造函数,所有要求交给IOC容器管理的类必须有无参构造函数。 如何赋值呢? 调用无参构造只会创建对象而不会进行赋值,如何赋值呢?只需要在spring.xml中进行相关配置即可。 添加property标签:name对应属性名,value是属性的值。 注:若包含特殊字符,比如name="<一只阿木木>",使用]]>进行配置。 spring.xml 复制代码       ]]> 复制代码 有参构造代码 在实体类中创建有参构造 Employee.java 复制代码 public Employee(int id, String employeeNo, String employeeName) { super(); this.id = id; this.employeeNo = employeeNo; this.employeeName = employeeName; } 复制代码 spring.xml 复制代码 复制代码 除了使用name对应参数外,还可以通过下标index对应。 复制代码 复制代码 进阶1:多个对象级联关系? 创建工作经历类 job.java 复制代码 public class Job { /** 序号 */ private int id; /** 单位名称 */ private String companyName; /** 职位名称 */ private String position; /** 工作薪水 */ private BigDecimal salary; /** setter and getter */ } 复制代码 在员工Employee 类中添加工作经历job 类: Employee.java 复制代码 /** 工作经历类*/ private Job job; /** 系统id */ private int id; /** 员工编号 */ private String employeeNo; /** 员工姓名 */ private String employeeName; 复制代码 spring.xml中配置Job 对象,然后将该对象赋值给emp 对象。 spring.xml 复制代码 ]]> 复制代码 在spring.xml中,通过ref属性将其他bean赋给当前bean对象,这种方式叫做依赖注入(DI),是Spring非常重要的机制,DI是将不同对象进行关联的一种方式,是IOC的具体实现方式,通常DI和IOC是紧密结合在一起的,所以一般说的IOC包括DI。 如果是集合属性如何依赖注入? Job 类中添加List属性。 Job.java 复制代码 /** List属性*/ private List employeeList; 复制代码 spring.xml中配置2个emp对象,1个job对象,并将2个emp对象注入到job对象中。 spring.xml 复制代码 ]]> ]]> 复制代码 集合属性通过list标签和ref标签完成注入。ref的bean属性指向需要注入的bean对象。 IoC和DI 2004年大师级人物Martin Fowler:“依赖注入”明确描述了“被注入对象依赖IoC容器配置依赖对象”。 DI—Dependency Injection,即“依赖注入”:我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。 理解DI的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么”。 谁依赖于谁:当然是应用程序依赖于IoC容器; 为什么需要依赖:应用程序需要IoC容器来提供对象需要的外部资源; 谁注入谁:很明显是IoC容器注入应用程序某个对象,应用程序依赖的对象; 注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)。 IoC和DI 是什么关系呢? 其实它们是同一个概念的不同角度描述。 IoC 是spring的核心,所有的类的创建、销毁都由 spring来控制,也就是说控制对象生存周期的不再是引用它的对象,而是spring。由spring来负责控制对象的生命周期和对象间的关系,这叫控制反转。 Java 1.3之后一个重要特征是反射(reflection),它允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性,spring就是通过反射来实现注入的。IoC的一个重点是在系统运行中,动态的向某个对象提供它所需要的其他对象。这一点是通过DI(Dependency Injection,依赖注入)来实现的。 控制的什么被反转了?就是:获得依赖对象的方式反转了。 案例2:工厂方法 IOC是典型的工厂模式,IOC通过工厂模式创建bean有两种方式: 1.静态工厂方法 2.实例工厂方法 一.静态工厂方法 1.1 创建工作实体类 job.java 复制代码 public class Job { /** 序号 */ private int id; /** 单位名称 */ private String companyName; /** 职位名称 */ private String position; public Job(int id, String companyName, String position) { super (); this.id = id; this.companyName = companyName; this.position = position; } public Job() { super(); } @Override public String toString() { return "Job [id=" + id + ", companyName=" + companyName + ", postion=" + position + " ]"; } } 复制代码 1.2 创建静态工厂类,静态工厂方法。 StaticFactoryJob.java 复制代码 private static Map jobs; static { jobs = new HashMap<>(); jobs.put(1, new Job(1, "猫厂", "p7")); jobs.put(2, new Job(2, "鹅厂","T2")); } public static Job getJob(int id) { return jobs.get(id); } 复制代码 1.3 在spring.xml中配置静态工厂。 spring.xml 复制代码 复制代码 factory-method指向静态方法。 constructor-arg 的value属性为调用静态方法所传的参数。 1.4 在测试类中直接获取job1对象。 TestSpringStatic.java 复制代码 public static void main(String[] args) throws SQLException { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml"); Job job = (Job) applicationContext.getBean("job1"); System.out.println(job); } // 打印:Job [id=1, companyName=猫厂, postion=p7 ] 复制代码 二.实例工厂方法 2.1 创建实例工厂类,工厂方法 。 InstanceFactoryJob.java 复制代码 private Map jobs; public InstanceFactoryJob() { jobs = new HashMap<>(); jobs.put(1, new Job(1, "猫厂", "p7")); jobs.put(2, new Job(2, "鹅厂", "T2")); } public Job getJob(int id) { return jobs.get(id); } 复制代码 2.2 spring.xml 中配置 bean spring.xml 复制代码 复制代码 2.3 在测试类中直接获取car2对象 复制代码 public static void main(String[] args) throws SQLException { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml"); Job job = (Job) applicationContext.getBean("job2"); System.out.println(job); } // 打印: Job [id=2, companyName=鹅厂, postion=T2 ] 复制代码 区别 静态工厂方法的方式创建job对象,不需要实例化工厂对象,因为静态工厂的静态方法,不需要创建对象即可调用。所以spring.xml只需要配置一个Job bean,而不需要配置工厂bean。 实例工厂方法创建job对象,必须先实例化工厂对象,因为调用的是非静态方法,必须通过对象调用,不能直接通过类来调用,所以spring.xml中需要先配置工厂bean,再配置Job bean。 案例3:IOC自动装载(autowire) 自动装载有两种方式: byName:通过属性名自动装载 byType:通过属性对应的数据类型自动装载 3.1 通过属性名自动装载 1 新建BaseEmployee.java 类 复制代码 public class BaseEmployee { /** 系统id */ private int id; /** 员工编号 */ private String employeeNo; /** 员工姓名 */ private String employeeName; /** 工作经历*/ private Job job; /** setter and getter */ @Override public String toString() { return "BaseEmployee [id=" + id + ", employeeNo=" + employeeNo + ", employeeName=" + employeeName + ", job=" + job + "]"; } } 复制代码 2 spring.xml中配置Car bean和Person bean,并通过自动装载进行依赖注入。 spring.xml 复制代码 复制代码 注意:通过property标签手动进行car的注入优先级更高,若两种方式同时配置,以property的配置为准。 3 测试类中获取baseEmployee 对象。 TestSpringBaseEmployee.java 复制代码 public class TestSpringBaseEmployee { public static void main(String[] args) {
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信