尚硅谷课堂笔记:
链接: https://pan.baidu.com/s/1BPdI_vDWW2M-1A0okF3Pww 提取码: 2333
视频的代码笔记和资料。
老师笔记中的某些内容不再赘叙
此笔记 针对以上笔记为基础 添加补充
主要目的为针对自己复习学习
入门案例
public class TestSpring5 {
@Test
public void testAdd(){
//1.加载spring配置文件
/*
在src下 ,写下面这个(类路径)
new FileSystemXmlApplicationContext()不同
写绝对路径 D:\Mozilla Firefox\aa......
*/
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
//2.获取配置创建的对象
User user1 = context.getBean("user1", User.class);
user1.add();
}
}
public class User {
public void add(){
System.out.println("add....");
}
}
<?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">
<!-- 配置User对象创建-->
<bean id="user1" class="com.company.Spring5.User"></bean>
</beans>
一.IOC

调用过程 也就是在其他类里 去new 一个类,
虽然省去了new, 但是要到配置文件读取,配置文件中也得说明
目前还看不出来它的强大
1.IOC原理理解

问题:

dao路径变化了 方法变了 Service 都要变,耦合度高
这不满足 迪米特原则(最少知道原则)
目的:耦合度减低到最低
解决方法一(最终方法是IOC):工厂模式

这样解耦 还没有到达最低
解决方法二:IOC(xml+反射)

这样只需要改xml的class 就可以改动类,类似于定义变量,修改不用一个一个改
2.IOC接口

使用第二种 因为服务器启动时 可以慢,而且第一种是内部使用的接口

3.IOC —Bean管理操作


以下是xml Bean管理操作

User user1 = context.getBean("user1", User.class);
上面的代码 如果没有无参构造会报错

DI :Dependency Injection
DI 是IOC的一种具体实现。需要在创建对象的基础上完成
第一种注入方式:使用 set 方法进行注入
- (1)创建类,定义属性和对应的 set 方法
- (2)在 spring 配置文件配置对象创建,配置属性注入
八种基本类型 + String类型注入使用+Date类型 使用value属性进行赋值
对象类型 使用ref
详细的文章

