Spring入门笔记1

  • 零 l 
  • 一 l 
  • 二 l 
  • (一)下载解压
  • (二)提取需要的文件到一个文件夹中
  • (三)导入到项目中
  • (四)依赖注入(DI)是什么意思
  • 三 l 
  • (一)介绍
  • (二)BeanFactory和ApplicationContext对比
  • 四 l 
  • (一)装配Bean的三种方式
  • (二)bean的作用域
  • (三)bean的生命周期(了解)
  • 五 l 
  • (一)手动装配,使用xml配置
  • (二)SpEL表达式【了解】
  • (三)集合注入(给集合注入数据)
  • 六 l 
  • 七 l 
  • (一)对IoC理解
  • (二)对本文的总结





IDE:

IntelliJ IDEA 2020.2



零 l 


1、以初学者的视角记录笔记
2、课程链接
4、实操很重要!!!
5、本文主讲控制反转(IoC)




一 l 


Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。

控制反转(IoC):本来是在程序内new的对象,交由Spring进行创建


Spring 体系结构:

springboot ActivitiModeler字体不生效 spring的各种字体_加载



Spring在项目中的架构:

springboot ActivitiModeler字体不生效 spring的各种字体_java_02







二 l 


(一)下载解压

1、下载Spring并解压:
  教程链接   下载链接
2、下载commons-logging-1.x-bin.zip并解压

(二)提取需要的文件到一个文件夹中

1、在spring-framework-x.x.x.RELEASE文件夹中的libs文件夹中取出其中的4个核心jar包

jar包名

作用

spring-core-x.x.x.RELEASE.jar

包含Spring框架基本的核心工具类,Spring其它组件要都要使用到这个包里的类,是其它组件的基本核心。

spring-beans-x.x.x.RELEASE.jar

所有应用都要用到的,它包含访问配置文件、创建和管理bean以及进行Inversion of Control(IoC) / Dependency Injection(DI)操作相关的所有类

spring-context-x.x.x.RELEASE.jar

Spring提供在基础IoC功能上的扩展服务,此外还提供许多企业级服务的支持,如邮件服务、任务调度、JNDI定位、EJB集成、远程访问、缓存以及各种视图层框架的封装等。

spring-expression-x.x.x.RELEASE.jar

Spring表达式语言


2.2.在commons-logging-1.x文件夹中提取commons-logging-1.x.jar(与课程中jar包名字不一样没关系)

(三)导入到项目中

1、

springboot ActivitiModeler字体不生效 spring的各种字体_spring_03


2、

springboot ActivitiModeler字体不生效 spring的各种字体_java_04



(四)依赖注入(DI)是什么意思

依赖注入相当于在配置文件中执行了一次set方法(需要实现set方法)

<!-- 配置一个bean 【对象】-->
    <bean id="userService" class="com.gyf.service.UserService">
        <!-- 依赖注入数据,调用属性的set方法 -->
        <property name="name" value="qwe"></property>
    </bean>

spring内部创建对象的原理:反射
  1.解析xml文件,获取类名,id,属性
  2.通过反射,用类型创建对象
  3.给创建的对象赋值




三 l 


Spring通过xml配置文件,加载Bean(Bean似于类的实例),从而实现对Bean的统一控制。

现在可以粗略的理解为 .xml配置文件加载的东西 就是 Spring容器

加载配置 比 配置Bean 简单点,所以放在第三部分。

(一)介绍

1、spring的配置文件放在src目录下(相对路径)【最常用】

ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");


2、文件系统路径获得配置文件(绝对路径)

ApplicationContext context = new FileSystemXmlApplicationContext("绝对路径");


3、使用BeanFactory【了解】【过时方法】

BeanFactory factory = new XmlBeanFactory(new FileSystemResource("绝对路径"));

(二)BeanFactory和ApplicationContext对比

1、BeanFactory 第一次getBean时才会初始化Bean【延迟加载】

