「2020最新」Spring最易学习教程—第一个Spring程序

1 Spring简介

Spring 是一款轻量级的JavaEE开发框架,其对比的EJB是Sun官方力推的JavaEE解决方案。使用EJB编码必须要实现EJB的组件,必须运行在支持EJB的服务器中,无论是测试还是运行都十分不便。Spring能够非侵入的解决JavaEE的通用问题,在测试、运行、扩展等方面比EJB强大的多。

Spring构建于众多优秀的设计模式之上:工厂设计模式代理设计模式、模板方法设计模式、策略设计模式...

设计模式:前人总结好的,用于解决特定问题的方案。

学习Spring的核心就是学习其应用的设计模式本身要解决那些问题。

2 工厂设计模式

工厂设计模式:使用工厂创建对象,代替new创建对象。

new模式的问题:

image-20200727192500840
image-20200727192500840

new模式下,类和类之间是强耦合的。

解决方案:工厂设计模式(解耦合)

image-20200727193150450
image-20200727193150450
  1. 配置一个properties文件

    userService=com.bcl.service.impl.UserServiceImpl
    
  2. 创建BeanFactory工厂类

    public class BeanFactory {
        private static Properties prop = new Properties();
        static{
            //通过流读取配置文件,保存到prop
            InputStream in = BeanFactory.class.getResourceAsStream("/applicationContext.properties");
            try {
                prop.load(in);
            } catch (IOException e) {
                e.printStackTrace();
                throw new RuntimeException(e);
            }finally{
                if(in != null){
                    try {
                        in.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        public static Object getBean(String id){

            //获取类对象
            Object o = null;
            try {
                Class c = Class.forName(prop.getProperty(id));
                o = c.newInstance();
            } catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException(e);
            }
            //创建对象
            return o;
        }
    }
  3. 面向接口编程

    UserService service = (UserService) BeanFactory.getBean("userService");

工厂设计模式的特点:配置文件+反射+面向接口编程

通过工厂模式,解开了类和类之间强耦合,提高了程序的可维护性和可扩展性,满足开闭原则。

3 第1个Spring程序

Spring框架的基本作用:对象工厂(容器)。可以借助Spring工厂创建(获取)对象,解开类和类之间的耦合,提高程序的维护性和扩展性。

3.1 Spring工厂的使用步骤

  1. 导入依赖

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.3.26.RELEASE</version>
    </dependency>
  2. 导入配置文件

    applicationContext.xml位置任意,建议放置在resources根目录下。

    <bean id="标识" class="全类名"/>
  3. 创建Spring工厂,获取对象

    Spring中工厂类型:ApplicationContext(接口)
        
      实现类:
          非web环境: ClassPathXmlApplicationContext
          web环境: XmlWebApplicationContext 
        
         方法:
          Object getBean(String id);

3.2 Spring工厂实战

  1. 创建一个业务类

  2. 配置applicationContext.xml

    <bean id="userService" class="com.bcl.service.impl.UserServiceImpl"/>
  3. 创建Spring工厂,获取对象

    //创建Spring工厂
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
    //从工厂中获取UserService
    UserService userService = (UserService)applicationContext.getBean("userService");
    userService.deleteUserById(1);

4 Spring框架的组成模块

image-20200529113407665
image-20200529113407665
  1. Test:简化Spring代码的测试
  2. 核心容器:Spring作为对象工厂的实现
  3. AOP和Aspects:面向切面编程,非侵入的为现有代码提供增强功能
  4. 辅助功能
  5. 数据访问:提供了访问数据库的功能
  6. Web模块:提供了对Web开发的支持

Spring提供了一套完整的企业应用开发方案,同时还能和其它框架整合(Struts2、MyBatis)。在发展中,Spring族系涌现出一系列的优秀的子框架,最终发展成一个开发生态。Spring族系有名的框架:SpringMVC、SpringBoot、SpringCloud、SpringData、SpringSecurity、SpringTask...

5 Spring工厂实现原理

Spring工厂创建对象:读取配置文件(applicationContext.xml),获取到全类名,通过反射默认调用无参构造方法创建对象。

bean标签的scope属性设置对象是否单例:

singleton (单例 默认值)

prototype (多例)

为什么单例是默认策略?节省内存空间

可以被用户公用的对象(单例):

Dao、service、SqlSessionFactory

不能被用户公用的对象(多例):

connection、sqlSession、Cart、Action

6 注入(Injection)

给对象的属性赋值(注入值)。

image-20200727193438437
image-20200727193438437

6.1 Set注入

本质:通过无参构造方法创建对象后,调用对象属性的set方法进行赋值。

操作:在bean标签中,通过property子标签为对象的属性进行set注入。

6.1.1 基本类型(包装类)+String

<bean id="s" class="com.bcl.entity.Student">
    <!-- name属性:对象的属性名
   value子标签体:对象的属性值
 -->

    <property name="id">
        <value>1</value>
    </property>
    <property name="name">
        <value>xiaohei</value>
    </property>
    <property name="age">
        <value>18</value>
    </property>
    <property name="score">
        <value>100.0</value>
    </property>
</bean>

<bean id="s" class="com.bcl.entity.Student">
    <!-- name属性:对象的属性名
   value属性:对象的属性值
 -->

 <property name="id" value="1"/>
        <property name="name" value="xiaohei"/>
        <property name="age" value="18"/>
        <property name="score" value="100.0"/>
</bean>

6.1.2 自定义对象类型

<bean id="a" class="com.bcl.entity.Address">
    <property name="city" value="郑州"/>
    <property name="street" value="文化路"/>
</bean>
<bean id="p" class="com.bcl.entity.Person">
    <property name="addr">
        <!--
    ref标签的bean属性:另外一个bean的id值
  -->

        <ref bean="a"/>
    </property>

    <property name="id" value="1"/>
    <property name="personName" value="xiaohei"/>
</bean>


<bean id="p" class="com.bcl.entity.Person">
    <!--
  ref属性:另外一个bean的id值
 -->

    <property name="addr" ref="a"/>
    <property name="id" value="1"/>
    <property name="personName" value="xiaohei"/>
</bean>

6.1.3 数组、List和Set

<bean id="u" class="com.bcl.entity.User">
    <property name="id" value="1"/>
    <property name="name" value="xiaohei"/>

    <property name="os">
        <!-- 
   array标签表示一个数组
   元素是简单数据用value子标签
   元素是自定义类型数据用ref子标签
  -->

        <array>
            <value>1</value>
            <value>100.0</value>
            <value>hhh</value>
            <ref bean="a"/>
        </array>
    </property>

    <property name="list">
        <!-- 
   list标签表示一个List集合
   元素是简单数据用value子标签
   元素是自定义类型数据用ref子标签
  -->

        <list>
            <value>1</value>
            <value>hhh</value>
            <ref bean="a"/>
            <ref bean="a2"/>
        </list>
    </property>

    <property name="set">
        <!-- 
   set标签表示一个Set集合
   元素是简单数据用value子标签
   元素是自定义类型数据用ref子标签
  -->

        <set>
            <value>1</value>
            <value>1</value>
            <value>hhh</value>
            <ref bean="a"/>
            <ref bean="a2"/>
        </set>
    </property>
</bean>

6.1.4 Map和Properties

<bean id="u" class="com.bcl.entity.User">
    <property name="map">
        <map>
            <entry key="k1"><value>v1</value></entry>
            <entry key="k2" value="v2"/>
            <entry key="k3" value-ref="a"/>
            <entry key-ref="p" value-ref="a"/>
        </map>
    </property>

    <property name="prop">
        <props>
            <prop key="pk1">pv1</prop>
            <prop key="pk2">pv2</prop>
        </props>
    </property>
</bean>

6. 2 构造注入

本质:调用有参构造方法创建对象的同时,为属性赋值。

前提:必须要提供有参构造

操作:在bean标签中定义constructor-arg子标签。

6.2.1 基本使用

当一个类中的多个有参构造方法的参数个数不同时,constructor-arg标签会根据数量匹配构造方法进行调用
<bean id="b1" class="com.bcl.entity.Book">
        <constructor-arg value="1"/>
        <constructor-arg value="十万个为什么"/>
        <constructor-arg value="100000.0"/>
        <constructor-arg value="佚名"/>
    </bean>

6.2.2 type属性

当一个类中的构造方法,形参个数相同,类型不同时,通过type属性明确形参类型,调用指定构造方法。
<bean id="b1" class="com.bcl.entity.Book">
    <constructor-arg value="1" type="java.lang.Integer"/>
</bean>

6.2.3 index属性

index属性设置形参的下标,从0开始
<bean id="b1" class="com.bcl.entity.Book">
        <constructor-arg value="1" type="java.lang.Integer" index="0"/>
        <constructor-arg value="十万个为什么" type="java.lang.String" index="1"/>

    </bean>

6.3 自动装配

本质:Spring自动分析属性,调用属性的set方法完成赋值。

操作:通过bean标签的属性 autowire = "byType"|"byName"

 <bean id="bookService" class="com.bcl.service.impl.BookServiceImpl"/>
    <!--<bean id="bookService2" class="com.bcl.service.impl.BookServiceImpl"/>-->

<!--
 byType:根据属性的类型,在Spring容器中获取需要的对象
  注意此时Spring中该类型的对象必须唯一

 byName:根据属性的名字,在Spring容器找id="属性名"的对象
-->

    <bean id="bookAction" class="com.bcl.action.BookAction" autowire="byType">
    </bean>

「❤️ 帅气的你又来看了我」

如果你觉得这篇内容对你挺有有帮助的话:

  1. 点赞支持下吧,让更多的人也能看到这篇内容(收藏不点赞,都是耍流氓 -_-)

  2. 欢迎在留言区与我分享你的想法,也欢迎你在留言区记录你的思考过程。

  3. 觉得不错的话,也可以关注 编程鹿 的个人公众号看更多文章和讲解视频(感谢大家的鼓励与支持🌹🌹🌹)

posted @ 2020-07-27 19:52  编程鹿  阅读(252)  评论(0编辑  收藏  举报