SSM框架 ----- spring学习笔记

161 阅读8分钟

1 spring简介

1.1 spring是什么?

Spring是分层Java SE/EE应用full-stack轻量级开源框架,以loC(Inverse Of Control)和AOP(Aspect Oriented Programming)为内核。

提供了展示层springMVC和持久层spring JDBCTemplate 以及业务事务管理等众多的企业级应用技术,还能整合开源框架和类库,逐渐成为使用最多的Java EE企业应用开源框架。

1.2 spring的优势

1) 方便解耦,简化开发
通过spring提供的loC容器,可以将对象间的依赖交由spring进行控制,避免硬编码的过度耦合。用户也不必为单例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。

2) AOP编程支持
 通过spring的AOP功能,方便进行面向切面编程,许多不容易用传统OOP实现的功能可以通过AOP轻松实现。

3) 声明式事务支持
 可以将我们从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活的进行事务管理,提升开发效率和质量。

4) 方便程序的测试
可以用非容器依赖的编程方式进行几乎所有的测试工作,测试不再是昂贵的操作,而是随手可做。

5) 方便集成优秀框架
Spring对各种优秀框架的支持。(struts、Hibernate、Hessian、Quart)

6) 降低JavaEE API的使用难度
Spring对JavaEE API(jdbc,javamail)进行薄薄的封装层,使这些API的使用难度大为降低

7) Java源码是经典学习范例
源代码设计巧妙、结构清晰、匠心使用,体现对Java设计模式的应用和Java技术的高深造诣。

1.3 spring的体系结构

image.png

2. spring快速入门

2.1 spring开发步骤

image.png

1) 导入spring开发的依赖:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.6.RELEASE</version>
</dependency>

2) 编写dao接口和实现类Bean

@Override
public void save() {
    System.out.println("=====save dao11111111 ==========");
}
  1. 创建spring核心配置文件applicationContext.xml
  1. 在spring配置文件中配置UserDaoImpl
<bean id="userDao" class="cn.hfnu.dao.impl.UserDaoImpl"></bean>
  1. 使用spring的API获得Bean实例 getBean
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao1 = (UserDao) app.getBean("userDao");
UserDao userDao2 = (UserDao) app.getBean("userDao");
System.out.println("=======userDao1=====>"+userDao1);
System.out.println("=======userDao2=====>"+userDao2);
userDao1.save();
userDao2.save();

3. spring配置文件

3.1 Bean标签基本配置

用于配置对象由spring来创建,默认情况它调用类中的无参构造函数
基本属性:
id: bean实例在spring容器的唯一标识
class: bean的全限定名

3.2 bean标签的范围配置

scope: 指对象的作用范围
singleton: 默认值,单例的
prototype: 多例的
request:web项目,spring创建bean对象,并将对象存入request域
session: web项目,spring创建bean对象,并将对象存入session域
global session: web项目中应用portlet环境,如果没有portlet环境那么globalsession相当于session
<bean id="userDao" class="cn.hfnu.dao.impl.UserDaoImpl" scope="singleton"></bean>

image.png

<bean id="userDao" class="cn.hfnu.dao.impl.UserDaoImpl" scope="prototype"></bean>

image.png

1) 当scope取值singleton时
bean的实例化个数:1个
bean实例化时机:spring核心配置文件applicationContext.xml被加载,实例化配置bean实例
bean的生命周期:
对象创建:当应用加载,创建容器时,对象被创建
对象运行:只要容器在,对象就一直活着
对象销毁:当应用卸载,销毁容器,对象被销毁
2) 当scope取值prototype时
bean的实例化个数:多个
bean实例化时机:当getbean()方法实例化bean
对象创建:当使用对象时,创建新的对象实例
对象运行:只要对象再使用中,对象一直活着
对象销毁:当对象长时间不用时,被java垃圾回收器回收

3.3 bean生命周期配置

init-method: 指定类中的初始化方法名称
destroy-method: 指定类中销毁方法名称
<bean id="userDao" class="cn.hfnu.dao.impl.UserDaoImpl" scope="singleton" init-method="init" destroy-method="destroy"></bean>
ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao1 = (UserDao) app.getBean("userDao");
UserDao userDao2 = (UserDao) app.getBean("userDao");
System.out.println("=======userDao1=====>"+userDao1);
System.out.println("=======userDao2=====>"+userDao2);
userDao1.save();
userDao2.save();
app.close();

3.4 bean实例化三种方式

1)无参构造实例化(重点)

//无参构造
public UserDaoImpl() {
    System.out.println("=========UserDaoImpl对象被创建=========");
}

2)工厂静态实例化

<bean id="userDao" class="cn.hfnu.fatory.StaticFactory" scope="singleton" factory-method="getUserDao"></bean>
public static UserDao getUserDao(){
    System.out.println("==========静态工厂=======");
    return new UserDaoImpl();
}

3)工厂实例化

<bean id="factory" class="cn.hfnu.fatory.DynamicFactory"></bean>
<bean id="userDao" factory-bean="factory" factory-method="getUserDao"></bean>

3.5 bean依赖注入分析

image.png

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

3.6  bean依赖注入的概念

依赖注入(Dependency Injection):它是spring容器核心的IoC具体实现。
将bean对象的实例存到spring容器中,从外部获得bean实例与程序进行结合,设置bean对象到spring容器中。

编写程序时,通过控制反转(Inverse of Controller),将对象创建交给了spring容器管理,IoC解耦只能降低他们的依赖关系,但不会消除。

将service层对象通过spring容器交给controller层,dao层对象交给service层,bean对象交到spring容器中就由spring容器来维护了。

3.7 bean的依赖注入

将userdao注入到userservice内部?

  1. 构造方法注入:
private UserDao userDao;

public UserServiceImpl() {
}

public UserServiceImpl(UserDao userDao) {
    this.userDao = userDao;
}
<bean id="userDao" class="cn.hfnu.dao.impl.UserDaoImpl"></bean>

<bean id="userService" class="cn.hfnu.service.impl.UserServiceImpl">
    <constructor-arg name="userDao" ref="userDao"></constructor-arg>
</bean>
  1. set方法注入:p命名空间注入本质也是set方法注入
<bean id="userDao" class="cn.hfnu.dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="cn.hfnu.service.impl.UserServiceImpl">
    <property name="userDao" ref="userDao"></property>
</bean>
private UserDao userDao;

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

需要引入P命名空间:

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

需要修改注入方式:

<bean id="userService" class="cn.hfnu.service.impl.UserServiceImpl" p:userDao-ref="userDao"/>

3.8 bean的依赖注入的数据类型

1)普通数据类型注入:

private String username;
private int age;
private String gender;

public void setUsername(String username) {
    this.username = username;
}

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

public void setGender(String gender) {
    this.gender = gender;
}
<bean id="userDao" class="cn.hfnu.dao.impl.UserDaoImpl">
    <property name="username" value="曹操"></property>
    <property name="age" value="20"></property>
    <property name="gender" value="男"></property>
</bean>

2)引用数据类型注入:

3)集合数据类型注入:

//集合
private List<String> list;
private Map<String, User> map;
private Properties properties;

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

public void setMap(Map<String, User> map) {
    this.map = map;
}

public void setProperties(Properties properties) {
    this.properties = properties;
}
<bean id="userDao" class="cn.hfnu.dao.impl.UserDaoImpl">
    <property name="list">
        <list>
            <value>诸葛亮</value>
            <value>曹操</value>
            <value>孙权</value>
        </list>
    </property>
    <property name="map">
        <map>
            <entry key="1001" value-ref="user1"></entry>
            <entry key="1002" value-ref="user2"></entry>
            <entry key="1003" value-ref="user3"></entry>
        </map>
    </property>
    <property name="properties">
        <props>
            <prop key="A001">aaa</prop>
            <prop key="A002">bbb</prop>
            <prop key="A003">bbb</prop>
        </props>
    </property>
</bean>

<bean id="user1" class="cn.hfnu.pojo.User">
    <property name="uid" value="1001"></property>
    <property name="username" value="zhangsan"></property>
    <property name="age" value="18"></property>
    <property name="pwd" value="123"></property>
</bean>
<bean id="user2" class="cn.hfnu.pojo.User">
    <property name="uid" value="1002"></property>
    <property name="username" value="lisi"></property>
    <property name="age" value="22"></property>
    <property name="pwd" value="123"></property>
</bean>
<bean id="user3" class="cn.hfnu.pojo.User">
    <property name="uid" value="1003"></property>
    <property name="username" value="wangwu"></property>
    <property name="age" value="20"></property>
    <property name="pwd" value="123"></property>
</bean>

3.9 引入其他配置文件

