JavaEE学习笔记3——Spring

  • Post author:
  • Post category:java



JavaEE学习笔记3

对应代码

地址




Note for JavaEE-Day3



关于Spring

Spring是针对复杂的EJB最早于2002提出的JavaEE设计开发工具。其基本结构可以表示为下图:




Figure 1



Spring优势

  • Spring在企业级开发中占有率很高,大于90%
  • Spring可以简化企业级应用开发
  • Spring可以有效整合其他技术来促进开发



Spring生态

  • SpringFramework: 框架核心,其他技术的基础
  • SpringBoot: 超热门的简化spring开发工具
  • SpringCloud: 为分布式应用所提出的微服务框架



Spring控制反转



松/紧耦合编程

这里的耦合即程序中连个模块的相互关联程度。紧耦合编程模块之间的相关度高,维护成本大;松耦合编程模块之间的关联少,而通过接口联系,即在欲关联的模块外部设置依赖关系。

一个松耦合的例子是一个类中某属性为另一个类,不在这个类的业务层new另一个类,而是通过在外部新生成这两个类的对象,再通过set方法设置属性。



Spring控制反转容器

在实例的创建和初始化中,IOC容器中的实例被称为beans,依赖注入会在bean之间进行。



创建Spring工程

这里介绍使用maven创建spring工程,分为如下步骤:

  1. 创建maven工程,并向

    pom.xml

    中添加SpringFramework依赖,添加后更新maven插件。

    例如:
<dependencies>
    <!-- 添加SpringFramework -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.2.10.RELEASE</version>
    </dependency>
    <!-- 添加junit -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>
</dependencies>
  1. 在资源文件夹中添加spring配置文件

    applicationContext.xml

  2. 创建java类,并在spring配置文件中声明bean,参考代码如下:
    <!--2.配置bean-->
    <!--bean标签标示配置bean
    id属性标示给bean起名字
    class属性表示给bean定义类型-->
    <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
    <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
        <!--7.配置server与dao的关系-->
        <!--property标签表示配置当前bean的属性
        name属性表示配置哪一个具体的属性
        ref属性表示参照哪一个bean-->
        <property name="bookDao" ref="bookDao"/>
    </bean>
  1. 启动IOC容器,使用bean启动方法,参考代码如下:
public static void main(String[] args) {
    // 3.获取IoC容器
    ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    // 4.获取bean(根据bean配置id获取)
    // BookDao bookDao = (BookDao) ctx.getBean("bookDao");
    // bookDao.save();
    BookService bookService = (BookService) ctx.getBean("bookService");
    bookService.save();
}



bean的生命周期



Scope of beans

scope是声明bean时的一个可选参数,取值为

singleton



prototype

,默认为前者。前者标注的bean在控制反转生成实例时,多次调用返回的是同一实例,即引用地址相同。而后者标注的bean会生成多个不同的实例,即引用地址不同。

特别指出,我在这里翻看了spring源码,其中有

beanFactory.preInstantiateSingletons();

这样一个方法,spring会逐个bean检查,对于

singleton

对应的bean,它会预先实例化。所以这就有了后面使用bean实例化bookDao也调用bookService的初始化方法。



使用Factory实例化

使用bean实例化有以下四种方法:

    <!--方式一:构造方法实例化bean-->
    <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
    <!--方式二:使用静态工厂实例化bean-->
    <bean id="orderDao" class="com.itheima.factory.OrderDaoFactory" factory-method="getOrderDao"/>
    <!--方式三:使用实例工厂实例化bean-->
    <bean id="userFactory" class="com.itheima.factory.UserDaoFactory"/>
    <bean id="userDao" factory-method="getUserDao" factory-bean="userFactory"/>
    <!--方式四:使用FactoryBean实例化bean-->
    <bean id="userDao2" class="com.itheima.factory.UserDaoFactoryBean"/>

关于这四种方法的解释如下:

  • 方法一: 朴素方法,与前面创建spring工程中的启动IOC容器一致。
  • 方法二: 本质上就是在

    OrderDaoFactory

    类中有一个静态的

    getOrderDao

    方法,在这个方法中返回新实例化的

    boookDao
  • 方法三: 与方法二相比

    getUserDao

    不是静态方法,但仍返回新实例化的

    boookDao

    。第一句bean的声明为声明factory,第二句为声明factory的方法。
  • 方法四: 类

    UserDaoFactoryBean

    使用接口

    FactoryBean

    ,类内部有新实例化

    boookDao

    的方法。



初始化方法与销毁方法

可以在声明bean时加入

init-method



destroy-method

参数,其指向类的对应方法将分别在bean实例化对象的初始化阶段和销毁阶段调用,后者只适用于单例(

singleton

)对象。实例代码为:

<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl" init-method="init" destroy-method="destory"/>



InitializingBean与DisposableBean接口

bean提供有InitializingBean与DisposableBean接口可覆写其中方法,其调用与

init-method/destroy-method

相似。示例如下:

    @Override
    public void destroy() throws Exception {
        System.out.println("service destroy");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("service init");
    }



依赖注入

我所理解的依赖注入就是设置bean对应类中的属性(基本类型或引用类型),其有如下几种方法。



通过setter注入

所谓setter就是对应类中一个设置类中属性的方法,而通过其注入只需要在对应bean中进行property配置即可。

<!--注入简单类型-->
    <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
        <!--property标签:设置注入属性-->
        <!--name属性:设置注入的属性名,实际是set方法对应的名称-->
        <!--value属性:设置注入简单类型数据值-->
        <property name="connectionNum" value="100"/>
        <property name="databaseName" value="mysql"/>
    </bean>

    <bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>

    <!--注入引用类型-->
    <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
        <!--property标签:设置注入属性-->
        <!--name属性:设置注入的属性名,实际是set方法对应的名称-->
        <!--ref属性:设置注入引用类型bean的id或name-->
        <property name="bookDao" ref="bookDao"/>
        <property name="userDao" ref="userDao"/>
    </bean>



通过构造方法注入

不同于调用setter方法,还可以通过构造方法设置属性。具体方法是使用

constructor-arg

标签替代

property

标签,

name

参数指示形参名称,从而根据参数名称注入依赖。形式如下:

    <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
        <!--根据构造方法参数名称注入-->
        <constructor-arg name="connectionNum" value="10"/>
        <constructor-arg name="databaseName" value="mysql"/>
    </bean>
    <bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>

    <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
        <constructor-arg name="userDao" ref="userDao"/>
        <constructor-arg name="bookDao" ref="bookDao"/>
    </bean>

这里的

name

参数可以替换为

type



index

,前者指示根据参数类型注入,后者指示根据参数位置(索引)注入。



为集合属性添加依赖

针对典型的集合属性如数组、list、set、map、properties,其添加依赖形式与传统形式相似,使用对应标签指示集合内容即可,形如:

<!--数组注入,int类型-->
<property name="array">
    <array>
        <value>100</value>
        <value>200</value>
    </array>
</property>
<!--list集合注入,string类型-->
<property name="list">
    <list>
        <value>itcast</value>
        <value>boxuegu</value>
    </list>
</property>



自动注入依赖

自动注入依赖不需要手动注入属性,在对应bean中加入

autowire

参数即可,形式如下:

<!--autowire属性:开启自动装配,通常使用按类型装配-->
<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl" autowire="byName"/>


autowire

参数值可选

byType



byName

,前者将会寻找与被注入bean的setter中参数类型相同的bean进行注入(多个相同会抛出

NoUniqueBeanDefinitionException

异常),后者将会寻找与被注入bean的setter方法名所对应的bean进行注入(如果没找到就不注入)。



IOC容器



IOC容器类




Figure 2

IOC容器中类的接口与继承关系如Figure 2所示,由其可见我们常用的

ApplicationContext

类继承自

BeanFacory

类,而其他常用的类如

ClassPathXmlApplicationContext



FileSystemXmlApplicationContext

都是调用了

ApplicationContext

接口,其使用方法如下:

 //1.加载类路径下的配置文件
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

//2.从文件系统下加载配置文件
ApplicationContext ctx = new FileSystemXmlApplicationContext(
"D:\\workspace\\spring_10_container\\src\\main\\resources\\applicationContext.xml");



获取Bean

获取bean有三种方法,分别是通过bean的名字、生成方法以及类型,其代码如下:

 //1. getBean by Name
        BookDao bookDao = (BookDao) ctx.getBean("bookDao");
 
//2. getBean by Name(Generic method)
        BookDao bookDao = ctx.getBean("bookDao",BookDao.class);
 
//3. getBean by Type
        BookDao bookDao = ctx.getBean(BookDao.class);



Spring注解

这里主要介绍ppt中对应的注解:


  1. @Configuration

    。声明当前类为spring配置类,而后可以用IOC容器类

    AnnotationConfigurationContext((配置类名).class)

    加载该配置类以初始化spring容器。

  2. @ComponetScan({})

    。注解于spring配置类前,用以设置bean扫描路径,多个路径写为字符串数组格式。

  3. @Component

    。用以实现bean的注入,即声明bean,从而使其可以被spring扫描或实例化。

  4. @Scope("")

    。设置bean的声明周期,

    singleton



    prototype


  5. @PostConstruct

    。设置bean的初始化方法。

  6. @PreDestroy

    。设置bean的销毁方法。

  7. @Bean("")

    。注解bean中方法,相当于实例化工厂实例化bean。

  8. @Autowired

    。可注解于字段、初始化方法以及set方法,以自动注入依赖。

  9. @Qualifier("")

    。注解于

    @Autowired

    后字段或方法前,用于按名字注入。

  10. @PropertySource({""})

    。设置资源文件扫描路径。

  11. @Value("${资源文件中的变量名}")

    。设置属性注入。

  12. @Controller

    。指示bean是springMVC中的一个controller。

  13. @Service

    。指示bean是一个service。

  14. @Repository

    。指示bean是在SpringData中的一个库。



版权声明:本文为vermouth_1412原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。