Spring入门

导读:本篇文章讲解 Spring入门,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

Spring入门

一、Spring概论

Spring框架是由于软件开发的复杂性而创建的。Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅仅限于服务器端的开发。从简单性、可测试性和松耦合性角度而言,绝大部分Java应用都可以从Spring中受益。

在Javaweb中,我们需要自己手动new大量的对象,**但是在spring框架中,这些new对象的操作可以由spring完成,**大大减少了程序员的工作量,以及减少后期代码维护的成本

并且在spring框架中,我们只需要修改配置文件即可完成代码的修改,不需要对java代码进行更改,便于维护代码


二、Spring开发步骤

在这里插入图片描述

上图就是Spring框架创建对象的过程

  1. 首先在Spring的xml配置文件中,用一个Bean容器给其一个id(id不可重复)
  2. 在程序中只需要使用Spring客户端的getBean(id标识)方法即可
  3. 而Spring框架会读取xml配置文件,根据id表示获得Bean全限定名,接着通过反射创建Bean对象,最后返回对象

Spring的开发步骤:

  1. 首先导入Spring开发的基本包坐标

    <!--导入springjar包-->
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>5.0.5.RELEASE</version>
        </dependency>
    
  2. 编写Dao接口和实现类

  3. 接着创建Spring核心配置文件(在resources右键——>新建——>XML配置文件——>Spring配置)

    在这里插入图片描述

  1. 在Spring配置文件中配置UserDaoImpl

    <?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="userDao" class="com.kang.impl.UserDaolmpl" ></bean>
    
    </beans>
    
  2. 在Spring的API获取到Bean实例

    package com.kang.demo;
       
    import com.kang.UserDao;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
       
    public class UserDaoDemo {
        public static void main(String[] args) {
            ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
            UserDao userDao = (UserDao) app.getBean("userDao");
            userDao.save();
        }
    }
    
  • 在Spring的XML配置文件中,class的路径必须为全限名字,例如com.kang.impl.UserDaolmpl

三、 Spring配置文件

1、Bean标签范围配置

scope:指的是对象的作用范围,其取值如下

取值范围 说明
singleton 默认值,单例的
prototype 多例的
request WEB项目中,Spring创建的一个Bean的对象,将对象存入到request域中
session WEB项目中,Spring创建的一个Bean的对象,将对象存入到session域中
golobal sesssion WEB项目中,应用在Portlet环境,如果没有Portlet环境那么golobal sesssion香港党羽seesion
  • 当scope取值为singleton的时候

    <?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="userDao" class="com.kang.impl.UserDaolmpl" scope="singleton"></bean>
    
    </beans>
    

    Bean的实例化个数:1个

    Bean的实例化时机:当Spring核心文件被加载时,实例化配置的Bean实例

    package com.kang.test;
    
    import com.kang.UserDao;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class SpringTest {
        @Test
        public void test01(){
            //当程序执行完这条代码,也就是读取完xml配置文件,对象就被创建,而且多次创建的对象都是同一个对象
            ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
            UserDao userDao1 = (UserDao) app.getBean("userDao");
            UserDao userDao2 = (UserDao) app.getBean("userDao");
            System.out.println(userDao1);
            System.out.println(userDao2);
        }
    }
    

    在这里插入图片描述

    Bean的生命周期:

    • 对象创建:当应用加载,创建容器时,对象就被创建
    • 对象运行:只要容器在,对象一直活着
    • 对象销毁:当应用卸载,销毁容器时,对象就被销毁了
  • 当scope取值为prototype的时候

    <?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="userDao" class="com.kang.impl.UserDaolmpl" scope="prototype"></bean>
    
    </beans>
    

    Bean的实例化个数:多个

    Bean的实例化时机:当调用getBean()方法时,实例化Bean

    package com.kang.test;
    
    import com.kang.UserDao;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class SpringTest {
        @Test
        public void test01(){
            ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
            //当程序执行完这条代码,也就是读取完xml配置文件,对象就被创建,而且多次创建的对象为不同个对象
            UserDao userDao1 = (UserDao) app.getBean("userDao");
            UserDao userDao2 = (UserDao) app.getBean("userDao");
            System.out.println(userDao1);
            System.out.println(userDao2);
        }
    }
    

    在这里插入图片描述

    Bean的生命周期:

    • 对象创建:当使用对象时,创建新的对象实例
    • 对象运行:只要对象在使用中,就一直活着
    • 对象销毁:对象长时间不使用,就会被JAVA的垃圾回收器回收了

2、Bean实例化三种方式

Bean实例化的三种方式:

  • 无参构造方法实例化
  • 工厂静态方法实例化
  • 工厂实例方法实例化

2.1、无参构造方法实例化

 <bean id="userDao" class="com.kang.impl.UserDaolmpl"></bean>

上述测试代码中所有的Bean实例化均为无参构造方法


2.2、工厂静态方法实例化

public class UserDaolmplFactory {
    public static UserDaolmpl CreateUserDao(){
        return new UserDaolmpl();
    }
}
<bean id="userDao" class="com.kang.factory.UserDaolmplFactory" factory-method="CreateUserDao"></bean>

只需要在xml文件中,用factory-method告诉spring框架这是一个工厂模式并且工程的方法是CreateUserDao,那么spring框架仍然会返回一个Bean的实例化

spring框架会先找到com.kang.factory.UserDaolmplFactory,然后调用CreateUserDao这个静态方法,即可返回一个UserDao对象

并且java代码不需要有任何修改

在这里插入图片描述


2.3、工厂实例方法实例化

在工厂静态方法实例化的实现中,由于工厂里的方法是静态的,所以不需要创建工厂实例化对象,但是在如果工厂创建对象的方法不是静态的,那应该怎么办?


<bean id="factory" class="com.kang.factory.UserDaolmplFactory"></bean>

<bean id="userDao" factory-bean="factory" factory-method="CreateUserDao"></bean>
  • 首先先创建id为factory的bean,让它返回一个工厂的对象
  • 然后创建一个id为userDao的bean,在当中指明factory-bean(工厂的bean)的id,然后还有工厂创建对象的方法
  • 同样,Java代码不需要修改

在这里插入图片描述


3、Bean生命周期配置

Bean可以由程序猿指定初始化和销毁的方法,只需要在xml配置文件的对应bean中加入以下标签

  • init-method:指定类中的初始化方法名称
  • destroy-method:指定类中的销毁方法名称
<bean id="userDao" class="com.kang.impl.UserDaolmpl" init-method="init" destroy-method="destroy"></bean>
package com.kang.impl;

import com.kang.UserDao;


public class UserDaolmpl implements UserDao {

    public UserDaolmpl(){
        System.out.println("创建对象");
    }

    @Override
    public void save() {
        System.out.println("save running......");
    }

    //初始化方法
    public void init(){
        System.out.println("初始化。。。。");
    }

   //销毁方法
    public void destroy(){
        System.out.println("销毁.....");
    }
}

测试代码

public class SpringTest {
    @Test
    public void test01(){
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        
        UserDao userDao1 = (UserDao) app.getBean("userDao");
        
        System.out.println(userDao1);
        
        ((ClassPathXmlApplicationContext)app).close();
    }
}

在这里插入图片描述


4、依赖注入

问题引入:

  1. 创建 UserService,UserService 内部在调用 UserDao的save() 方法
public class UserServiceImpl implements UserService {
    @Override
    public void save() {
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao userDao = (UserDao) app.getBean("userDao");
        userDao.save();
    }
}
  1. 将 UserServiceImpl 的创建权交给 Spring

    <bean id="userDao" class="com.kang.impl.UserDaolmpl"></bean>
        <bean id="userService" class="com.kang.impl.UserServiceImpl"></bean>
    
  2. 从 Spring 容器中获得 UserService 进行操作

 @Test
    public void test02(){
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService = (UserService) app.getBean("userService");
        userService.save();
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gT469oAN-1645704192217)(Spring入门.assets/image-20220224093008916.png)]

上述做法是将UserService实例和UserDao都存在spring容器中,然后再容器外部获取UserService实例和UserDao实例,然后在程序中进行结合

在这里插入图片描述

这当中存在的问题是:加载配置文件的时候,不需要getBean方法,配置文件的内容都被执行了,导致配置文件加载了多次,浪费资源

在test中,只需要UserService,但是UserDao也实例化了

因为UserService和UserDao都在Spring容器中,而最终程序直接使用的是UserService,所以可以在 Spring容器中,将UserDao设置到UserService内部。

在这里插入图片描述

要解决这个问题,就需要用到依赖引入

在这里插入图片描述


4.1、依赖引入的方式

通过构造方法和set方法实现将UserDao注入到UserService内部


4.1.1、set方法注入

set方法注入的前提,是要在UserServiceImpl里定义一个私有变量UserDao

然后通过set方法给该私有变量赋值

public class UserServiceImpl implements UserService {
    private UserDao userDao;
    @Override
    public void save() {
        userDao.save();
    }

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
}
    <bean id="userDao" class="com.kang.impl.UserDaolmpl"></bean>
    <bean id="userService" class="com.kang.impl.UserServiceImpl">
        <!--第一个userDao是指set方法后面的UserDao, 既setUserDao-->
        <!--第二个userDao 是指上面的id的userDao的Bean实例化返回的UserDao对象-->
        <property name="userDao" ref="userDao"/>
    </bean>

注意:虽然两个userDao写法一样,但是两个userDao所代表的意思并不一样,注意区分

set方法注入还可以用P空间命名注入

首先引入P空间命名空间:

xmlns:p="http://www.springframework.org/schema/p"

接着,修改注入方式:

<bean id="userService" class="com.kang.impl.UserServiceImpl" p:userDao-ref="userDao">
        <!--第一个userDao是指set方法后面的UserDao(首字母大写换小写), 既setUserDao-->
        <!--第二个userDao 是指上面的id的userDao(对象引用)-->
        <!--<property name="userDao" ref="userDao"/>-->
    </bean>

spring的XML配置文件如下:

<?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:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--<bean id="factory" class="com.kang.factory.UserDaolmplFactory"></bean>-->
    <!--<bean id="userDao" factory-bean="factory" factory-method="CreateUserDao"></bean>-->
    <!--<bean id="userDao" class="com.kang.impl.UserDaolmpl" init-method="init" destroy-method="destroy"></bean>-->

    <bean id="userDao" class="com.kang.impl.UserDaolmpl"></bean>
    <bean id="userService" class="com.kang.impl.UserServiceImpl" p:userDao-ref="userDao">
        <!--第一个userDao是指set方法后面的UserDao, 既setUserDao-->
        <!--第二个userDao 是指上面的id的userDao-->
        <!--<property name="userDao" ref="userDao"/>-->
    </bean>

</beans>

4.1.2、通过构造方法注入

创建有参构造方法

package com.kang.impl;

import com.kang.dao.UserDao;
import com.kang.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @ClassName UserServiceImpl
 * @Description TODO
 * @Author kang
 * @Date 2022/2/24 上午 9:22
 * @Version 1.0
 */
public class UserServiceImpl implements UserService {
    private UserDao userDao;

    public UserServiceImpl(UserDao userDao) {
        this.userDao = userDao;
    }

    public UserServiceImpl() {
    }

    @Override
    public void save() {
        userDao.save();
    }

}

配置spring的xml配置文件

<bean id="userDao" class="com.kang.impl.UserDaolmpl"></bean>
    <bean id="userService" class="com.kang.impl.UserServiceImpl" >
        <!--第一个userDao是指有参构造方法的参数-->
        <!--第二个userDao是指引用对象,即上面的id属性-->
        <constructor-arg name="userDao" ref="userDao"></constructor-arg>
</bean>

Java的测试类代码依然不用变

在这里插入图片描述


5、Bean的依赖注入的数据类型

Bean的依赖注入的数据类型有很多种,除了上面的对象还支持普通数据类型,集合等可以在容器中进行注入

注入的三种基本数据类型

  • 普通数据类型
  • 引用数据类型
  • 集合数据类型

上述对对象的操作就是对引用数据类型的依赖注入


5.1、普通数据类型的注入

public class UserServiceImpl implements UserService {
    private String name;
    private int age;

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public void save() {
        System.out.println("name = " + name);
        System.out.println("age = " + age);
    }

}
    <bean id="userService" class="com.kang.impl.UserServiceImpl">
        <property name="name" value="小明"></property>
        <property name="age" value="18"></property>
    </bean>

在这里插入图片描述

注意:ref 和 value的使用场景不一样

  • ref:对象引用
  • value:普通数据

5.2、集合数据类型(List< String >)的注入

package com.kang.impl;

import com.kang.dao.UserDao;
import com.kang.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.List;

public class UserServiceImpl implements UserService {
    List<String> list;

    public void setList(List<String> list) {
        this.list = list;
    }

    @Override
    public void save() {
        System.out.println(list);
    }

}
    <bean id="userService" class="com.kang.impl.UserServiceImpl">
        <property name="list">
            <list>
                <value>华为</value>
                <value>小米</value>
                <value>苹果</value>
            </list>
        </property>
    </bean>

