Spring-IOC(未完善)

一、Spring 框架概念、模块划分与环境搭建


1.Spring框架概念

  • Spring 是众多开源 java 项目中的一员,基于分层的 javaEE 应用一站式轻量级开源框
    架,主要核心是 Ioc(控制反转/依赖注入) 与 Aop(面向切面)两大技术,实现项目在开发过
    程中的轻松解耦,提高项目的开发效率。
  • 在项目中引入 Spring 立即可以带来下面的好处 降低组件之间的耦合度,实现软件各层
    之间的解耦。可以使用容器提供的众多服务,如:事务管理服务、消息服务等等。当我们
    使用容器管理事务时,开发人员就不再需要手工控制事务.也不需处理复杂的事务传播。 容
    器提供单例模式支持,开发人员不再需要自己编写实现代码。 容器提供了 AOP 技术,利
    用它很容易实现如权限拦截、运行期监控等功能。

1.Spring官网

  • spring.io

2.版本介绍

  • GA:稳定版
  • SNAPSHOT:快照版
  • Pre:预发布
  • Alpha:第一次修正
  • Beta:第二次修正

3.什么叫Spring

  • Spring是一款企业级开发的开源框架
  • Spring提供IOC容器和AOP框架
    • IOC解决了对象的创建以及对象管理,同时解决了对象与对象之间的依赖
    • AOP解决的是一些公关的业务逻辑
  • Spring是一种"粘合剂",采用Spring去集成第三方框架或者组件(MyBatis/Redis客户端/RabbitMQ客户端/Hibernate等等),集成原理还是基于IOC容器

2.Spring组件介绍

在这里插入图片描述

  • 数据访问相关组件(Data Access):Spring JDBC/Spring ORM/Spring OXM
  • Web应用相关组件(Web): Spring Web、Spring MVC(重点)、Spring Websocket…
  • AOP(面向切面编程)、Aspects(切面)
  • 核心容器组件:Beans(Bean相关内容:BeanFactory)、Context(Spring配置的上下文 ApplicationContext)、Core、SpEL(Spring的EL表达式)
  • 测试组件:Spring-test包含:mock(模拟)测试、Random Port(随机端口测试)、TestContext Framework(测试上下文框架)

3.集成Spring框架

  • 在项目的pom中添加spring-context依赖,通过Maven的依赖传递将Spring其他核心组件的jar包也一起依赖进项目
<!--依赖Spring相关jar包-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.2.1.RELEASE</version>
    </dependency>

4.Bean的概念

  • <beans…/>元素是Spring配置文件的根元素,<beans…/>元素可以包含多个<bean…/>子元素,每个<bean…/>元素可以定义一个Bean实例,每一个Bean对应Spring容器里的一个Java实例定义Bean时通常需要指定两个属性。
  • Id:确定该Bean的唯一标识符,容器对Bean管理、访问、以及该Bean的依赖关系,都通过该属性完成。Bean的id属性在Spring容器中是唯一的。
  • Class:指定该Bean的具体实现类。注意这里不能使接口。通常情况下,Spring会直接使用new关键字创建该Bean的实例,因此,这里必须提供Bean实现类的类名。
  • Spring容器集中管理Bean的实例化,Bean实例可以通过BeanFactory的getBean(String beanid)方法得到。BeanFactory是一个工厂,程序只需要获取BeanFactory引用,即可获得Spring容器管理全部实例的引用。程序不需要与具体实例的实现过程耦合。大部分Java EE应用里,应用在启动时,会自动创建Spring容器,组件之间直接以依赖注入的方式耦合,甚至无须主动访问Spring容器本身。
  • 当我们在配置文件中通过方法配置一个Bean时,这样就需要该Bean实现类中必须有一个无参构造器。

5.构建Spring的一个Bean对象

  • 1.编写一个HelloService类,同时创建一个hello()
  • 2.创建一个application.xml文件,同时添加beans相关的命名空间,配置HelloService 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 其中id唯一标记这个bean,class属性代表是这个bean的类-->
    <bean id="helloService" class="com.shsxt.service.HelloService" />

