`

spring01:控制反转(IOC容器)引出工厂模式(bean工厂)、代理模式(代理对象与目标对象)

 
阅读更多

第一:概念
1.EJB:企业级javabean
spring框架主要讲两个东西。一个是控制反转(一种思想)和依赖注入(对思想的实施),第二个是面向切面编程。
2.
(1).控制反转与依赖注入(IoC与DI).ref指明依赖关系
控制反转IoC:Inversion of Control
依赖注入DI:Dependency Injection
hibernate框架解决了对象与对象之间的关联关系,控制反转是为了解决对象与对象之间的依赖关系。
依赖注入是控制反转的具体实现
(2)面向切面编程(AOP)
AOP:Aspect Orinented Programming,Aspect是切面,Orinented是面向的意思,Programming是变成。
AOP编程是面向对象编程的一种应用。spring框架利用了面向切面编程
2.Spring框架的整合:
(1).与JDBC以及hibernate的整合
(2).与struts2的整合
3.依赖关系和依赖解耦
1.什么是类的依赖关系?
答:如果在一个类的业务方法中使用另外一个类的业务方法来完成自己的功能,那么这两个类就构成了依赖关系。
自己对依赖注入的理解:
---1.仅在调用类的方法中依赖:我们平时写的一个方法调用其他类中的一个方法,这就是一种依赖关系。
---2.属性依赖一个类(类里有方法)把另一个当做自己的引用类型的属性,然后创建setget方法,然后在本类的方法中调用该引用类型的属性来调用这个属性里面的方法。这也是一种依赖关系
其中这里的set方法就是二者的依赖关系的体现。这也是spring框架要研究的,这个就做属性依赖,属性依赖的目的是被依赖对象的声明周期与调用对象的声明周期相同
4.属性依赖会产生依赖耦合的问题
依赖耦合的特点是:调用类的依赖属性的类型是具体的实现类,即调用类依赖具体的是实现类
依赖耦合的问题是:当针对调用类实施功能扩展的时候,需要大量修改代码(也就是由于要扩展调用类中的方法的功能,就导致被调用类里面的方法需要大量修改)
5.依赖解耦用来解决依赖耦合的问题:
 ---问:什么是依赖解耦:封装调用类的时候,它的依赖属性的类型是接口而不是具体的实现类,例如User u=new UserImpl()
 ---问:以阿里解耦的目的是什么:当调用类需要增加新的功能的时候,调用类的代码不需要变更或者变更量很小
 ---问:如何实施依赖解耦:首先被调用类需要实现某个接口,第二调用了依赖的是被调用类的接口,而不是具体的类
/**原始做法:
public static void main(String[] args) {
  IHelloBean hello;//接口类型的变量
  
  //①创建所依赖的对象
  EnHelloBean enHello=new EnHelloBean();
  ZhHelloBean zhHello=new ZhHelloBean();
  //②创建调用对象
  UseBean useBean=new UseBean();
  //③设置调用对象与依赖对象的依赖关系;
  hello=enHello;//接口变量引用所依赖的对象
//  hello=zhHello;
  useBean.setHello(hello);
  
     //执行调用对象的业务方法;
  useBean.show();
 }
**/
/**反转做法:
第一步创建工厂:
public class MyBeanFactory {
public static Object getUseBean(){
  //①创建调用类所依赖的对象;
  EnHelloBean enHello=new EnHelloBean();
  ZhHelloBean zhHello=new ZhHelloBean();
  //②创建调用类的对象
  UseBean useBean=new UseBean();  
  //使用接口变量引用所依赖对象
  IHelloBean hello=enHello;
  //使用接口变量引用所依赖对象
                //IHelloBean hello=zhHello; 
  //③设置对象之间的依赖关系
  useBean.setHello(hello);
  return useBean;
 }}

   第二步:通过工厂类所要目标对象,并运行
 public static void main(String[] args) {
  UseBean useBean=(UseBean)MyBeanFactory.getUseBean();
  useBean.show();
 }
**/
/**IoC容器的做法:
第一步:编写配置文件,用配置文件配置对象并指明类与类之间的依赖关系(有创建对象的权利,依赖关系的权利)
<bean id="hdisk"
       class="ioc.exer.HardDisk"/>
 <bean id="udisk"
       class="ioc.exer.UniDisk"/>
 <bean id="computer"
       class="ioc.exer.Computer">
  <property name="disk" ref="udisk" />
 </bean>
第二步:获得配置文件找到目标对象,并运行
public static void main(String[] args) {
  //创建IoC容器
  ApplicationContext ac=
   new ClassPathXmlApplicationContext(CONFIG);
  //通过IoC容器对象,获得我们需要的bean对象;这里貌似只获得了一个对象
  Computer computer=(Computer)ac.getBean("computer");
                //这里写的是依赖关系,因此可以根据上面的对象获得其他对象。
  computer.saveData();
 }
**/
6.控制权有两个:一个是创建对象的控制权,一个是设置对象依赖关系的权利
7.控制反转:将控制权交给自定义的第三方工厂类MyBeabFactory(工厂类是通过静态方法封装的是创建对象的控制权,把创建对象的权利交给了工厂)
工厂类里面写个方法能够返回调用类的对象,工厂对象是代理对象,目标对象是被代理对象
8:什么是反转:
 --1.传统方式:调用类掌握控制权,即在调用类的执行方法中进行创建所依赖的对象、创建调用对象、设置调用对象和所依赖对象的依赖关系(也就是调用类调用被调用类)
 --2.反转方式:调用类将控制权转移给第三方工厂类,调用类在执行方法中向工厂类所要对象并执行相应的业务方法。
9.Spring框架的IoC容器:(其中的容器只的是工厂,bean工厂)
 --1.spring框架的Ioc容器实际上是一个实现了BeanFactory接口的工厂类,例如XmlBeanFactory。(BeanFactory是个接口类,他下面有很多实现类)
 --2.BeanFactory的功能:
    ---1.通过Resource对象,加载对象的配置信息(对象的配置信息通长采用xml,标准名称是applicationContext.xml也可以采用自定义名称,根据文件放在类的路径下,即src下的相应包中
    ---2.根据xml文件的配置,创建对象和设置对象的依赖关系
10.在applicationContext.xml中的beans标签中有两个名称空间,第一个xmlns是默认的名称空间,第二个是www协会的标准名称空间
里面的bean标签其实就是在程序中创建了class类的对象。property标签是属性的意思,也就是写的是依赖对象,里面的name属性写的是当前类中的属性,ref表示当前属性依赖于哪个类,这里写的内容通常是上面bean的id属性。
注意:spring框架中的applicationContext.xml配置文件(工厂)代替了我们以前用的以前自定义的工厂类,因此配置文件的存在表明了现在是控制反转,而配置文件中的bean标签里面的内容体现了依赖注入。
bean对象其实就是java代码中的实体类对象,当我们加载配置文件的时候,就会同时加载配置文件中的bean对象,因此会执行java代码中的实体类的构造方法(表示创建了实体类对象)。
11注意:SpringIoC容器是通过反射创建对象的(因为我们在程序中没有创建对象,而是配置文件帮我们创建了文件,每个bean都是每个对象,bean标签当中的class属性就表示了反射创建的方法。在java程序中可以用BeanFactory类的getBean方法获得该对象)
----------------------------------
一、Spring框架中IoC容器的常见类型(下面三种接口都表示ioc容器,也就是说都表示applicationContext.xml配置文件)
1.BeanFactory接口,实现类是XmlBeanFactory,(最核心的)
  (1)特点: 
          ①提供了IoC容器的核心功能,通常被称为"Bean工厂";
          ②创建容器时,需要Resource(资源)对象;
  (2)功能:
    ①实例化对象及设置对象的依赖关系;
    ②管理对象的生命周期并负责提供对象;
2.ApplicationContext接口(标准接口),(是beanfactory的子接口,因此扩展了beanfactory的功能,因此不需要资源文件)
    实现类是ClassPathXmlApplicationContext (*)
  (1)特点:
          ①继承于BeanFactory接口,因而功能更加完善,
             是实际应用中的标准容器,通常被称为"应用上下文";
          ②不需要资源对象,直接针对XML配置文件的路径创建容器对象;
  (2)功能:
          ①拥有BeanFactory的所有功能;
          ②支持国际化和事件发布等先进功能
3.WebApplicationContext接口(专用接口),实现类是XmlWebApplicationContext
  (1)特点:
          ①ApplicationContext接口的子接口,专用于Web应用中的IoC容器,
          ②通过Web容器监听器(ContextLoaderListener)加载配置文件
             并创建Spring容器;
  (2)功能:
          整合时提供组件,有两种情况:
          ①为控制器提供业务组件;
          ②负责提供所有组件(包括控制器);
         
二、利用ApplicationContext容器管理对象         
1.bean对象的创建时机:
  (1)默认情况下,容器创建的同时bean也被创建;
  (2)设置lazy-init属性为true
          当向容器所要对象时,容器才创建对象;(延时初始化,就是在我们服务器启动的时候会加载配置文件(因为在src下),默认情况下此时就加载了配置文件中的每个bean对象,延时初始化就表示暂时不创建这个bean对象,等我们调用他的时候在创建,用getBean方法调用)
2.bean对象的创建模式,即设置scope属性的值:
  (1)singleton(单例对象)
          容器只创建一个对象    
          当向容器所要对象时,IoC容器每次提供相同的对象
  (2)prototype(原型对象):
          容器创建多个对象(多例对象)    
          当向容器所要对象时,IoC容器每次提供不同的对象
  (3)针对于Web应用,IoC容器可以将所创建的对象存入
     HttpServletRequest对象和HttpSession对象中:
  ①request
  ②session
3.bean对象的再次初始化:
  (1)执行时机:在构造器之后立即执行的方法;
  (2)配置属性:init-method
4.bean对象销毁之前执行的方法:
  (1)执行时机:关闭容器前,容器首先要销毁容器中所创建的对象
  (2)配置属性:destroy-method
 
第二:代码(原始做法)
1.中文方法(被调用类)
package dependent1.property.couple;
public class ZhHelloBean {
 //该对象提供一个显示中文问候语的方法
 public void sayHello(){
  System.out.println("世界,你好!");
 }
}
2.英文方法(被调用类)
package dependent1.property.couple;
public class EnHelloBean {
 
 public void sayHello(){
  System.out.println("Hello World!");
 }
}
3.user方法(调用者)
package dependent1.property.couple;
import dependent1.property.EnHelloBean;
/**
 * 【说明】:
 * 扩充UseBean的功能,导致UseBean程序发生大量修改
 * 【原因】:
 * UseBean依赖于具体的实现类,
 * 即UseBean的依赖属性的类型是一个具体的实现类。
 */
public class UseBean {
// private EnHelloBean ehello;
 //属性变更
 private ZhHelloBean zhello;
 
// public EnHelloBean getHello() {
//  return ehello;
// }
//
// public void setHello(EnHelloBean ehello) {
//  this.ehello = ehello;
// }
 
 //属性方法变更
 public ZhHelloBean getHello() {
  return zhello;
 }
    //属性方法变更
 public void setHello(ZhHelloBean zhello) {
  this.zhello = zhello;
 }
 
// public void show(){
//  System.out.println("调用"+
//            ehello.getClass().getName()+
//            "对象的sayHello方法:");
//  ehello.sayHello();
// }
 
 /* 业务方法变更 */
 public void show(){
  System.out.println("调用"+
            zhello.getClass().getName()+
            "对象的sayHello方法:");
  zhello.sayHello();
 }
 
}
 
4.main方法实现调用
package dependent1.property.couple;
import dependent1.property.EnHelloBean;
public class UseBeanTest {
 /**
  * UseBean类的执行方法:
  * (1)创建对象和设置依赖关系的控制权;
  * (2)执行目标对象的业务方法;
  */
 public static void main(String[] args) {
  //①创建依赖对象
  EnHelloBean enHello=new EnHelloBean();
  ZhHelloBean zhHello=new ZhHelloBean();
  //②创建目标对象
  UseBean useBean=new UseBean();
  //③设置目标对象与依赖对象的依赖关系;
//  useBean.setHello(enHello);
  useBean.setHello(zhHello);
  
  ////4.执行useBean对象的业务方法////////////
  useBean.show();
 }
}
 
第三:反转的做法(使用了接口,并产生了第三方对象作为工厂类)
1.中文类
package dependent2.demo1;
/**
 * 要求所依赖的类实现接口
 */
public class ZhHelloBean implements IHelloBean {
 @Override
 public void sayHello() {
  System.out.println("世界 你好!");
 }
}
2.英文类
package dependent2.demo1;
/**
 * 要求所依赖的类实现接口
 */
public class EnHelloBean implements IHelloBean {
 @Override
 public void sayHello() {
  System.out.println("Hello World!");
 }
}
3.接口类
package dependent2.demo1;
/**
 * 所依赖的对象需要实现的接口
 */
public interface IHelloBean {
 public void sayHello();
}
4,用户类
package dependent2.demo1;
/**
 * UseBean依赖接口:
 * UseBean对象依赖于接口类型的对象,而不是子类类型的对象。
 */
public class UseBean {
 private IHelloBean hello;
 public IHelloBean getHello() {
  return hello;
 }
 public void setHello(IHelloBean hello) {
  this.hello = hello;
 }
 
 public void show(){
  System.out.println("调用"+
    hello.getClass().getName()+
    "对象的sayHello方法:");
  hello.sayHello();
 }
}
5.工厂类
package dependent2.demo1;
/**
 * 【说明】:
 *   将控制权转移给第三方工厂类
 */
public class MyBeanFactory {
 public static Object getUseBean(){
  //①创建调用类所依赖的对象;
  EnHelloBean enHello=new EnHelloBean();
  ZhHelloBean zhHello=new ZhHelloBean();
  //②创建调用类的对象
  UseBean useBean=new UseBean();
  
  //使用接口变量引用所依赖对象
  IHelloBean hello=enHello;
  //使用接口变量引用所依赖对象
//  IHelloBean hello=zhHello;
  
  //③设置对象之间的依赖关系
  useBean.setHello(hello);
  
  return useBean;
 }
}
6.main方法
package dependent2.demo1;
public class UseBeanTest {
 /**
  * 【说明】:
  *   通过工厂类所要目标对象
  */
 public static void main(String[] args) {
  UseBean useBean=(UseBean)MyBeanFactory.getUseBean();
  useBean.show();
 }
}
 
第四:IoC容器
1.方法1
package ioc.exer;
public class UniDisk implements IDisk {
 @Override
 public void writeDataToDisk() {
  writeDataToUniDisk();
 }
 private void writeDataToUniDisk(){
  System.out.println("正在写数据到移动硬盘上...");
 }
}
2.方法2
package ioc.exer;
public class HardDisk implements IDisk {
 @Override
 public void writeDataToDisk() {
  writeDataToHardDisk();
 }
 private void writeDataToHardDisk(){
  System.out.println("正在写数据到硬盘上...");
 }
}
 
3.接口
package ioc.exer;
public interface IDisk {
 public void writeDataToDisk();
}
4.业务方法
package ioc.exer;
public class Computer {
 private IDisk disk;
 
 public void setDisk(IDisk disk){
  this.disk=disk;
 }
 //业务方法:存储数据
 public void saveData(){
  disk.writeDataToDisk();
 }
}
5.main方法
package ioc.exer;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestExer2 {
 private static final String CONFIG=
   "ioc/exer/applicationContext.xml";
 public static void main(String[] args) {
  //创建IoC容器
  ApplicationContext ac=
   new ClassPathXmlApplicationContext(CONFIG);
  //通过IoC容器对象,获得我们需要的bean对象;
  Computer computer=(Computer)ac.getBean("computer");
  computer.saveData();
 }
}
6.application的配置文件(配置文件中的对象,在getbean的时候才会产生)
<?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-2.5.xsd"
>
 <bean id="hdisk"
       class="ioc.exer.HardDisk"/>
 <bean id="udisk"
       class="ioc.exer.UniDisk"/>
 <bean id="computer"
       class="ioc.exer.Computer">
  <property name="disk" ref="udisk" />
 </bean>
</beans>
 
 
 
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics