Spring第一天
一、简介
Spring框架是由于软件开发的复杂性而创建的。Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅仅限于服务器端的开发。从简单性、可测试性和松耦合性角度而言,绝大部分Java应用都可以从Spring中受益。
二、IOC容器
1.前景知识
1.1 容器:
可以管理对象的生命周期、对象与对象之间的依赖关系。
1.2POJO
① 什么是POJO
POJO(Plain Old Java Object)这种叫法是Martin Fowler、Rebecca Parsons和osh MacKenzie在2000年的一次演讲的时候提出来的。按照Martin FowlerE的解释是“Plain Old Java Object’",从字面上翻译为"纯洁老式的Java对象”,但大家都使用"简单Java对象"来称呼它。POJO的内在含义是指:那些没有继承任何类、也没有实现任何接口,更没有被其它框架侵入的Java对象。不允许有业务方法,也不能携带connection之类的方法,实际就是普通JavaBeans。
② 为什么会有POJO?
主要是Java的开发者被EJB的繁杂搞怕了,大家经过反思,又回归“纯洁老式”的JavaBean,即有无参构造函数,每个字段都有getter和setter的java类。
③ POJO的意义
POJO让开发者可专注于业务逻辑和脱离框架的单元测试。除此之外, 由于POJO并不须要继承框架的类或实现其接口,开发者能够极其灵活地搭建继承结构和建造应用。
POJO的意义就在于它的简单而灵活性,因为它的简单和灵活,使得POJO能够任意扩展,从而胜任多个场合,也就让一个模型贯穿多个层成为现实。
先写一个核心POJO,然后实现业务逻辑接口和持久化接口,就成了Domain Model; UI需要使用时,就实现数据绑定接口,变成VO(View Object)
④ POJO与PO、VO的区别
PO是指持久对象(persistant object持久对象)。
VO是指值对象或者View对象(Value Object、View Object)。View Object。
持久对象实际上必须对应数据库中的entity(与数据库中的字段一致),实体类与数据库表中字段不一致时,可以通过如下方法解决:
1. 与数据库表对应的PO.class
@Transient
不是数据库表字段的属性必须加@Transient注解(import javax.persistence.Transient)
@Column
数据库表字段与result不一致时用@Column注解,例如:
@Column(name = "t_schema")
private String schema;
2. 传入参数与数据库表字段不一致:
@Param
举个例子
表字段f_schema与实体schema不一致 错误代码:
public int update(UserExtraInfo info);
表字段f_schema与实体schema不一致 正确代码:
public int update(@Param("info") UserExtraInfo info);
所以和POJO有所区别。比如说POJO是由new创建,由GC回收。但是持久对象是insert数据库创建,由数据库delete删除的。基本上持久对象生命周期和数据库密切相关。另外持久对象往往只能存在一个数据库Connection之中,Connnection关闭以后,持久对象就不存在了,而POJO只要不被GC回收,总是存在的。
由于存在诸多差别,因此持久对象PO(Persistent Object)在代码上肯定和POJO不同,起码PO相对于POJO会增加一些用来管理数据库entity状态的属性和方法。而ORM追求的目标就是要PO在使用上尽量和POJO一致,对于程序员来说,他们可以把PO当做POJO来用,而感觉不到PO的存在。
1.3 JavaBean
JavaBean是一种AVA语言写成的可重用组件。JavaBean符合一定规范编写的ava类,不是一种技术,而是一种规范。大家针对这种规范
总结了很多开发技巧、工具函数。符合这种规范的类,可以被其它的程序员或者框架使用。它的方法命名,构造及行为必须符合特定的约定:
-
所有属性为private。
-
这个类必须有一个公共的缺省构造函数。即是提供无参数的构造器。
-
这个类的属性使用getter和setter来访问,其他方法遵从标准命名规范。
-
这个类应是可序列化的。实现serializablej接口。
因为这些要求主要是靠约定而不是靠实现接口,所以许多开发者把avaBean看作遵从特定命名约定的POJO。
1.4 POJO与JavaBean的区别
POJO类和Bean均用于定义Java对象,以提高其可读性和可重用性。POjO没有其他限制,而Bean是具有某些限制的特殊POJO。
1.5 SpringBean
SpringBean是受Spring管理的对象,所有能受Spring容器管理的对象都可以成为SpringBean。Spring中的Bean,是通过配置文件、javaconfig等的设置,由Springl自动实例化,用完后自动销毁的对象。
1.6 SpringBean和JavaBean的区别
1、用处不同:传统JavaBean更多地作为值传递参数,而Spring中的Bean用处几乎无处不在,任何组件都可以被称为Bean。
2、写法不同:传统JavaBean作为值对象,要求每个属性都提供getter和setter方法;但Spring中的Bean只需为接受设值注入的属性提供setter方法。
3、生命周期不同:传统JavaBean作为值对象传递,不接受任何容器管理其生命周期;Spring中的Bean有Spring管理其生命周期行为。
1.7.Entity Bean
Entity Bean是域模型对象,用于实现O/R映射,负责将数据库中的表记录映射为内存中的Entity对象,事实上,创建一个Entity Bean对象相当于新建条记录,删除一个Entity Bean会同时从数据库中删除对应记录,修改一个Entity Bean时,容器会自动将Entity Bean的状态和数据库同步。
2.概述
创建Maven项目,在pom配置文件引入Spring所需jar包和编译插件
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.19</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<!-- 编译插件-->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
Spring框架实现控制反转loC的原理,loC也称为依赖注入DL。
org.springframework.beans和org.springframework.context包是Spring框架的loC容器的基础。
BeanFactory接口提供了一种高级的配置机制,能够管理任何类型的对象。ApplicationContext是BeanFactory的子接口。它对
BeanFactory进行了补充:
BeanFactory能力:实现BeanFactory的实现类,BeanFactory管理容器里的Bean,BeanFactory子接口也有管理容器Bean的能力
设计在接口层设计,实现在实现类实现
- 更容易与Spring的AOP特性集成
- 消息资源处理(用于国际化),解析消息能力,支持国际化。继承自MessageSoure接口
- 事件发布,向注册侦听器发布事件的能力,集成自ApplicationEventPublisher接口
- 应用程序层特定的上下文,如(WebApplicationContext)用于web应用程序。
- 以通用方式加载文件资源的能力,继承自org.springframe.core.io.ResourceLoader接口。
简而言之,BeanFactory提供了容器的基本功能,而ApplicationContext添加了更多特定于企业的功能。ApplicationContext是
BeanFactory的一个完整超集
在Spring中,由Spring loC:容器管理的构成应用程序主干的对象称为bean。bean是由Spring loC容器实例化、组装和管理的对象。否则
bean只是应用程序中的众多对象之一。bean及其之间的依赖关系反映在容器使用的配置元数据中。
【applicationcontext】接口表示Spring loC容器,并负责实例化、配置和组装bean。容器通过读取配置元数据获得关于要实例化、配置和
组装哪些对象的指令。配置元数据以XML、Java注解或va代码表示。它允许您表达组成应用程序的对象以及这些对象之间丰富的相互依赖关系。
Spring提供了ApplicationContext接口的几个实现。
在独立应用程序中,创建ClassPathXmlApplicationContext或FileSystemXmlApplicationContext的实例是很常见的。虽然XML一直是定义配置元数据的传统格式,但您可以通过提供少量的XML配置以声明方式支持这些额外的元数据格式,指示容器使用v注解或代码作为元数据格式。
Spring容器 理解
代码目录
传统方式
dao层获取用户接口类
package com.ljz.dao;
public interface UserDao {
/**
* 获取用户信息
*/
void getUser();
}
dao层获取用户实现类
package com.ljz.dao.impl;
import com.ljz.dao.UserDao;
public class UserDaoImpl implements UserDao {
@Override
public void getUser() {
System.out.println("默认获取用户");
}
}
service层获取用户信息接口接口类
package com.ljz.service;
public interface UserService {
void getUser();
}
service层获取用户接口实现类
package com.ljz.service.impl;
import com.ljz.dao.UserDao;
import com.ljz.dao.impl.UserDaoImpl;
import com.ljz.service.UserService;
public class UserServiceImpl implements UserService {
private UserDao userDao = new UserDaoImpl();
@Override
public void getUser() {
userDao.getUser();
}
}
测试
package com.ljz.service.impl;
import com.ljz.service.UserService;
import org.junit.Test;
public class UserServiceImplTest {
@Test
public void getUser(){
UserService userService = new UserServiceImpl();
userService.getUser();
}
}
输出:
Spring容器思想:
将所有类的实例化都放到一个HashMap容器中,在其他类调用其他类时不用再重新new开辟实例空间。
IOC的思想就是把new实例化的操作交给Spring容器去做,去管理
在原代码基础上增加一个容器类
package com.ljz.container;
import java.util.HashMap;
import java.util.Map;
public class CoreContainer {
public static final HashMap<String,Object> MAP = new HashMap<>();
}
修改service层获取用户接口实现类逻辑
package com.ljz.service.impl;
import com.ljz.container.CoreContainer;
import com.ljz.dao.UserDao;
import com.ljz.dao.impl.UserDaoImpl;
import com.ljz.service.UserService;
/**
* @author ljz
* @version 1.0.0
* @ClassName UserServiceImpl.java
* @Description TODO
* @createTime 2022年05月05日 12:42:00
*/
public class UserServiceImpl implements UserService {
private final UserDao userDao = (UserDao) CoreContainer.MAP.get("userDao");
@Override
public void getUser() {
userDao.getUser();
}
}
测试
package com.ljz.service.impl;
import com.ljz.container.CoreContainer;
import com.ljz.dao.impl.UserDaoImpl;
import com.ljz.service.UserService;
import org.junit.Test;
public class UserServiceImplTest {
// @Test
// public void getUser(){
// UserService userService = new UserServiceImpl();
// userService.getUser();
// }
@Test
public void getUser1(){
CoreContainer.MAP.put("userDao",new UserDaoImpl());
CoreContainer.MAP.put("userService",new UserServiceImpl());
UserService userService = (UserService) CoreContainer.MAP.get("userService");
userService.getUser();
}
}
输出:
3.配置元数据
Spring loC容器使用一种配置元数据形式。这个配置元数据表示作为应用程序开发人员,告诉Spring容器如何去实例化、配置和组装应用程
序中的对象(类似于将配方交给Spring容器,他帮我们去实例化对象)。配置元数据传统上以简单而直观的XML格式提供。
创建配置文件:ioc.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userDao" class="com.ljz.dao.impl.UserDaoImpl">
</bean>
</beans>
测试类
加载配置元数据 ApplicationContext context = new ClassPathXmlApplicationContext(“ioc.xml”);
package com.ljz.service.impl;
import com.ljz.container.CoreContainer;
import com.ljz.dao.impl.UserDaoImpl;
import com.ljz.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class UserServiceImplTest {
@Test
public void testIoc(){
ApplicationContext context = new ClassPathXmlApplicationContext("ioc.xml");
UserDaoImpl bean = context.getBean(UserDaoImpl.class);
bean.getUser();
}
}
同样可以正确输出