</beans>
  • 3.编写测试代码,测试启动Spring容器,从容器中获取HelloService对象(bean)
    第一步:启动容器:创建一个ApplicationContext对象,有两个实现类:ClassPathXmlApplicationContext和FileSystemXmlApplicationContext,传入对应的xml配置文件
    第二步:获取bean对象:ApplicationContext中的getBean(id/name, clazz)
    第三步:执行bean的方法
  /**
     * 通过构建一个FileSystemXmlApplicationContext上下文对象(本质是一个ApplicationContext)
     */
    public static void getHelloServiceBean01() {
        // 启动Spring容器: ApplicationContext是Spring的核心上下文容器
        ApplicationContext ac = new FileSystemXmlApplicationContext("classpath:application.xml");
        // 获取对象
        HelloService helloService = (HelloService) ac.getBean("helloService");
        // 执行对象中的方法
        helloService.hello();
    }


    /**
     * 通过构建一个ClassPathXmlApplicationContext上下文对象(本质是一个ApplicationContext)
     */
    public static void getHelloServiceBean02() {
        // 启动Spring容器: ApplicationContext是Spring的核心上下文容器
        ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:application.xml");
        // 获取对象
        HelloService helloService = ac.getBean("helloService", HelloService.class);
        // 执行对象中的方法
        helloService.hello();
    }


6.构建Spring的一个Bean对象

  • 思路
    1.读取xml,解析xml配置(dom4j解析)(解析方式2种:DOM解析–全部读取xml节点到内存,然后进行解析;SAX解析–边读取边解析)
    2.获取<bean id=”” class=”” />标签,将bean标签的属性封装到对象中
    3.将解析后的标签的对象存入集合中
    4.遍历解析后的Bean标签(id, class)集合,同时利用反射机制创建对象,并将id和对象存入map中
    5.编写一个getBean(id)的方法获取bean实例化后的对象

  • 代码实现

第一步:编写一个BeanFactory,暴露一个getBean接口

/**
 * 模拟Bean工程提供获取Bean的方法
 */
public interface BeanFactory {

    public Object getBean(String id);

}

第二步:编写BeanFactory的实现类SxtClassPathXmlApplicationContext()
该类包含两个属性:第一个属性存放Map其中key为id, value为实例化后的bean对象;第二个属性就存放bean标签的集合对象

/**
 * 模拟的是一个ApplicationContext上下文容器
 */
public class SxtClassPathXmlApplicationContext implements BeanFactory {

    private Map<String, Object> beans = new HashMap<>();// 实例化后的对象放入map
    private List<SxtBean> sxtBeans;// 存放已读取bean 配置信息

}

第三步:编写一个构造器,传入xml配置文件,调用解析方法进行xml读取、解析,调用实例化对象的方法去实例化对象(应用反射)

// 构造器,传入xml配置文件名
public SxtClassPathXmlApplicationContext(String fileName) {
	this.readBeansXml(fileName);// 读取并解析配置文件
	this.insranceBeans(); // 实例化bean
}

第四步:读取、解析xml配置文件,将bean标签内容存入集合的SxtBean对象中(bean metadata)

/**
 * 读取 并解析xml 配置文件
 * @param fileName
 */
private void readBeansXml(String fileName) {
    URL url=this.getClass().getClassLoader().getResource(fileName);
    // 判断xml配置文件是否存在
    if (url == null) {
        System.out.println("资源文件未找到!");
        return;
    }
    // 解析xml配置文件
    SAXReader saxReader=new SAXReader();// 创建saxReader 对象
    Document doc= null;
    try {
        doc = saxReader.read(url);
    } catch (DocumentException e) {
        e.printStackTrace(); // 打印异常的堆栈信息
        return;
    }
    Map<String, String> map = new HashMap<>(); // 一定要加泛型
    map.put("sxt", "http://www.springframework.org/schema/beans");  //将xml命名空间放入map
    XPath xPath= doc.createXPath("//sxt:bean");//定义查找路径
    xPath.setNamespaceURIs(map);
    List<Element> elements = xPath.selectNodes(doc);
    if (CollectionUtils.isEmpty(elements)) {
        return;
    }
    sxtBeans = new ArrayList<>();
    for(Element element : elements){
        //System.out.println(element.attributeValue("id")+element.attributeValue("class"));
        SxtBean sxtBean = new SxtBean(element.attributeValue("id"), element.attributeValue("class"));
        sxtBeans.add(sxtBean);
    }
}

