Spring应用学习——IOC

Easter79
• 阅读 376

1. Spring简介

    1. Spring的出现是为了取代EJB(Enterprise JavaBean)的臃肿、低效、脱离现实的缺点。Spring致力于J2EE应用的各层(表现层、业务层、持久层)的解决方案,Spring是企业应用开发的“一站式”选择。

    2. 定义:Spring是分层的JavaSE/EE应用一站式的轻量级开源框架(官网: http://spring.io/ ),以Ioc(Inverse of control)控制反转和Aop(Aspect Oriented Programming)面向切面编程为核心。

    3. 优点:

  • 轻量级:针对EJB来说,使用方便。
  • 一站式:spring针对各各层(表现层、业务层、持久层)提出解决方案。
    • 表现层:springmvc(spring自己的mvc框架),提供和其它web框架整合方案。
    • 业务层:spring基于aop(面向切面编程)思想进行事务控制。
    • 持久层:spring自己提供JdbcTemplate,提供和其它持久层框架整合的方案。

    4. spring核心 :Ioc(控制反转)和aop(面向切面编程)。重点是:IOC,spring要管理各各层的bean。

    5. Spring模块组件图:

Spring应用学习——IOC

2. Spring IOC

1. 什么是IOC

    1. 不使用ioc,代码中创建一个对象直接操作接口实现类,并没有面向接口开发。面向接口开发指的是调用接口的方法,只面向接口而不面向接口实现类,因为一个接口可能有多个实现类。而没有面向接口开发的问题就是调用接口的类和接口实现类之间存在直接耦合。比如下列代码

//老板向一个写字员发出命令去做一个工作
public class Boss {
    private Writer emp;//直接使用Writer类,与Boss产生强依赖关系,直接耦合

    //老板只能向写字员发出命令,如果想要向一个秘书或其他员工发出命令则无法实现,这显然是不合理的
    public void order(){
        emp=new Writer();
        emp.doJob();
    }
}
public class Writer{
    public void doJob(){
        System.out.println("do something");
    }
}

面向接口开发的改进代码:

//老板向一个员工发出命令去做一个工作
public class Boss {
    private Employee emp;//使用Employee接口,将具体实现类与Boss解耦合,这样就大大增强了代码的可重用性并减弱耦合度

    //老板可以向任何一个实现了Employee接口的员工类发出命令
    public void order(){
        emp=new Writer();
        emp.doJob();
    }
}
public class Writer implements Employee{
    public void doJob(){
        System.out.println("do something");
    }
}
public interface Employee {
    public void doJob();
}

    2. IOC:Inverse of Control,即控制反转。是指将原来程序中自己创建实现类对象的控制权反转到IOC容器中。只需要通过IOC获了对象的实例,将IOC当成一个黑盒子、工厂。对象只与工厂耦合,对象之间没有耦合。而上面的代码也可以改为

//老板向一个员工发出命令去做一个工作
public class Boss {
    private Employee emp;//使用Employee接口,这样就大大增强了代码的可重用性并减弱耦合度
    //老板可以向任何一个实现了Employee接口的员工类发出命令,但这里的Employee的具体实现类对象由IOC容器提供,通过IOC容器来生成所需要的对象,这样可以将Boss类与具体员工类解耦,所有的类之间的依赖关系都由IOC容器进行管理,便于修改维护

    public void order(){
        emp=IOC容器.getEmp();
        emp.doJob();
    }
}
public class Writer implements Employee{
    public void doJob(){
        System.out.println("do something");
    }
}
public interface Employee {
    public void doJob();
}

Spring应用学习——IOC

2. Spring IOC的使用

    1. 首先建立一个Maven项目,通过Maven来导入所需要的jar包,主要是spring-webmvc.jar以及其相关的依赖jar包,使用4.3.版本,另外要注意,JDK版本与Spring版本的兼容问题,Spring4.0以后的版本建议使用JDK1.8版本;其次要导入commons-logging.jar,该包是Spring所使用的JCL日志体系jar包,只有相关接口,具体的实现类还需要导入log4j.jar。

    2. 编写Spring IOC容器的配置文件:是一个xml文件

  • 引入xml文件Spring的相关标签约束,加入的每一个Spring的相关jar包里都会包含该jar包相关的约束文件,具体如何添加可以网上搜索相关方法,这里给一个基本全面的标签约束,可以直接复制粘贴使用,xsi:schemaLocation中可以修改每个版本的约束文件,比如Spring4.3版本的beans相关约束可以将http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 改为 **http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/****spring-beans-4.3.xsd**

    <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" 
        xmlns:jdbc="http://www.springframework.org/schema/jdbc"  
        xmlns:jee="http://www.springframework.org/schema/jee" 
        xmlns:tx="http://www.springframework.org/schema/tx"
        xmlns:aop="http://www.springframework.org/schema/aop" 
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xmlns:util="http://www.springframework.org/schema/util"
        xmlns:jpa="http://www.springframework.org/schema/data/jpa"
        xsi:schemaLocation="
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
            http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
            http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
            http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
            http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
            http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd">
    
  • 在xml文件中的beans标签内添加bean,bean标签内有多个属性以及一些嵌套标签,用于定义bean的相关操作,下面简单定义一个bean作为示例

    //注意,一个JavaBean类的规范实现
    public class UserData{
        private String cn_user_id;
        private String cn_user_name;
        private String cn_user_password;
        public static UserData getUser(){
            return new UserData("9527","9527","9527");
        }
        public UserData(String cn_user_id, String cn_user_name, String cn_user_password) {
            super();
            this.cn_user_id = cn_user_id;
            this.cn_user_name = cn_user_name;
            this.cn_user_password = cn_user_password;
        }
    //IOC容器中的bean必须有无参构造方法,也就是默认构造方法
        public UserData() {
            super();
        }
        public String getCn_user_id() {
            return cn_user_id;
        }
        public void setCn_user_id(String cn_user_id) {
            this.cn_user_id = cn_user_id;
        }
        public String getCn_user_name() {
            return cn_user_name;
        }
        public void setCn_user_name(String cn_user_name) {
            this.cn_user_name = cn_user_name;
        }
        public String getCn_user_password() {
            return cn_user_password;
        }
        public void setCn_user_password(String cn_user_password) {
            this.cn_user_password = cn_user_password;
        }
        
    }
    
    
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans" 
        xsi:schemaLocation="
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
        <!-- bean标签:
            1.id/name属性:用来标示bean的名称,该名称在SpringIOC容器中不允许重复,如果不指定名称,将默认为类路径
            2.class属性:IOC要管理实现类的全限定路径名,IOC将根据此路径去实例化类对象
         -->
        <bean id="user" class="com.cloud_note.entity.UserData"></bean>
        <!-- SpringIOC实例化bean的三种方法:
        1.默认无参构造器
        2.有参构造器
        3.静态工厂方法
         -->
        <!-- 有参构造器方法 -->
        <bean id="user1" class="com.cloud_note.entity.UserData">
        <!-- index指参数在参数列表的下标,从0开始 -->
            <constructor-arg index="0" value="9527" type="java.lang.String"></constructor-arg>
            <constructor-arg index="1" value="9527" type="java.lang.String"></constructor-arg>
            <constructor-arg index="2" value="9527" type="java.lang.String"></constructor-arg>
        </bean>
        <!-- 静态工厂方法,通过类中的静态工厂方法生成bean实例 -->
        <bean id="user2" class="com.cloud_note.entity.UserData" factory-method="getUser">
    
        <!-- bean作用域:
        1.singleton:单例模式,即在Spring容器启动时只生成一个bean实例,在每次访问(getBean)时都将此对象返回,Spring容器默认此方式
        2.prototype:多例模式,即每次访问(getBean)Spring容器都会返回一个新实例
        3.request
        4.session
         -->
        <bean id="user" class="com.cloud_note.entity.UserData" scope="singleton"></bean>
        <bean id="user1" class="com.cloud_note.entity.UserData" scope="prototype"></bean>
        </bean>
    </beans>
    

    Spring应用学习——IOC

  • 编写测试代码,测试是否能从上面配置的IOC容器中取出指定的bean对象

    //测试从Spring中获取bean实例,该测试方法需要导入junit的jar包,来使用@Test相关注解
    public class TestCase1 {
        //测试无参构造器方法
        @Test
        public void test1(){
            //1.获取SpringIOC容器对象
            ApplicationContext app=new ClassPathXmlApplicationContext("config/applicationContext.xml");
            //2.从SpringIOC中获取对应的bean实例
            UserData user=(UserData) app.getBean("user");
            System.out.println("获取成功");
        }
        //测试有参构造器方法
        @Test
        public void test2(){
            ApplicationContext app=new ClassPathXmlApplicationContext("config/applicationContext.xml");
            UserData user=(UserData) app.getBean("user1");
            System.out.println(user.getCn_user_id());
        }
        //测试静态工厂方法
        @Test
        public void test3(){
            ApplicationContext app=new ClassPathXmlApplicationContext("config/applicationContext.xml");
            UserData user=(UserData) app.getBean("user2");
            System.out.println(user.getCn_user_id());
        }
        
        //获取SpringIOC容器对象的方法
        @Test
        public void test4(){
            //1.FileSystemXmlApplicationContext是通过加载文件系统路径下的配置文件来创建一个容器实例
            ApplicationContext app1=new FileSystemXmlApplicationContext("/src/main/resources/config/applicationContext.xml");
            //2.ClassPathXmlApplicationContext是通过加载classpath路径下的配置文件来创建一个容器实例
            ApplicationContext app2=new ClassPathXmlApplicationContext("config/applicationContext.xml");
            //3.同时加载多个配置文件,可以连续填写多个路径参数或传入数组,或者通过通配符来加载
            ApplicationContext app3=new ClassPathXmlApplicationContext("config/applicationContext.xml","config/applicationContext1.xml");
            String[] configs=new String[]{"config/applicationContext.xml","config/applicationContext1.xml"};
            ApplicationContext app4=new ClassPathXmlApplicationContext(configs);
            ApplicationContext app5=new ClassPathXmlApplicationContext("classpath:config/applicationContext*.xml");
        }
    

    3. 使用注解向IOC容器中添加bean:

  • 首先要在Spring配置文件中开启组件扫描

    <?xml version="1.0" encoding="UTF-8"?>
    <!--省略xml约束-->
    <beans>
        <!-- Spring注解开发:通过注解来管理Spring的bean -->
        <!-- 开启组件扫描,用以扫描指定包内带有实例化注解的类 -->
        <context:component-scan base-package="package"></context:component-scan>
    
    </beans>
    
  • 对象实例化的注解有四种,分别是:通过注解进行实例化时,必须保证类中有默认构造方法

    • @Component:指定该类为一个普通bean,默认id为类名首字母小写,也可指定id,如@Component("user")
    • **@Repository**:指定该类为一个持久层bean,默认id为类名首字母小写,也可指定id,如@Repository("user")
    • **@Service**:指定该类为一个业务层bean,默认id为类名首字母小写,也可指定id,如@Service("user")
    • @Controller:指定该类为一个控制层bean,默认id为类名首字母小写,也可指定id,如@Controller("user")
  • @Scope("prototype"/"singleton"):该注解指定bean的作用域,该注解要与以上注解搭配使用,singleton表示容器中只生成一个实例,也就是单例模式,默认为该模式;而prototype表示会生成多个实例,每访问一次容器就创建一次Spring应用学习——IOC

3. DI(依赖注入)

    1. 即IOC容器在运行期间动态的将对象的依赖关系注入到对象的属性中,底层原理为:首先生成类对象,依据所依赖的属性类型生成属性实例,然后通过set方法来实现注入,或通过有参构造器在生成类的实例时注入所依赖的属性实例
    2. 依赖注入的实现方式有两种:有参构造器实现注入、set方法实现注入

    3. 通过配置文件配置依赖注入:有参构造器在上面的IOC介绍中已经演示

<?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" 
    xmlns:jdbc="http://www.springframework.org/schema/jdbc"  
    xmlns:jee="http://www.springframework.org/schema/jee" 
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop" 
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:util="http://www.springframework.org/schema/util"
    xmlns:jpa="http://www.springframework.org/schema/data/jpa"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
        http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd">
    
    <!--set方法实现注入-->
    <bean id="user" class="UserData"></bean>
    <bean id="book" class="Book">
    <!-- property标签:指定注入的属性 
        name属性用来指定类中需要注入的属性名,由set方法后的字符串首字母小写决定,即调用注入的set方法时将由set+name属性值
        来决定调用那个set方法
        ref属性表示被注入的bean的id
        value属性表示一个具体的值,用于java中的简单类型
    -->
        <property name="user" ref="user"></property>
    </bean>
    
    <!-- set方法可以注入的属性类型 -->
    <bean id="queryVo" class="QueryVo">
    <!-- 基本类型 -->
    <property name="t1" value="vn"></property>
    <property name="t2" value="1"></property>
    <!-- pojo类型 -->
    <property name="t3" ref="user"></property>
    <!-- List类型   List<String> -->
    <property name="t4">
        <list>
            <value>vn</value>
        </list>
    </property>
    <!-- List类型   List<UserData> -->
    <property name="t5">
        <list>
            <ref bean="user"/>
        </list>
    </property>
    <!-- Map类型 -->
    <property name="t6">
        <map>
            <entry key="1" value="vn"></entry>
        </map>
    </property>
    <!-- Properties类型 -->
    <property name="t7">
        <props>
            <prop key="name">vn</prop>
        </props>
    </property>
    </bean>
</beans>

    4. 通过注解进行依赖注入:

  • 首先需要开启Spring组件扫描,并且要保证注入的属性实例的类以及被注入的类都在Spring容器中

  • @Autowired:直接标记在属性上,依据属性类型进行注入,即依据该类型在容器中查找相同类型或基类的bean进行注入,若依据类型查找到多个bean,则会报错,可以在要注入的bean的类前添加实例注解时指定bean的id即可避免,也可以写在set方法上, @Autowired会依据set方法中的参数类型来查找bean

  • @Qualifier("id"):该注解要写在@Autowired之后,搭配使用,用来指定要注入的bean的id,也可以避免上面的错误, 这两个注解也可以写在set方法上

  • @Resource(name="user"):相当于@Autowired+@Qualifier(""),直接依据id查找,@Autowired是由Spring提供的,而@Resource是由jdk提供的

    @Component("book") @Scope("prototype") public class Book implements Serializable { private String cn_notebook_id; //@Autowired //@Qualifier("user") @Resource(name="user") private UserData user; public UserData getUser() { return user; } //@Autowired //@Qualifier("user") public void setUser(UserData user) { this.user = user; } public String getCn_notebook_id() { return cn_notebook_id; } public void setCn_notebook_id(String cn_notebook_id) { this.cn_notebook_id = cn_notebook_id; } }

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Easter79 Easter79
2年前
springcloud eureka.instance
1.在springcloud中服务的 InstanceID默认值是:${spring.cloud.client.hostname}:${spring.application.name}:${spring.application.instance\_id:${server.port}},也就是:主机名:应用名:应用端口。如图1
Easter79 Easter79
2年前
Spring框架之IoC和AOP
Spring框架简介:2003年2月,Spring框架正式成为一个开源项目,并发布于SourceForge中。致力于JavaEE应用的各种解决方案,而并不是仅仅专注于某一层的方案,是企业应用开发的“一站式”选择。贯穿表现层,业务层,持久层,并不取代已有的框架,而是以高度的开放性与它们无缝整合。注:首先通过Spring官网的地址http://
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Easter79 Easter79
2年前
Spring的基本应用(1):IDEA版本
一、Spring概述:1.什么是Spring?Spring是分层的JavaSE/EE应用fullstack(一站式)轻量级开源框架,以IoC(InverseOfControl:控制反转)和AoP(AspectOrientedPrograming,面向切面编程)为内核,提供了展现层SpringMVC和持久层Spring
Stella981 Stella981
2年前
Spring 学习笔记(一):Spring 入门
1Spring简介Spring是一个轻量级Java开发框架,最早由RodJohnson创建,目的是为了解决企业级应用开发的业务逻辑层和其他各层的耦合问题,是一个分层的JavaSE/EEfullstack轻量级开源框架,为开发Java应用程序提供全面的基础架构支持。2Spring体系结构
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
Easter79
Easter79
Lv1
今生可爱与温柔,每一样都不能少。
文章
2.8k
粉丝
5
获赞
1.2k