实际开发中spring的配置内容非常多,导致spring配置很繁杂且体积很大,所以可以将部分配置拆解到其他配置文件中,在spring主配置文件通过import标签进行加载。

<import resource="applicationContext_user.xml" />

4. spring相关的API

4.1 applicationcontext的继承体系

applicationcontext: 接口类型,代表应用上下文,可以通过其实例获得spring容器的bean对象

4.2 applicationcontext的实现类

image.png

4.3 getBean() 方法使用

当参数的数据类型是字符串时,表示bean的id从容器中获取bean实例,返回object需要强转。当参数数据类型是class类型,表示根据类型从容器中匹配bean实例,当容器中相同类型的bean有多个时,此方法会报错。

5 spring配置数据源

5.1 数据源(数据连接池)的作用

数据源是提高程序性能
事先实例化数据源,初始化部分连接资源
使用连接资源时从数据源中获取
使用完毕后将连接资源归还给数据源

6. spring注解开发

6.1 spring的原始注解

spring是轻代码而重配置的框架,配置比较繁重,影响开发效率,注解代替xml配置文件可以简化配置,提高开发效率。
spring原始注解主要替代<bean>的配置
@Component  使用在类上用于实例化Bean
@Controller   使用在web层类上用于实例化bean
@Service      使用在service层类上用于实例化bean
@Repository   使用在dao层类上用于实例化bean
@Autowired   使用在字段上用于根据类型依赖注入
@Qualifier     结合@Autowired一起使用用于根据名称进行依赖注入
@Resource     相当于@Autowired + @Qualifier,按照名称进行注入
@Value        注入普通属性
@Scope        标注bean的作用范围
@PostConstruct  使用在方法上标注该方法是bean的初始化方法
@PreDestroy     使用在方法上标注该方法是bean的销毁方法
//<bean id="studentDao" class="cn.hfnu.dao.impl.StudentDaoImpl"></bean>
@Component

//<bean id="studentService" class="cn.hfnu.service.impl.StudentServiceImpl"></bean>
@Component

@Autowired
@Qualifier("studentDao")
private StudentDao studentDao;

使用注解进行开发时,需要在applicationContext.xml中配置组件扫描,作用是指定哪个包及其子包下的bean需要进行扫描以便识别使用注解配置的类、字段和方法。

<!--配置组件扫描包-->
<context:component-scan base-package="cn.hfnu"/>

6.2 spring的新注解

非自定义的bean的配置:<bean>

加载properties文件配置:

image.png

组件扫描的配置:

image.png

引入其他文件:<import>
@Configuration  用于指定当前类是一个spring配置类,当创建容器时会从该类上加载注解
@ComponentScan   用于指定spring在初始化容器要扫描的包。
@Bean    使用在方法上,标注将该方法的返回值存储到spring容器中
@PropertySource   用于加载.properties 文件中配置
@Import    用于导入其他配置类

7 spring集成junit

7.1 原始junit测试spring的问题

image.png

这两行代码的作用是获取容器,如果不写,提示空指针异常。不能轻易的删除。

7.2 上述问题的解决方案

让springjunit负责创建spring容器,但是需要将配置文件的名称告诉它 将需要进行测试的bean直接在测试类中进行注入

7.3 spring集成junit步骤

导入spring集成junit的坐标
使用@Runwith注解替换原来的运行期
使用@ContextConfiguration指定配置文件或配置类
使用@Autowired注入需要测试的对象
创建测试方法进行测试

8 spring集成web环境

8.1 applicationcontext应用上下文获取方式

应用上下文对象是通过new ClassPathXmlApplicationContext("applicationContext.xml")方式获取的,但是每次从容器中获得bean时都要
new ClassPathXmlApplicationContext("applicationContext.xml"),这样的弊端是配置文件被加载多次,应用上下文对象创建多次。

在web项目中,可以使用servletcontextlistener监听web项目启动,我们可以在web项目中启动时,加载spring配置文件,创建应用上下文对象applicationcontext,在将其存储到最大的域servletcontext域中,这样就可以在任意位置从域中获得应用上下文applicationcontext对象。

如果你认真阅读到这里相信你对Spring入门有了一定的收获。以上这篇博客是对自己的学习过程的记录,坚持一件事不容易,我们的目标和人民日报站在一起!如果你在看,请坚持点个“在看”,点个“赞”,你个在看你会变好看。