一、spring

1
2
3
4
5
6
7
8
9
spring核心学习内容 IOC,AOP,jdbcTemplate,声明式事务     Maven构建,不用闸包!!!!
1.IOC:控制反转,可以管理Java对象
2.AOP:切面编程
3.JDBCTemplate:是spring提供一套访问数据库技术
4.声明式事务:基于ioc/aop实现事务管理

几个重要概念:
Spring可以整合其他框架(Spring是管理框架的框架)
两个核心概念:IOC、AOP

二、快速入门

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
1.构建Maven模块
2.引入依赖:
pendency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>7.0.5</version>
</dependency>

3.在resources文件夹下创建xml文件(spring的)
4.配置xml文件:
<!--配置User对象-->
<!--
这里解读:
1.在beans文件中可以配置多个bean
2.bean表示一个Java对象!!!!
3.class属性是用于指定类的全路径->spring底层使用反射创建
4.id属性表示该Java对象在spring容器中的id,通过id获取到对象,如果没有配置id,按照全类名配置!!
5.property 表示设置属性,name表示该类里面的变量,value表示设置值
-->
<bean class="om.itchen.Spring6.User" id="user1">
<!--1.当我们给某个Bean对象设置属性的时候-->
<!--2.底层使用对应的setter方法完成的,比如setName()-->
<!--3.如果没有该方法,就会报错!!!!!-->
<property name="id" value="100"/>
<property name="name" value="牛魔王"/>
<property name="skill" value="芭蕉扇"/>
</bean>

三、获取bean

1
2
3
4
5
6
7
8
9
10
//全部:获取bean容器
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");

//方式1:根据id获取(bean要有id。如果没有则默认全类名)
User user = (User) context.getBean("user1");
System.out.println("id获取Bean:" + user);

//方式2: 根据类型和id获取
User user2 = context.getBean(User.class,"user1");
System.out.println("根据类型获取:" + user2);

四、设置bean属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
1. setter方法注入:
<bean id="book1" class="com.itchen.spring6.iocxml.di.Book"> 一定要有setter方法,否则无法注入!!!
<property name="bname" value="java" />
<property name="author" value="Xc" />
</bean>

2.构造器注入:
<bean id="book2" class="com.itchen.spring6.iocxml.di.Book">
<!--构造器注入-->
<constructor-arg value="python" index="0" />
<constructor-arg value="老陈" index="1" />
</bean>

3.ref标签(外部引入)
<bean class="spring.dao.MemberDAOImpl" id="memberDAO"/> 第一个bean
<bean class="spring.service.MemberServiceImpl" id="memberService"> 引入第一bean
<property name="memberDAO" ref="memberDAO" /> ref="id名"
</bean>

注:特殊值:&lt 是 <; &gt 是 >; 使用 <![CDATA[a < b]]> CDATA节; <null /> 空值;

五、特殊属性注入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
1.级联对象注入(ref标签):
<bean id="dept1" class="com.itchen.spring6.iocxml.di.Dept"> <!--建立父级(部门) -->
<property name="dname" value="开发部" />
</bean>
<bean id="emp1" class="com.itchen.spring6.iocxml.di.Emp"> <!-- 建立子级(员工) -->
<property name="ename" value="小陈" />
<property name="age" value="20" />
<!--对象属性注入-->
<property name="dept" ref="dept1" />
<!--修改父级的值--> 这里父类和子类都要有get方法!!!
<property name="dept.dname" value="测试部" />
</bean>

2.数组类型注入:
<bean id="emp1" class="com.itchen.spring6.iocxml.di.Emp">
<!--数组类型注入-->
<property name="hobby">
<array> 使用array数组标签
<value>打篮球</value> 可以有多个值
<value>跳舞</value>
<value>唱歌</value>
</array>
</property>
</bean>

3.List类型注入:
<bean id="dept3" class="com.itchen.spring6.iocxml.di.Dept">
<property name="dname" value="开发部" />
<property name="emplist">
<list> 使用list数组标签
<ref bean="emp2" />
<ref bean="emp3" />
</list>
</property>
</bean>

4.Map类型注入:
<!--创建老师-->
<bean id="teacher1" class="com.itchen.spring6.iocxml.dimap.Teacher">
<property name="tname" value="王老师" />
<property name="tid" value="1" />
</bean>
<!--创建学生-->
<bean id="student1" class="com.itchen.spring6.iocxml.dimap.Student">
<property name="sid" value="1" />
<property name="sname" value="小陈" />
<!--map属性类型注入-->
<property name="teacherMap">
<map> map标签,entry标签,key标签(存放键),ref标签(存放值)
<entry>
<key>
<value>1</value>
</key>
<ref bean="teacher1" />
</entry>
</map>
</property>
</bean>

5.Set和properties属性类型注入:
这里简短些
Set: 和list一样 <set> </set>
properties: <props> <prop key="username">itchen</prop> </props>

6.数据重用:
<bean parent="monster1" id="m" class="....."> 如果想重用其他bean,使用parent属性!!!

六、util配置和p标签

1
2
3
4
5
6
7
8
9
10
11
12
1.如果有重复使用的值,有不想创建类,可以使用util配置     注:支持list map set properties
<util:list id="myBookList">
<value>三国演义</value>
<value>红楼梦</value>
</util:list> //使用用ref即可


2.普通代码太长,可以使用p标签缩短 写在bean属性上
<bean id="book4" class="com.itchen.spring6.iocxml.di.Book"
p:bname="水浒传"
p:author="施耐庵"
/>

七、bean的作用域和生命周期

1.bean的作用域

作用域定义了 Spring 容器创建 Bean 实例的规则,Spring 7 中核心作用域有 6 种,其中单例(singleton)原型(prototype) 是最常用的基础作用域,其余为 Web 环境专属。

核心作用域详解(按使用频率排序)

作用域 核心含义 适用场景 Spring 7 注意点
singleton 容器中仅创建 1 个实例,全局共享(默认作用域) 无状态的工具类、服务类(如 Service) 优化了单例 Bean 的初始化性能
prototype 每次获取 Bean 时创建新实例,容器仅负责创建,不管理销毁 有状态的对象(如 User、Order) 适配 Java 17 密封类,创建效率提升
request Web 环境中,每个 HTTP 请求创建 1 个实例 Web 请求级别的数据载体 需结合 Spring MVC 7.0+
session Web 环境中,每个 HTTP Session 创建 1 个实例 用户会话级别的数据(如购物车) 兼容 Servlet 6.0+
application Web 环境中,整个 Web 应用仅 1 个实例(区别于 singleton:基于 ServletContext) 应用级全局配置 与 singleton 功能重叠,极少使用
websocket WebSocket 连接周期内仅 1 个实例 实时通信场景 适配 WebSocket 1.1 规范
1
2
3
4
5
6
7
8
9
10
11
12
13
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">

<!-- 1. 单例 Bean(默认,可省略 scope="singleton") -->
<bean id="singletonService" class="com.example.SingletonService" scope="singleton"/>

<!-- 2. 原型 Bean(每次获取新建实例) -->
<bean id="prototypeUser" class="com.example.User" scope="prototype"/>

</beans>

2.bean的生命周期

(1)实例化(Instantiation)

容器根据配置(XML / 注解)创建 Bean 实例(底层通过反射 new 对象),此时仅分配内存,未注入任何属性。

(2)属性注入(Populate)

容器将依赖的 Bean / 值注入到当前 Bean 的属性中(如 XML 中的 <property>/<constructor-arg>)。

(3)初始化(Initialization)

Bean 实例就绪前的自定义操作,有 2 种常用扩展方式:

  • 实现 InitializingBean 接口(重写 afterPropertiesSet());
  • XML 中配置 init-method(自定义初始化方法)。

(4)使用(Usage)

Bean 完全就绪,可通过容器获取并调用方法。

(5)销毁(Destruction)

容器关闭时执行的清理操作,有 2 种扩展方式:

  • 实现 DisposableBean 接口(重写 destroy());
  • XML 中配置 destroy-method(自定义销毁方法)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