第五步:遍历bean的元数据信息(SxtBean集合)信息,利用反射实例化对象,同时存储到map中

/**
 * 实例化bean 对象
 */
private void insranceBeans() {

    // 先判断<bean>标签集合是否有值
    if (CollectionUtils.isEmpty(sxtBeans)) {
        return;
    }
    // 遍历<bean>标签,同时利用反射机制生成对象,并将对象存入map中,其中key为bean对象的id,value是对象
    for(SxtBean sxtBean: sxtBeans){
        try {
            beans.put(sxtBean.getId(), Class.forName(sxtBean.getClazz()).newInstance());
        } catch (Exception e) {
            continue;
        }
    }
}

第六步:重写getBean方法,从map中返回bean的实例化后的对象

/**
 * 根据id 名获取bean
 */
@Override
public Object getBean(String id) {
    return beans.get(id);
}

7.IOC容器加载多个配置文件

第一种:启动ApplicationContext上下文容器时,允许加载多个配置文件

@Test
public void testMultiXml() {
    // 启动IOC容器(加载配置文件生成ApplicationContext)
    ApplicationContext ac = new ClassPathXmlApplicationContext("controller.xml", "dao.xml", "service.xml");
    // 获取Bean对象
    UserController userController = ac.getBean("userController", UserController.class);
    UserService userService = ac.getBean("userService", UserService.class);
    UserDao userDao = ac.getBean("userDao", UserDao.class);
    // 调用Bean方法
    userController.show();
    userService.add();
    userDao.save();
}

第二种:用某一个公共的配置文件,把其他配置文件通过<import resource=”” />导入进来

    <!--配置bean 其中id唯一标记这个bean,class属性代表是这个bean的类-->
    <bean id="helloService" class="com.shsxt.service.HelloService" />

    <import resource="controller.xml"/>
    <import resource="service.xml"/>
    <import resource="dao.xml"/>
 @Test
public void testSingleXml() {
    // 启动IOC容器(加载配置文件生成ApplicationContext)
    ApplicationContext ac = new ClassPathXmlApplicationContext("application.xml");
    // 获取Bean对象
    UserController userController = ac.getBean("userController", UserController.class);
    UserService userService = ac.getBean("userService", UserService.class);
    UserDao userDao = ac.getBean("userDao", UserDao.class);
    // 调用Bean方法
    userController.show();
    userService.add();
    userDao.save();
}

8.Bean的实例化方式

  • 第一种是上面写的构造器实例化
  • 第二种是静态工厂实例化
**
 * 静态工厂实例化Bean
 */
public class StaticFactory {

   /**
    * 编写一个静态方法,同时返回一个实例化对象
    * @return
    */
    public static UserService createUserService(){
      return new UserService();
   } 
}
<?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,配置的class指向工厂类,添加factory-method属性指向创建对象的静态方法-->
    <bean id="userService" class="com.shsxt.factory.StaticFactory" factory-method="createUserService" />

</beans>
  • 第三种是实例化工厂方法
/**
 * 实例化工厂创建Bean对象
 */
public class InstanceFactory {

    /**
     * 此方法不需要静态化
     * @return
     */
    public UserService createUserService() {
        return new UserService();
    }

}
<?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对象-->
    <bean id="instanceFactory" class="com.shsxt.factory.InstanceFactory"  /> <!--工厂bean-->

    <!--实例化UserService Bean-->
    <bean id="userService" factory-bean="instanceFactory" factory-method="createUserService" />
</beans>

9.对象依赖与注入

1.IOC本质问题

  • IOC:控制反转,就是由原来主动创建对象改成交给spring创建对象
public class UserController {
	private UserService userService = new UserService();  // 主动创建
}
public class UserController {
	private UserService userService ;

	public UserController(UserService userService) {   // 交由第三方创建在传入
		this.userService = userService;
}

2.依赖注入(DI)

  • 依赖:对象与对象之间的关系,注入由第三方(Spring)在实例化对象时进行注入。因此DI是IOC的另外一种表达方式,换个说法:IOC是DI的理论基础

3.依赖注入的方法

  • 四种注入方式
    • 构造器注入(比较常用)
    • setter注入(最常用)
    • 静态工厂注入(比较少用)
    • 实例工厂注入(比较少用)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值