2、ApplicationContext 是对BeanFactory扩展,提供了更多功能【即时加载】
(加载配置的文件之后即刻加载类)
  (1)国际化处理
  (2)事件传递
  (3)Bean自动装配
  (4)各种不同应用层的Context实现




四 l 


知道了怎么加载Spring容器,接下来就要学着配置 Bean的设置 了。

(一)装配Bean的三种方式

1、new 对象,class 是实例类

<bean id="userService1" class="com.gyf.service.UserServiceImpl"></bean>

2、静态工厂,使用工厂类的静态方法 new 对象

<bean id="userService2" class="com.gyf.service.UserSereviceFactory1" factory-method="createUserService"></bean>

3、实例工厂,new 一个工厂类,再调用工厂方法 new 对象,factory-bean:工厂实例

<bean id="factory2" class="com.gyf.service.UserSereviceFactory2"></bean>
<bean id="userService3" factory-bean="factory2" factory-method="createUserService"></bean>

(二)bean的作用域

类别

说明

singleton(默认)

在Spring IoC容器中仅存在一个Bean实例,Bean以单例方式存在,默认值

prototype

每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时 ,相当于执行new XxxBean()

request

每次HTTP请求都会创建一个新的Bean,该作用域仅适用于WebApplicationContext环境

session

同一个HTTP Session 共享一个Bean,不同Session使用不同Bean,仅适用于WebApplicationContext 环境

globalSession

一般用于Portlet应用环境,该作用域仅适用于WebApplicationContext 环境


prototypre使用例子:

<bean id="userService" class="com.gyf.service.UserService" scope="prototype"></bean>

(三)bean的生命周期(了解)

springboot ActivitiModeler字体不生效 spring的各种字体_java_05

1、instantiate bean对象实例化【new对象】
2、populate properties 封装属性【调用set方法赋值】
3、如果Bean实现BeanNameAware 执行 setBeanName【设置bean名】
4、如果Bean实现BeanFactoryAware 执行setBeanFactory ,获取Spring容器【把对象放进工厂,放进容器】
5、如果存在类实现 BeanPostProcessor,执行preProcessBeforeInitialization【批量预处理】
6、如果Bean实现InitializingBean 执行 afterPropertiesSet 【属性赋值完成】
7、调用 指定初始化方法 init【调用自定义初始化方法】(init-method属性)
8、如果存在类实现 BeanPostProcessor(处理Bean) ,执行postProcessAfterInitialization
执行业务处理【批量后处理】
9、如果Bean实现 DisposableBean 执行 destroy【调用销毁bean容器方法】(需要手动关闭容器)

context.getClass().getMethod("close").invoke(context);

10、调用 指定销毁方法 customerDestroy【调用自定义销毁方法】(destroy-method属性)


5和8单独处理的例子,对所有bean都有效:

// MyBeanPostProcessor.java
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        //这边可以用于多个对象共同的事情的处理
        System.out.println("5:预处理:" + bean + ":" + beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("8:后处理:" + bean + ":" + beanName);
        return bean;
    }
}

// beans.xml
<bean id="beanProcess" class="com.gyf.model.MyBeanPostProcessor"></bean>





五 l 


通过第四部分的学习,现在可以构造一个Bean(实例)。

接下来,就可以想着能不能顺便给Bean赋初值。

(一)手动装配,使用xml配置

1、构造方法注入1

<bean id="stu" class="com.gyf.model.Student">
	<!-- 相当调用 public Student(String username, String password) 构造方法 -->
	<!-- name:构造属性名; value:数值 -->
	<constructor-arg name="username" value="qwe"></constructor-arg>
	<constructor-arg name="password" value="1"></constructor-arg>
</bean>


2、构造方法注入2

<!-- 通过索引加类型 给构造方法赋值 -->
    <bean id="stu" class="com.gyf.model.Student">
        <constructor-arg index="0" value="qwe" type="java.lang.String"></constructor-arg>
        <constructor-arg index="1" value="2" type="int"></constructor-arg>
    </bean>


3、属性setter方法注入

<!-- 2.通过set方法往bean注入属性值 -->
    <bean id="stu" class="com.gyf.model.Student">
        <property name="username" value="qwe"></property>
        <property name="password" value="3"></property>
        <property name="age" value="3"></property>
    </bean>


4、p命名空间注入【了解】

<!-- xmlns xml namespace:xml命名空间,注意xmlns:p这一行 -->
<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">

<!-- 3.通过p命名空间注入 -->
    <bean id="stu" class="com.gyf.model.Student"
          p:username="qwe" p:password="4" p:age="4"></bean>

(二)SpEL表达式【了解】

Spring 表达式:对<property>进行统一编程,所有的内容都使用value

表达式

意义

#{123}、#{‘jack’}

数字、字符串

#{beanId}

另一个bean引用

#{beanId.propName}

操作数据

#{beanId.toString()}

执行方法

#{T(类).字段|方法}

静态方法或字段

(三)集合注入(给集合注入数据)

集合的注入都是给<property>添加子标签

集合类型

子标签

数组

<array>

List

<list>

Set

<set>

Map

<map> ,map存放k/v 键值对,使用<entry>描述

Properties

<props> <prop key="">value</prop>

普通数据

<value>

引用数据

<ref>

例子:

<bean id="programmer" class="com.gyf.model.Programmer">
    <!-- list类实例cars -->
    <property name="cars">
        <list>
            <value>ofo</value>
            <value>mobai</value>
            <value>宝马</value>
        </list>
    </property>

    <!-- set类实例pats -->
    <property name="pats">
        <set>
            <value>小黑</value>
            <value>小黄</value>
            <value>小白</value>
        </set>
    </property>


    <!-- map类实例infos -->
    <property name="infos">
        <map>
            <entry key="name" value="qwe"></entry>
            <entry key="age" value="1"></entry>
            <entry key="ip" value="127.0.0.1"></entry>
        </map>
    </property>

    <!--Properties类实例mysqlInfos(数据库连接信息) -->
    <property name="mysqlInfos">
        <props>
            <prop key="url">mysql:jdbc://localhost:3306/dbname</prop>
            <prop key="user">root</prop>
            <prop key="password">123456</prop>
        </props>
    </property>
</bean>





六 l 


在xml中配置好像过于繁琐了,通过一步步的学习,已经了解了各种方法。

最后,通过 注解 返璞归真的同时,更进一步减少代码量。

现在,试试回到 java代码 中去配置。

1、注解注入的准备
(1)把spring-framework-x.x.x.RELEASE文件夹中的libs文件夹中取出spring-aop-x.x.x.RELEASE.jar到之前的包文件夹里。(不然可能会报NoClassDefFoundError的错误)
(2)在xml配置文件中的beans添加成如下样式(重点看第3、6、7行);再添加两行注解代码。

<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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context.xsd">
    <!-- 开启注解-->
    <context:annotation-config/>

    <!-- 注解的位置-->
    <context:component-scan base-package="com.gyf"/>
</beans>


2、基本spring注解
注解:就是一个类
使用方式:在实现类或接口前一行添加 “@注解名称”(在接口前添加会自动找实现类)
为什么使用:开发中使用注解取代 xml 配置文件。

注解

等价bean定义

@Component

<bean class=“类”>

@Component(“id”)

<bean id=“别名” class=“类”>

tips:
(1)如果@Component没配置id,可以通过类获取:
  

IUserService service = (IUserService) context.getBean(IUserServiceImpl.class);   有id使用:
   IUserService service = (IUserService) context.getBean("id");

例子:

// UserDaoImpl.java
@Component
public class User{
}

等价于

<!-- beans.xml -->
<bean id="userService" class="com.qwe.service.User">


3、在web开发中产生的衍生
阿里巴巴开发手册中有请求处理层(Web层)、业务逻辑层(Service层)、通用逻辑层(Manager层)、数据持久层(DAO层)

层级

对应注解

Web层

@Controller(“名称”)

Service层

@Service(“名称”)