第二种注入方式:使用有参数构造进行注入
-
(1)创建类,定义属性,创建属性对应有参数构造方法
-
(2)在 spring 配置文件中进行配置
<bean class="cdi.EmpDAOImpl" id="empDAO">
<!--使用构造注入-->
<constructor-arg index="0" name="name" value="小黑黑"/>
<constructor-arg index="1" name="age" value="23"/>
<constructor-arg index="2" name="bir" value="2012/12/12"/>
<!--注入数组-->
<constructor-arg index="3" name="qqs">
<array>
<value>小黑</value>
<value>小名</value>
<value>小陈</value>
</array>
</constructor-arg>
<!--注入list-->
<constructor-arg index="4" name="habbys">
<list>
<value>好人</value>
<value>坏蛋</value>
<value>小豆豆</value>
</list>
</constructor-arg>
</bean>
作者:嘿_鱼骨头
链接:https://juejin.cn/post/7088814727081492517
```xml
第三种注入方式:p名称空间
> 就是 标签的 p属性
>
> 其实底层还是第一种方法
### 4. 注入null和特殊值


xml语法那部分讲过的,cdata纯文本区域,不需要xml解析,自然不会错误识别了
### 5.注入属性—外部bean
解答:创建实例很费时间,通过配置文件的方式可以在服务器运行过程中提高速度,同时好管理好维护,
```xml
<bean id="UserService" class="com.company.Spring5.service.UserService">
<property name="userDao" ref="userDaoImpl"></property>
</bean>
<bean id="userDaoImpl" class="com.company.Spring5.dao.UserDaoImpl"></bean>
public class UserDaoImpl implements UserDao {
@Override
public void update() {
System.out.println("dao.update");
}
}
public class UserService {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void add() {
System.out.println("service.add");
}
}
6.内部bean和级联赋值
外部bean可以通过ioc获取,内部的获取不到
<bean id="emp1" class="com.company.Spring5.bean.Emp">
<property name="empName" value="ZS"></property>
<property name="gender" value="man"></property>
<property name="dept">
<!--就是属性也是个对象,这个对象有自己的小属性-->
<bean id="dept1" class="com.company.Spring5.bean.Dept">
<property name="deptName" value="KF"></property>
</bean>
</property>
</bean>
public class Emp {
private String empName;
private String gender;
//部门
private Dept dept;
public void setDept(Dept dept) {
this.dept = dept;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public void setGender(String gender) {
this.gender = gender;
}
}
以上的效果和上面的外部bean 一样


方法二需要生成get方法

7.注入集合类属性
<?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="stu" class="com.company.Spring5.bean.Stu">
<!--数组类型注入-->
<property name="courses" >
<array>
<value>java课程</value>
<value>数据库课程</value>
</array>
</property>
<!--list类型注入-->
<property name="list">
<list>
<value>张三</value>
<value>法外狂徒</value>
</list>
</property>
<!--map类型注入-->
<property name="map">
<map>
<entry key="skill1" value="java"></entry>
<entry key="skill2" value="php"></entry>
</map>
</property>
<!--set类型注入-->
<property name="set">
<set>
<value>Mysql</value>
<value>Redis</value>
</set>
</property>
</bean>
</beans>
public class Stu {
private String[] courses;
private List<String> list;
private Map<String, String> map;
private Set<String> set;
public void setList(List<String> list) {
this.list = list;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public void setCourses(String[] courses) {
this.courses = courses;
}
public void setSet(Set<String> set) {
this.set = set;
}
}
注入值是对象的情况
<!--创建多个 course 对象-->
<bean id="course1"class="com.atguigu.spring5.collectiontype.Course">
<property name="cname" value="Spring5 框架"></property>
</bean>
<bean id="course2" class="com.atguigu.spring5.collectiontype.Course">
<property name="cname" value="MyBatis 框架"></property>
</bean>
<!--注入 list 集合类型,值是对象-->
<property name="courseList">
<list>
<ref bean="course1"></ref>
<ref bean="course2"></ref>
</list>
</property>
集合注入部分提取

好像 一个公共类里面的公共方法

8.FactoryBean
FactoryBean 和BeanFactory 没有区别

工厂bean 就是xml 定义的类型 和 读取xml 后实际创建出来的bean类型不一样
9.Bean的作用域
1、在Spring里面,设置创建bean实例是单实例还是多实例。
默认情况下是单实例:
@Test
public void test2(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean6.xml");
//2.获取配置创建的对象
Book t1 = context.getBean("t1", Book.class);
System.out.println(t1);
Book t11 = context.getBean("t1", Book.class);
System.out.println(t11);
//com.company.Spring5.Book@72e5a8e
//com.company.Spring5.Book@72e5a8e
}
<?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="t1" class="com.company.Spring5.Book"></bean>
</beans>
设置是单实例还是多实例:

<?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="t1" class="com.company.Spring5.Book" scope="prototype"></bean>
</beans>
public void test2(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean6.xml");
//2.获取配置创建的对象
Book t1 = context.getBean("t1", Book.class);
System.out.println(t1);
Book t11 = context.getBean("t1", Book.class);
System.out.println(t11);
//com.company.Spring5.Book@29215f06
//com.company.Spring5.Book@59505b48
}

10.Bean的生命周期

1,2 步上面已经演示过了
第三步 是自己根据需要配置的,



同样是自己配置的

但是 销毁需要手动使用 .close() 才会去调用你配置的销毁方法。

bean的后置处理器,bean生命周期有七步
在实现BeanPostProcessor接口后 还有两步,可以在 初始化前 和初始化后 调用
1)通过构造器创建 bean 实例(无参数构造)
2)为 bean 的属性设置值和对其他 bean 引用(调用 set 方法)
3)把 bean 实例传递 bean 后置处理器的方法 postProcessBeforeInitialization
4)调用 bean 的初始化的方法(需要进行配置初始化的方法)把bean实例传递bean后置处理器的方法postProcessAfterInitialization
6)bean 可以使用了(对象获取到了)
7)当容器关闭时候,调用 bean 的销毁的方法(需要进行配置销毁的方法
实际开发的时候可以在项目启动时就获取到Bean对象,比如希望做一个过滤器链,可以存放到Map中在调用的时候直接从Map中获取,就不用在使用getBean方法了

配置之后所以的bean 都添加了后置处理器(好像是类似过滤器的那种)

11.XML管理方式(自动装配)(实际开发直接用注解方式 自动装配)
上面使用 或者外部bean的方法属于手动装配
<!--
以前的外部bean方式的属性注入
<bean id="emp" class="com.company.Spring5.Autowire.Emp2">
<property name="Dept2" ref="dept" ></property>
</bean>
<bean id="dept" class="com.company.Spring5.Autowire.Dept2"></bean>
-->
byName根据属性名称: 就是根据set方法注入
<!--实现自动装配
bean标签属性autowire,配置自动装配
autowire属性常用两个值:
byName根据属性名称注入 注入值bean的id值和类属性名称一样 我类的属性名字是dept2 下面那个标签的id 也是dept2
byType根据属性类型注入-->
<bean id="emp2" class="com.company.Spring5.Autowire.Emp2" autowire="byName">
</bean>
<bean id="dept2" class="com.company.Spring5.Autowire.Dept2"></bean>

byType根据属性类型注入:
<bean id="emp2" class="com.company.Spring5.Autowire.Emp2" autowire="byType">
</bean>
<bean id="dept2" class="com.company.Spring5.Autowire.Dept2"></bean>
下面这种就会报错 ,有两个Dept2类型的bean
<bean id="emp2" class="com.company.Spring5.Autowire.Emp2" autowire="byType">
</bean>
<bean id="dept2" class="com.company.Spring5.Autowire.Dept2"></bean>
<bean id="dept3" class="com.company.Spring5.Autowire.Dept2"></bean>
12.引入外部属性文件
引入namespace(命名空间)其实就是为了解析那个标签,spring默认引入的只有4个默认的标签
这个是使用schema技术对这个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"
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">
<!--
直接配置连接池
<bean id=" dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/userDb"></property>
<property name="username" value="root"></property>
<property name="password" value="123456"></property>
</bean>
-->
<context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
<bean id=" dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${prop.driverClassName}"></property>
<property name="url" value="${prop.url}"></property>
<property name="username" value="${prop.username}"></property>
<property name="password" value="${prop.password}"></property>
</bean>
</beans>
以下是注解 Bean管理操作

13.创建对象

4种功能没有区别 都可以创建对象 命名不同 开发更清晰而已(约定大于配置)

<?xml version="1.0" encoding="UTF-8"?>
<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:component-scan base-package="com.company.Spring5.dao,com.company.Spring5.service"></context:component-scan>
<!--或者写上层路径-->
<context:component-scan base-package="com.company.Spring5"></context:component-scan>
</beans>
//括号中的值可以不写默认首字母小写,就是userService
//等价于bean标签的Id ,上面的其他3种效果也一样
@Component(value = "userService")
public class UserService {
public void add() {
System.out.println("service.add");
}
}
public class TestBean {
@Test
public void testService() {
ApplicationContext context =new ClassPathXmlApplicationContext("bean1.xml");
UserService userService = context.getBean("userService", UserService.class);
userService.add();
}
}
14组件扫描细节
例1:
在设置的包中只扫描Controller注解

user-default-filters=“fasle” 时候 不写 includ-filter 就不会扫描包
例2:
在设置的包中除了Controller 其他的都扫描

15.属性注入

autowired根据bytype quilife根据byname reources可以根据byname也可以根据bytype

@Component(value = "userService")//等价于bean标签的Id
public class UserService {
@Autowired
private UserDao userDao;
public void add() {
System.out.println("service.add");
}
}
@Repository
public class UserImpl implements UserDao{
@Override
public void add() {
System.out.println("UserDao.add");
}
}
如果多个实现类可能就要指定名称 上面的例子中只有一个实现类
@Component(value = "userService")//等价于bean标签的Id
public class UserService {
@Autowired
@Qualifier(value = "userImpl1")
private UserDao userDao;
public void add() {
System.out.println("service.add");
userDao.add();
}
}
@Repository(value = "userImpl1")
public class UserImpl implements UserDao{
@Override
public void add() {
System.out.println("UserDao.add");
}
}
- @Resource注解是javax.annotacion包下的,属于java的扩展包,在标准jdk中没有 。需要导入

import javax.annotation.Resource;
-

@Value(value = "aaa") private String name;
16.纯注解开发
了解,实际中使用Springboot开发
(1)创建配置类 替代xml(中开启组件扫描)
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration //当前类作为配置类
@ComponentScan(basePackages = {"com.company"})
public class SpringConfig {
}
(2)测试类
@Test
public void testSpringConfig() {
ApplicationContext context =new AnnotationConfigApplicationContext(SpringConfig.class);
UserService userService = context.getBean("userService", UserService.class);
userService.add();
}


470

被折叠的 条评论
为什么被折叠?