///创建类,并实现 初始化类和销毁类
public class beanLife implements InitializingBean, DisposableBean {
private String name;

// 属性注入用的 Setter
public void setName(String name) {
this.name = name;
System.out.println("2. 注入属性:name = " + name);
}

// 1. 实例化构造器
public beanLife() {
System.out.println("1. 实例化 Bean(调用构造器)");
}

// === 初始化阶段 ===
// 方式 1:实现 InitializingBean 接口
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("3. 执行 InitializingBean.afterPropertiesSet()");
}

// 方式 2:自定义 init-method(XML 配置)
public void myInit() {
System.out.println("4. 执行自定义 init-method:myInit()");
}

// === 销毁阶段 ===
// 方式 1:实现 DisposableBean 接口
@Override
public void destroy() throws Exception {
System.out.println("6. 执行 DisposableBean.destroy()");
}

// 方式 2:自定义 destroy-method(XML 配置)
public void myDestroy() {
System.out.println("7. 执行自定义 destroy-method:myDestroy()");
}

// 业务方法
public void queryUser() {
System.out.println("5. 使用 Bean:查询用户,name = " + name);
}
}



///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">
///init-method="初始化方法名" 执行这个方法表示初始化 destory-method="销毁方法名" 执行这个方法表示销毁
<bean id="beanLife" class="com.itchen.spring6.iocxml.beanLife.beanLife" init-method="myInit"
destroy-method="destroy">
<property name="name" value="张三" />
</bean>
</beans>



///测试
public class Test {
public static void main(String[] args) {
ClassPathXmlApplicationContext life =
new ClassPathXmlApplicationContext("beanLife.xml");
beanLife beanLife = life.getBean("beanLife", beanLife.class);
/// 使用bean查询
beanLife.queryUser();
/// 销毁bean 使用bean容器的close方法
life.close();
}
}

///执行流程
1. 实例化 Bean(调用构造器)
2. 注入属性:name = 张三
3. 执行 InitializingBean.afterPropertiesSet()
4. 执行自定义 init-method:myInit()
5. 使用 Bean:查询用户,name = 张三
6. 执行 DisposableBean.destroy()

八、自动装配

1
<bean id="userService" class="com.itchen.spring6.iocxml.auto.service.userServiceImp.UserServiceImp" autowire="byType">          使用autowire自动装配
模式 含义 优点 缺点
no 关闭自动装配(默认),需手动配置依赖注入 可控性高 配置繁琐
byName 按「属性名」匹配容器中的 Bean ID,匹配成功则注入 简单,匹配规则明确 需保证属性名和 Bean ID 完全一致
byType 按「属性类型」匹配容器中的 Bean,匹配成功则注入(Spring 7 推荐) 无需关注 Bean ID,更灵活 同类型多个 Bean 时会报错
constructor 按构造器参数的「类型」匹配 Bean,注入到构造器中 适合不可变 Bean(final) 同类型多个 Bean 时会报错
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
// 依赖的 Bean:UserDao
package com.example;
public class UserDao {
public void query() {
System.out.println("UserDao 执行查询");
}
}

// 目标 Bean:UserService(依赖 UserDao)
package com.example;
public class UserService {
// 注意:属性名和 Bean ID 一致(byName 模式需要)
private UserDao userDao;

// Setter 方法(byName/byType 模式需要)
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}

// 构造器(constructor 模式需要)
public UserService(UserDao userDao) {
this.userDao = userDao;
}

// 无参构造器(byName/byType 模式需要,否则容器无法实例化)
public UserService() {}

// 业务方法
public void doService() {
userDao.query();
}
}



<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">

<!-- 1. 定义被依赖的 Bean:UserDao(ID 为 userDao) -->
<bean id="userDao" class="com.example.UserDao"/>

<!-- 2. 定义目标 Bean:UserService,开启自动装配 -->
<!-- 方式 1:按名称装配(byName):匹配属性名 userDao → Bean ID userDao -->
<bean id="userService" class="com.example.UserService" autowire="byName"/>