DAO层

@Repository(“名称”)

(1)以上三个注解的用法与@Component相同
(2)为什么会有衍生:保证生成的顺序从DAO层->Service层->Web层


4、其他注解

其他注解

功能

@Autowired

自动 根据类型 注入 同类型Bean(需要存在)。一般只用这个,不用下两个

@Qualifier(“名称”)

指定自动注入的id名称【指定Bean】

@Resource(“名称”)

等于@Autowired加@Qualifier(“名称”)

@ PostConstruct

自定义初始化。相当于bean属性 init-method=“方法名”

@ PreDestroy

自定义销毁。相当于bean属性 destroy-method=“方法名”

@Scope(“作用域”)

设置bean的作用域。相当于bean属性 scope=“作用域”


5、例子
(1)不使用注解的例子
java文件:

// DAO层 UserDao.java
public class UserDao implements IUserDao{
    @Override
    public void add(User user) {}
}

// service层 UserService.java
public class UserService implements IUserService {
    private IUserDao userDao;
    
    @Override
    public void add(User user) {
        //调用dao
        userDao.add(user);
    }
    
    public IUserDao getUserDao() { return userDao; }

    public void setUserDao(IUserDao userDao) { this.userDao = userDao; }
}

// web层 UserAction.java
public class UserAction{
    private IUserService userService;

    public void save(User user){
        userService.add(user);
    }

    public IUserService getUserService() { return userService; }

    public void setUserService(IUserService userService) { this.userService = userService; }
}

xml配置文件:

<!-- 1.配置dao-->
    <bean id="userDao" class="com.gyf.dao.UserDao"></bean>

    <!-- 2.配置service -->
    <bean id="userService" class="com.gyf.service.UserService">
        <property name="userDao" ref="userDao"></property>
    </bean>

    <!--3.配置action-->
    <bean id="userAction" class="com.gyf.web.action.UserAction">
        <property name="userService" ref="userService"></property>
    </bean>

程序调用userAction.save()->调用userService.add()->调用userDao.add()


(2)使用注解的例子
java文件:

// DAO层 UserDao.java 使用@Repository作为注解
@Repository
public class UserDao implements IUserDao{
    @Override
    public void add(User user) { System.out.println("dao 添加用户:" + user); }
}

// service层 UserService.java 使用@Service作为注解
@Service("myUserService")
public class UserService implements IUserService {
	@Autowired  // spring会自动注入userDao赋值,不用get和set方法了
    private IUserDao userDao;
    
    @Override
    public void add(User user) {
        //调用dao
        userDao.add(user);
    }
}

// web层 UserAction.java 使用@Controller作为注解
@Controller
public class UserAction{
    @Autowired  // spring自动注入userService赋值
    @Qualifier("myUserService")  // 根据指定的id注入属性
    // @Resource(name = "myUserService")  // 等价上面两个
    private IUserService userService;

    public void save(User user){
        System.out.println("action save方法 ");
        userService.add(user);
    }
}

xml配置文件:只需要开启注解




七 l 


(一)对IoC理解

假设有一个金字塔的三层结构,数据从顶到底流通,每一层都会有很多的类,除底层外每一层都依赖于下一层。

第一步:
 每实例化一个类的时候同时递归实例化底层的类。

优点:
 实现简单
缺点:
 每一层相同类的实例数据不互通且冗余,随着实例的增加,冗余线性提升

第二步:
 在金字塔额外创建一个工具(含多个类),专门管理金字塔中类的实例。

优点:
 方便管理与通信
缺点:
 这个工具的实现会极其的复杂

这种管理类的工具的控制方法就是控制反转(IoC)
spring可以很方便的使用类的实例而不用担心类之间的依赖

(二)对本文的总结

第二部分是快速入门

第三部分是加载xml配置

第四五六部分才是IoC的内容,其中又分为xml配置和注解配置

全文的重点应该在第六部分的注解配置上,注解配置相当于在xml中定义+依赖注入(第四五部分内容)