Spring第一天笔记
一、spring的介绍
- spring 开源的轻量级框架
- spring的两大核心:IOC ,AOP
- IOC(Inverse Of Control:反转控制)
- AOP(Aspect Oriented Programming:面向切面编程)
二、spring和EJB的区别(了解)
EJB可以说像是一个Web Service,但也不完全是,比如EJB将编写好的业务组件放置在EJB容器上,然后提供接口给客户端访问;但是功能不仅限如此,EJB标准中提供了很多规范等,而这些规范只有在EJB容器才能正常运行。
EJB重量级框架
Spring容器取代了原有的EJB容器,因此以Spring框架为核心的应用无须EJB容器支持,可以在Web容器中运行。
Spring容器管理的不再是复杂的EJB组件,而是POJO(Plain Old Java Object) Bean。
Spring轻量级框架
三、耦合和解耦
- 什么是耦合
模块之间的关联程度, 依赖程度 - 什么是解耦
降低模块之间的耦合度(依赖关系) - 解耦的目的
编译器不依赖,运行期才依赖 - 解耦思路
(1) 把全限类名都放到配置文件中
(2) 通过工厂帮助创建对象
四、解耦代码(了解)
try { //耦合度高,在编译时就需要其他模块支持(new 对象)
Driver driver = new Driver();
//注册驱动
DriverManager.registerDriver(driver);
} catch (SQLException e) {
e.printStackTrace();
}
try { //解耦思想,通过全限类名反射创建对象
Class.forName("com.mysql.jdbc.Driver");
//此时的好处是我们的类中不再依赖具体的驱动类,此时就算删除 mysql的驱动jar包依然可以编译
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
同时,也产生了一个新的问题,mysql 驱动的全限定类名字符串是在 java 类中写死的,一旦要改还是要修改源码。
解决这个问题也很简单,使用配置文件配置。
五、控制反转-- 自定义IOC(了解)
- 引入依赖
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>1.1.6</version>
</dependency>
- 配置文件 beans.xml
<beans>
<!--
用bean标签配置所有的bean对象
id: 对象的唯一的标志
class:类名
-->
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"></bean>
<bean id="userService" class="com.itheima.service.impl.UserServiceImpl"></bean>
</beans>
- 创建BeanFactory工厂对象
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 创建bean对象的工厂类
*/
public class BeanFactory {
private static Map<String ,Object> map = new HashMap<>();
//提前把所有的对象创建出来,存储
//Map :因为有查找需求 --相当于容器对象-- 包含了所有的对象
//静态代码块
static{
//获取配置文件的输入流对象
InputStream inputStream = BeanFactory.class.getResourceAsStream("/beans.xml");
//解析xml获取xml中所有的信息
SAXReader reader = new SAXReader();
try {
//创建文档对象
Document doc = reader.read(inputStream);
//获取根节点
Element root = doc.getRootElement();
//获取根节点中所有的子节点
//element("bean") : 获取第一个叫bean的子节点
//elements("bean") : 获取所有叫bean的子节点
//elements() : 获取所有的子节点
List<Element> beanList = root.elements("bean");
//获取每一个bean的id和class
for (Element element : beanList) {
String id = element.attributeValue("id");
String className = element.attributeValue("class");
//通过className全限类名创建对象--获取字节码
Class clazz = Class.forName(className);
//通过反射创建对象
Object obj = clazz.newInstance();
//存储在Map集合中
//key: id
//value:obj
map.put(id ,obj);
}
} catch (Exception e) {
e.printStackTrace();
}
}
//需要实现的功能,传入一个名字,获取一个Bean对象
public static Object getBean(String name){
return map.get(name);
}
}
- 测试
public static void main(String[] args) {
Object userService1 = BeanFactory.getBean("userService");
System.out.println(userService1); //@448139f0
Object userService2 = BeanFactory.getBean("userService");
System.out.println(userService2); //@448139f0
}
六、spring的IOC入门(掌握)
- 引入依赖
<!--引入spring 的最核心依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
- 创建beans.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!--
http://www.springframework.org/schema/beans: 引入bean的名称空间
约束:现在xml的书写
dtd:mybatis
schema:spring
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd :引入约束
-->
<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.itheima.dao.impl.UserDaoImpl"></bean>
</beans>
- 创建容器对象,根据id获取对象
//创建spring的IOC容器
ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
//获取对象
Object userDao = ac.getBean("userDao");
System.out.println(userDao);
七、IOC的细节
1、容器对象的类结构图
-
beanFactory 是spring容器的顶层接口
-
接口ApplicationContext是 beanFactory子接口
实现类: ClassPathXmlApplicationContext -- 从类路径之下读取配置文件 (常用) FileSystemXmlApplicationContext -- 从绝对路径指定的配置文件读取 AnnotationConfigApplicationContext -- 纯注解配置使用的类 (常用)
-
BeanFactory与ApplicationContext区别
Resource resource = new ClassPathResource("beans.xml");
// BeanFactory:创建容器对象时,只是加载了配置文件,没有创建对象
// 获取对象时:创建对象
BeanFactory beanFactory = new XmlBeanFactory(resource);
Object userDao = beanFactory.getBean("userDao");
System.out.println(userDao);
//创建spring的IOC容器
//在创建容器对象时,创建对象 (常用)
//ApplicationContext:在创建容器时只创建单例模式的对象
// 多例模式的对象,在获取时创建
ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
Object userDao2 = ac.getBean("userDao");
System.out.println(userDao2);
2、getBean方法(掌握)
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//根据名称获取该对象
Object userDao = ac.getBean("userDao");
System.out.println(userDao);
// 根据类型获取该对象
// 如果该类型有两个实现类,会执行异常
UserDao userDao = ac.getBean(UserDao.class);
System.out.println(userDao);
// 得到是id为userDao1的对象,类型为UserDao接口的实现类
UserDao userDao = ac.getBean("userDao2", UserDao.class);
System.out.println(userDao);
3、bean对象的范围和生命周期(掌握)
springIOC容器默认的单例模式: 单例模式的对象在创建容器时创建,销毁容器时销毁
scope: prototype 原型模式(多例模式):获取时创建,当对象长时间不在被引用,则被垃圾回收机制回收
scope: singleton 单例模式
scope: request 请求范围
scope: session 会话范围
scope: global session :全局范围 -- spring 5的新特性中被删除了
init-method:指定类中的初始化方法名称。
destroy-method:指定类中销毁方法名称。
4、实例化bean的三种方法(了解)
1 .<bean id="name" class="全限类名">
getBean(name)
2. 根据静态工厂获取对象
public class StaticFactory {
public static UserDao getUserDao(){
return new UserDaoImpl();
}
}
<!--通过静态工厂创建UserDao对象-->
<!--
factory-method: 工厂方法,返回UserDao对象的方法名
-->
<bean id="userDao" class="com.itheima.factory.StaticFactory"
factory-method="getUserDao"></bean>
3. 根据实例(非静态)工厂获取对象
public class InstanceFactory {
public UserDao getUserDao(){
return new UserDaoImpl();
}
}
<!--创建实例工厂对象-->
<bean id="instanceFatory" class="com.itheima.factory.InstanceFactory"></bean>
<!--通过实例工厂创建UserDao对象-->
<bean id="userDao2" factory-bean="instanceFatory"
factory-method="getUserDao"></bean>
5、依赖注入(掌握)
a.什么是依赖注入
虽然我们所需的对象交给工厂创建,但是有些对象与对象之间存在依赖关系
(例如UserService里面需要UserDao支持)
业务层需要持久层的对象,在配置文件中给业务层传入持久层的对象,就是依赖注入
b. ioc
控制反转包含了依赖注入和依赖查找
6、构造方法注入(掌握)
<!--依赖注入-->
value 属性只能赋值简单的类型:基本数据类型和String类型
ref: pojo类型,复杂类型, 关联创建好的对象
<!--默认创建对象方式,使用默认的空的构造方法创建对象-->
<bean id="user" class="com.itheima.domain.User">
<!--通过构造方法参数的索引赋值-->
<constructor-arg index="0" value="1"></constructor-arg>
<constructor-arg index="1" value="张三"></constructor-arg>
<!--通过构造方法参数类型赋值-->
<constructor-arg type="java.lang.Integer" value="2"></constructor-arg>
<constructor-arg type="java.lang.String" value="李四"></constructor-arg>
<!--通过构造方法参数名字赋值-->
<constructor-arg name="id" value="3"></constructor-arg>
<constructor-arg name="username" value="王五"></constructor-arg>
<constructor-arg name="sex" value="男"></constructor-arg>
<constructor-arg name="birthday" ref="birthday"></constructor-arg>
</bean>
<bean id="birthday" class="java.util.Date"></bean>
7、set方法注入属性(常用)(掌握)
<!--通过set方法注入-->
<bean id="user2" class="com.itheima.domain.User">
<!--property :属性注入 , 先找到set方法,才能最终找到属性-->
<property name="username" value="王朝"></property>
<property name="birthday" ref="birthday"></property>
<property name="sex" value="男"></property>
<property name="id" value="4"></property>
</bean>
8、p名称空间注入:基于set方法注入— 了解
a、在头部文件中引入p名称空间
xmlns:p="http://www.springframework.org/schema/p"
b、使用p名称空间注入属性
<bean id="user3" class="com.itheima.domain.User"
p:id="5" p:username="马汉" p:sex="男" p:birthday-ref="birthday"
></bean>
9、注入集合属性(掌握)
给类中的集合成员传值,它用的也是set方法注入的方式
<!--注入集合属性-->
<bean id="user4" class="com.itheima.domain.User">
<!--array ,list ,set 结构相同,标签可以混用-->
<property name="list">
<set>
<value>javaSE</value>
<value>javaEE</value>
<value>javaME</value>
</set>
</property>
<property name="set">
<array>
<value>javaSE</value>
<value>javaEE</value>
<value>javaME</value>
</array>
</property>
<property name="strs">
<list>
<value>javaSE</value>
<value>javaEE</value>
<value>javaME</value>
</list>
</property>
<!--map集合properties结构相同,可以通用-->
<property name="map">
<props>
<prop key="五" >five</prop>
<prop key="六" >six</prop>
<prop key="七" >seven</prop>
</props>
</property>
<property name="properties">
<map>
<!--键值对配置-->
<entry key="一" value="one"></entry>
<entry key="二" value="two"></entry>
<entry key="三" value="three"></entry>
<entry key="四" value="four"></entry>
</map>
</property>
</bean>