<!-- 方式 2:按类型装配(byType):匹配属性类型 UserDao → 容器中唯一的 UserDao Bean -->
<!-- <bean id="userService" class="com.example.UserService" autowire="byType"/> -->

<!-- 方式 3:按构造器装配(constructor):匹配构造器参数类型 UserDao -->
<!-- <bean id="userService" class="com.example.UserService" autowire="constructor"/> -->

</beans>

九、基于注解开发

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
注解可以放到类、方法、字段上,简化开发;
流程:
1.创建xml文件
2.输入:
xmlns:context="http://www.springframework.org/schema/context" 1 使用context空间
xsi:schemaLocation="
http://www.springframework.org/schema/context 2
http://www.springframework.org/schema/context/spring-context.xsd 3

开启组件扫描:
<context:component-scan base-package="com.itchen" />

3.使用注解
@Component(value = "user") //等同于 <bean id="user" class="...."> 不写默认类名!!!
public class User{

}

注解类型:
@Component 表示一个容器中的组件,其作用在任何一个层次内,如@Service;
@Repository 表示Dao层,与@Component作用相同
@Service 表示业务层,与@Component作用相同
@Controller 表示控制层,与@Component作用相同
@Autowired 自动装配,可以用到属性、set方法、构造方法、形参(set方法不可以) 默认byType类型
@Qualifier("bean类名") 与@Autowired 联合使用,当有两个相同的类注入时,使用该注解 byName类型
@Resource 自动装配,可以自动切换byName和byType类型!
需要引入依赖(@Resource是jdk自带的):
<dependency>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
<version>2.1.1</version>
</dependency>
注:如果类只有一个有参构造函数,可以省略@Autowired!!!!!

十、全注解开发

如何省略xml文件??使用注解

1
2
3
4
5
6
7
8
9
10
//流程:
///1.写一个类,声明这两个注解
@Configuration 配置类注解,代替xml文件
@ComponentScan("包路径")@Configuration联合使用,进行包扫描
@bean 表示注入bean,交给容器管理


///2.创建容器,此时不用 new ClassPathXmlApplicationContext("bean.xml");
ApplicationContext context = new
AnnotationConfigApplicationContext(SpringConfiguration.class); //扫描配置类!!!

十一、AOP切面编程

1.快速入门

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
1.引入依赖:
<!--引入 spring aop依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>7.0.5</version>
</dependency>
<!--引入 spring aspects依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>7.0.5</version>
</dependency>

2.创建一个接口类和实现类

3.xml配置
<!--开启组件扫描-->
<context:component-scan base-package="com.itchen.Spring6.annoaop" />
<!--开启aspect自动代理,为目标对象生成代理-->
<aop:aspectj-autoproxy />

4.创建切面类
@Aspect //切面类
@Component
public class LogAspect {
//前置通知
@Before(value = "execution(public int com.itchen.Spring6.annoaop.CalculatorImpl.* (..))")
public void beforeMethod(){
System.out.println("前置通知");
}
}

5.创建bean容器进行测试即可

2.通知方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1.前置通知:@Before    在方法调用前
使用:@Before(value = "execution(访问修饰符 增强方法返回值类型 方法全类名.方法名(*所有方法) 形参(..任意类型))")

2.返回通知:@AfterReturning 在方法调用之后 他和后置通知的区别是可以获取方法返回值
@AfterReturning(value = "execution(访问修饰符 增强方法返回值类型 方法全类名.方法名 形参",returning = "aa")类型Object

3.异常通知:@AfterThrowing 方法抛出异常通知
@AfterThrowing(value = "execution(访问修饰符 增强方法返回值类型 方法全类名.方法名 形参)",throwing = "ex")类型Object

4.后置通知:@After 有没有发生异常都会通知,又称最终通知
@After(value = "execution(访问修饰符 增强方法返回值类型 方法全类名.方法名(*所有方法) 形参(..任意类型))")

5.环绕通知:@Around
上面四个的总和,使用try..catch...finally使用上面四个通知!!!!!!
@Around(value = "execution(访问修饰符 增强方法返回值类型 方法全类名.方法名(*所有方法) 形参(..任意类型))")