在这里插入图片描述

上述是集合中为普通数据类型的案例


5.3、集合数据类型(List< User >)的注入

package com.kang.poj;

/**
 * @ClassName User
 * @Description TODO
 * @Author kang
 * @Date 2022/2/24 下午 4:29
 * @Version 1.0
 */
public class User {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
package com.kang.impl;

import com.kang.poj.User;
import com.kang.service.UserService;

import java.util.List;

public class UserServiceImpl implements UserService {
    List<User> list;

    public void setList(List<User> list) {
        this.list = list;
    }

    @Override
    public void save() {
        System.out.println(list);
    }

}
    <bean id="user1" class="com.kang.poj.User">
        <property name="name" value="小红"></property>
        <property name="age" value="18"></property>
    </bean>

    <bean id="user2" class="com.kang.poj.User">
        <property name="name" value="小明"></property>
        <property name="age" value="20"></property>
    </bean>

    <bean id="userService" class="com.kang.impl.UserServiceImpl">
        <property name="list">
            <list>
                <ref bean="user1"/>
                <ref bean="user2"/>
            </list>
        </property>
    </bean>

在配置文件中首先先要配置两个bean实例化的对象,然后将他们放到集合中


5.4、集合数据类型(Map< String, User >)的注入

将5.3的List集合改为Map集合,接着spring的XML文件配置修改为以下

    <bean id="userService" class="com.kang.impl.UserServiceImpl">
        <property name="list">
            <map>
                <entry key="第一个人" value-ref="user1"/>
                <entry key="第二个人" value-ref="user2"/>
            </map>
        </property>
    </bean>

在这里插入图片描述


5.5、集合数据类型(Properties)的注入

package com.kang.impl;

import com.kang.poj.User;
import com.kang.service.UserService;

import java.util.Map;
import java.util.Properties;

/**
 * @ClassName UserServiceImpl
 * @Description TODO
 * @Author kang
 * @Date 2022/2/24 上午 9:22
 * @Version 1.0
 */
public class UserServiceImpl implements UserService {
    private Properties properties;

    public void setProperties(Properties properties) {
        this.properties = properties;
    }

    @Override
    public void save() {
        System.out.println(properties);
    }

}
    <bean id="userService" class="com.kang.impl.UserServiceImpl">
        <property name="properties">
            <props>
                <prop key="p1">aaa</prop>
                <prop key="p2">bbb</prop>
                <prop key="p3">ccc</prop>
            </props>
        </property>
    </bean>

在这里插入图片描述


6 、引入其他配置文件

像上面这些配置文件数据要是写在一个配置中会显得这个spring配置文件特别乱

因此,我们可以将部分配置拆分到其他配置文件中,最后通过spring的import标签进行加载

这一有利于分模块开发

命名格式:applicationContext-xxx.xml

<import resource="applicationContext-xxx.xml"/>

7、spring的重点配置(*)

在这里插入图片描述


四、Spring相关的API

1、ApplicationContext的实现类

ApplicationContext的实现类有三种

  1. ClassPathXmlApplicationContext

    它是从类的根路径下加载配置文件 推荐使用这种

  2. FileSystemXmlApplicationContext

    它是从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置。使用该类的时候需要指明配置文件的全路径

  3. AnnotationConfigApplicationContext

    当使用注解配置容器对象时,需要使用此类来创建 spring 容器。它用来读取注解。


2、getBean()方法使用

getBean方法是用来返回Bean实例化的对象,方法重载了两个

public Object getBean(String name) throws BeansException {
	assertBeanFactoryActive();
	return getBeanFactory().getBean(name);
}

public <T> T getBean(Class<T> requiredType) throws BeansException {
	assertBeanFactoryActive();
	return getBeanFactory().getBean(requiredType);
}
    public void test02(){
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        // UserService userService = (UserService) app.getBean("userService");
        UserService userService = app.getBean(UserService.class);
        userService.save();
    }

注意:

  • 第一种用法适用于任何情况

  • 第二种用法只适用于id对应的类只有一个的情况,像下面这种情况这无法使用第二种用法,否则会报错,因为程序不知道对应哪一个id

        <bean id="user1" class="com.kang.poj.User">
            <property name="name" value="小红"></property>
            <property name="age" value="18"></property>
        </bean>
    
        <bean id="user2" class="com.kang.poj.User">
            <property name="name" value="小明"></property>
            <property name="age" value="20"></property>
        </bean>
    

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/95023.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!