Spring笔记

Spring的基础( 一 )

对于Spring,需要理解IOC,DI,AOP思想;

IOC

在传统的开发中,我们需要手动创建新对象,在Spring框架中创建对象的工作不在交给程序员来实现,而是将这一操作交给了Spring,即第三方来实现,为什么呢?在传统开发中,如果我们需要创建的对象以下称为(User),如果添加了新的接口和新的功能,那我们则需要一个个去改变他们的实现方式,和调用他们的方法,如果我们的User里面还有其他需要实现的对象,所以我们这里需要解耦。

IOC的出现就是实现了解耦,降低了层与层之间的依赖,增强了代码的可维护性和复用性。如果UserName依赖于User,使用IOC,就不需要我们来手动实现依赖即依赖注入DI,IOC会创建UserName然后注入到User中。

Spring有两大重要的模式:

小结IOC:工厂模式,将创建对象的方式交给第三方,也就是交给Spring,由它给出的BeanFactory,ApplicationContext和XmlBeanFactory来获取我们需要的对象,即geatBean()方法。同时会完成DI操作(依赖注入),将依赖于User的类创建并注入到User。

IOC提供了多个容器,XmlBeanFactory,ApplicationContext,ClassPathXmlApplicationContext,FileSystemXmlApplicationContext。

如何实现?

1.我们需要有demo1类,然后创建一个User的依赖类UserName

2.在pom.xml文件中导入相关依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  <groupId>org.example</groupId>
<artifactId>mevan-java</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
//导入springfarmework
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.7</version>
</dependency>
//使用junit,方便测试
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
</dependencies>

3.创建一个xml文件,写入我们需要使用的类和依赖类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?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,class标签是需要的主类,userName则是userBean的依赖项,id就是对demo类的使用
//在property里面写入userName的依赖项
<bean id = "userBean" class = "demo1">
//这里的ref是指依赖类的“路径”,userName则是在调用时的对象名
//如果下面依赖类的id改变,这里的ref也需要改变
<property name="userName" ref="userName"/>
</bean>
//如果需要注入依赖,那么依赖项也需要写入
<bean id = "userName" class = "UserName"/>

</beans>

4.写一个demo1类和UserName类,在demo1类中,写下主程序。这里使用@Test注释

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
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.AbstractFileResolvingResource;
import org.springframework.core.io.ClassPathResource;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Array;
import java.util.ArrayList;

public class demo1 {
public static void main(String[] args) {
//可以使用主类也可以在其他方法上面写一个@Test,可以独立运行,并得出结果
}
public void setUserName(UserName userName){
//这里写了userBean设置UserName的方法,在UserBaen实现时,也会创建一个UserName对象并且调用这个方法
System.out.println("让我看看怎么个事");
}
@Test
public void test(){
//这里使用了ApplicationContext来实现BeanFactory,ApplicationContext可以理解为BeanFactory的升级版
//new时,需要写入xml文件的路径,除了ClassPathXmlApplicationContext,还有一个方法FileSystemXmlApplicationContext
//这个方法则通过系统路径来确认xml的内容,不常用。
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
// ApplicationContext applicationContext1 = new FileSystemXmlApplicationContext("path");
Object user = applicationContext.getBean("userBean");
// System.out.println(user);
}
@Test
public void text1(){
//XmlBeanFactory方式创造Bean工厂,并且需要ClassPathResource来确定xml文件的位置
//不推荐,有更好的ApplicationConextext,为什么要用BeanFactroy呢?
//xmlBeanFactory是BeanFactory的具体实现类,通过xml的配置文件来生成Bean工厂
XmlBeanFactory xmlBeanFactory = new XmlBeanFactory(new ClassPathResource("spring.xml"));
//BeanFactory直接创建生成,但是有更好的ApplicationContext来生成,更方便,有更多的功能可使用
BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring.xml");
//在BeanFactory的基础上,提供了资源访问,国际化,事件传播等功能
//ApplicationContext和BeanFactory的区别
//四条
//1)ApplicationContext和BeanFactory创建对象的时间不同,ApplicationContext在创建ApplicationContext的时候就准备好了创建对象
// 但是BeanFactory在getBean()时,才会实现对象
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");

Object user = xmlBeanFactory.getBean("userBean");
System.out.println(user);
}
@Test
public void test1(){
//这里通过DefaultListableBeanFactory来实现Bean工厂
DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(defaultListableBeanFactory);
xmlBeanDefinitionReader.loadBeanDefinitions("spring.xml");
Object user = defaultListableBeanFactory.getBean("userBean");
}
}

这里只写了依赖类,下面补上无依赖类,配置文件不再多说

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//UserName的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 = "user" class = "User">
<property name="age" value="20"/>
<property name="id" value="001"/>
<property name="name" value="zhangsan"/>
<property name="userName" ref="userName"/>
</bean>
<bean id = "userName" class = "UserName"/>
</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
34
35
36
37
38
39
40
41
42
43
44
45
//User的代码
public class User {
private UserName userName;
public void setName1(UserName name1){
this.userName = name1;
}
public UserName getName1(){
return userName;
}
private String name;
private String age;
private String id;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getAge() {
return age;
}

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

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String toString(){
return "name = " + name + " age = " + age + " id = " + id + " " + userName;
}

public void setUserName(UserName userName) {
this.userName = userName;
}
}
1
2
3
4
5
//UserName的代码
public class UserName {

}
//看着什么都没有,其实他就是什么都没有
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//demo代码
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class demo {
@Test
public void test1(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("UserBean.xml");
User user = (User) applicationContext.getBean("user");
System.out.println(user);
}
}

上面的代码演示了一个主类和一个依赖类,主类内有成员,输出主类,并且输出依赖类UserName。

对于依赖类的成员可以模仿着主类的方法写。

构造方法

上面代码演示的是无参构造函数

下面演示无参构造方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    <bean id = "user" class = "User">
<!-- <property name="age" value="20"/>-->
<!-- <property name="id" value="001"/>-->
<!-- <property name="name" value="zhangsan"/>-->
<!-- <property name="userName" ref="userName"/>-->
<!-- 下面是第一种有参构造方法-->
<!-- <constructor-arg name ="name" value="lsii"/>-->
<!-- <constructor-arg name ="id" value = "001"/>-->
<property name="age" value = "20"/>
<property name="name1" ref = "userName" />
<!-- 下面是第二种有参构造方法-->
<!-- 其中的index,是在User构造方法里面的输入的参数的序号,从0开始-->
<constructor-arg value="lisi" index="0"/>
<constructor-arg value="001" index="1"/>

</bean>

<bean id = "userName" class = "UserName"/>

获取Bean对象的方式

获取方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class demo {
@Test
public void test1(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("UserBean.xml");
//通过写的id属性来获取Bean对象
User user = (User) applicationContext.getBean("user");
System.out.println(user);
//通过.class文件来获取对象
//如果有两个User.class文件,会抛出异常,此时没有唯一的Bean,不知道该选择哪个
User user1 = (User) applicationContext.getBean(User.class);
System.out.println(user1);
//比较麻烦
User user2 = applicationContext.getBean("user",User.class);
System.out.println(user2);
}
}

如果Bean对象中有特殊的字符需要使用CDATA

待补

Bean之间的级联关系需要使用ref,使用value会抛出错误

警告: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘user’ defined in class path resource [UserBean.xml]: Initialization of bean failed; nested exception is org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type ‘java.lang.String’ to required type ‘UserName’ for property ‘name1’; nested exception is java.lang.IllegalStateException: Cannot convert value of type ‘java.lang.String’ to required type ‘UserName’ for property ‘name1’: no matching editors or conversion strategy found

Bean之间不能相互包括

会在Bean中生成Bean,无限递归包括,最终栈就炸了。

Spring中的Bean

Bean是根据scope来生成的,表示Bean的作用域,scope有四种类型

singleton 单例 表示通过Spring获取的bean对象是唯一的 为默认值

对于singleton的bean对象

通过singleton获取到的对象都是同一个对象,用 == 比较为true

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class demo {
@Test
public void test1(){
// ApplicationContext applicationContext = new ClassPathXmlApplicationContext("UserBean.xml");
// User user = (User) applicationContext.getBean("user");
// System.out.println(user);
// User user1 = applicationContext.getBean("user",User.class);
// System.out.println(user1);
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("UserBean.xml");
User user2 = context.getBean("user",User.class);
User user3 = context.getBean("user",User.class);
if(user2 == user3)
System.out.println("True");
}
}

prototype 原型 表示Spring获取到的bean对象是不同的

对于这个方式获得的bean对象,获取到的对象都是不同的,可以通过上面的方法来比较

只不过他们的属性刚好相同

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class demo {
@Test
public void test1(){
// ApplicationContext applicationContext = new ClassPathXmlApplicationContext("UserBean.xml");
// User user = (User) applicationContext.getBean("user");
// System.out.println(user);
// User user1 = applicationContext.getBean("user",User.class);
// System.out.println(user1);
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("UserBean.xml");
User user2 = context.getBean("user",User.class);
User user3 = context.getBean("user",User.class);
if(user2 == user3)
System.out.println("True");
else
System.out.println("False");
}
}

设置方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?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里面定义属性scope为prototype-->

<bean id = "user" class = "User" scope="prototype">
<!-- <property name="age" value="20"/>-->
<!-- <property name="id" value="001"/>-->
<!-- <property name="name" value="zhangsan"/>-->
<!-- <property name="userName" ref="userName"/>-->
<!-- <constructor-arg name ="name" value="lsii"/>-->
<!-- <constructor-arg name ="id" value = "001"/>-->
<property name="age" value = "20"/>
<property name="name1" ref = "userName" />
<constructor-arg value="lisi" index="0"/>
<constructor-arg value="001" index="1"/>
</bean>

<bean id = "userName" class = "UserName"/>
</beans>

request 请求,表示在异常HTTP请求内有效

session 会话,表示在一个用户会话内有效

Spring中的继承

Spring中的继承相区别于Java的继承,Java的继承是针对于类来说的,Spring的继承是相对于对象的。

给出代码演示

1.UserBean.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?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 = "user" class = "User" scope="prototype">
<property name="age" value = "20"/>
<property name="name1" ref = "userName" />
<property name="name" value="lisi"/>
<property name="id" value="001"/>
</bean>
<bean id ="user1" class="User" parent="user">
<!-这里继承了lisi的age和name1属性-->
<property name="name" value="zhangsan"/>
<property name="id" value="001"/>
</bean>

<bean id = "userName" class = "UserName"/>
</beans>

2.代码输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class demo {
@Test
public void test1(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("UserBean.xml");
User user1 = (User) applicationContext.getBean("user");
User user2 = (User) applicationContext.getBean("user1");
System.out.println(user1);
System.out.println(user2);
}
}

完成Bean对象的继承,Spring的继承是针对对象的子Bean和父Bean不需要同一数据类型,只需要成员列表一致

Spring的依赖

IOC容器默认通过UserBean.xml文件的配置顺序来决定创建顺序,配置在前面的Bean对象会被先创建

在不更改Bean配置顺序的情况下来调整Bean的创建程序,通过依赖关系来创建先后顺序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?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">
<!--这里通过修改UserName的顺序-->
<bean id = "userName" class = "UserName"/>

<bean id = "user" class = "User" scope="prototype">
<property name="age" value = "20"/>
<property name="name1" ref = "userName" />
<property name="name" value="lisi"/>
<property name="id" value="001"/>
</bean>

<bean id ="user1" class="User" parent="user">
<property name="name" value="zhangsan"/>
<property name="id" value="001"/>
</bean>
</beans>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class demo {
@Test
public void test1(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("UserBean.xml");
User user1 = (User) applicationContext.getBean("user");
User user2 = (User) applicationContext.getBean("user1");
System.out.println(user1);
System.out.println(user2);
}
}

UserName的默认构造方法

1
2
3
4
5
6
public class UserName {
UserName(){
System.out.println("我是依赖项");
}
}

User的方法

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
public class User {
private UserName userName;

// public User(String name, String id) {
// this.name = name;
// this.id = id;
// }

public void setName1(UserName name1){
System.out.println("setName使用");
}
public UserName getName1(){
return userName;
}
private String name;
private String age;
private String id;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getAge() {
return age;
}

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

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String toString(){
return "name = " + name + " age = " + age + " id = " + id + " " + userName;
}

public void setUserName(UserName userName) {
this.userName = userName;
}
}

输出

我是依赖项
setName使用
setName使用
name = lisi age = 20 id = 001 null
name = zhangsan age = 20 id = 001 null

UserName对象只被创造了一次,更改scope属性

我是依赖项
setName使用
我是依赖项
setName使用
name = lisi age = 20 id = 001 null
name = zhangsan age = 20 id = 001 null

通过depends-on来设置依赖项,就不需要在主类里面再次设置依赖项

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

<bean id = "user" class = "User" scope="prototype">
<property name="age" value = "20"/>
<property name="name" value="lisi"/>
<property name="id" value="001"/>
</bean>
<bean id = "userName" class = "UserName" depends-on="user"/>

</beans>

依赖配置完成

Spring读取外部资源

Spring的外部资源读入,需要配置xml文件,同时引入properties配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?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 https://www.springframework.org/schema/context/spring-context.xsd">

<context:property-placeholder location="jdbc.properties"/>

<bean id="root" class="Root" scope="prototype">

<property name="name" value="${name}"/>
<property name="driveName" value="${driveName}"/>
<property name="password" value="${password}"/>
<property name="url" value="${url}"/>

</bean>
</beans>

编写properties文件

1
2
3
4
name = root
password = root
url = path:url
driveName = smg

Root主类

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
public class Root {
private String name;
private String password;
private String url;
private String driveName;

public void setName(String name){
this.name = name;
}
public void setPassword(String password){
this.password = password;
}
public void setUrl(String url){
this.url = url;
}
public void setDriveName(String driveName){
this.driveName = driveName;
}
public String getName(){
return name;
}
public String getPassword(){
return password;
}
public String getUrl(){
return url;
}
public String getDriveName(){
return driveName;
}
public String toString(){
return "name = " + name + " password = " + password + " url = " + url + " driveName = " + driveName;
}
}

测试类demo_1

1
2
3
4
5
6
7
8
9
10
11
12
13
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class demo_1 {
@Test
public void test1(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("UserBean.xml");
Root root = applicationContext.getBean(Root.class);
System.out.println(root);
}
}

Spring P命名空间

1
2
3
4
5
6
7
8
9
10
11
<?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" xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

<context:property-placeholder location="jdbc.properties"/>
<!--沿用了上面的例子,同时使用p来简化bean的书写,需要引入新的规范-->
<bean id="root" class="Root" scope="prototype"
p:name="root" p:driveName="smg" p:password="root" p:url="path:url"/>
</beans>

Spring工厂方法

静态工厂方法和实例工厂方法 区别:静态工厂类不需要实例化,石磊工厂类需要实例化

静态工厂类

1.配置xml文件

1
2
3
4
5
6
7
8
9
10
<?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" xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--这里的<constructor-arg value="1"/>是对静态方法直接传入了1值并得到到了Car返回值-->
<bean id="carFactory" class="CarFactory" factory-method="getCar">
<constructor-arg value="1"/>
</bean>
</beans>

2.各个类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Car {
private String id;
private String carName;
Car(){}
Car(String id,String carName){
this.id = id;
this.carName = carName;
}
public void setId(String id){
this.id = id;
}
public void setCarName(String carName){
this.carName = carName;
}
public String getId(){
return id;
}
public String getCarName(){
return carName;
}
public String toString(){
return "id = " + id +" carName = " + carName;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.HashMap;
import java.util.Map;

public class CarFactory {

public static Map<Integer,Car> carMap = new HashMap<>();
static{
carMap.put(1, new Car("1", "aa"));
carMap.put(2,new Car("2","bb"));
}
public static Car getCar(Integer num){
return carMap.get(num);
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class demo_1 {
@Test
public void test1(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("UserBean.xml");
//需要注意一点,这里使用了carFactory的静态方法,所以直接返回的是一个Car对象
Car carFactory = (Car) applicationContext.getBean("carFactory");
System.out.println(carFactory);
}
}

实例工厂方法

1.xml文件配置

1
2
3
4
5
6
7
8
9
10
11
12
<?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" xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--创建主类,根据主类去创建一个实例类-->
<bean id="carFactory" class="CarFactory"/>
<!--这里需要手动实现一个实例类,然后调用里面的的方法-->
<bean id="carfactory" factory-bean="carFactory" factory-method="getCar">
<constructor-arg value="1"/>
</bean>
</beans>

2.主类和其他类

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
public class Car {
private String id;
private String carName;
Car(){}
Car(String id,String carName){
this.id = id;
this.carName = carName;
}
public void setId(String id){
this.id = id;
}
public void setCarName(String carName){
this.carName = carName;
}
public String getId(){
return id;
}
public String getCarName(){
return carName;
}
public String toString(){
return "id = " + id +" carName = " + carName;
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.HashMap;
import java.util.Map;

public class CarFactory {

public Map<Integer,Car> carMap = new HashMap<>();
CarFactory(){
carMap.put(1,new Car("1","aa"));
carMap.put(2,new Car("2","bb"));
}
public Car getCar(Integer num){
return carMap.get(num);
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class demo_1 {
@Test
public void test1(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("UserBean.xml");
//和静态类的方法类似,获取一个实力类,来完成getCar
Car carFactory = (Car) applicationContext.getBean("carfactory");
System.out.println(carFactory);
}
}

Spring自动装配

Spring有两种自动装配方式

1.byName

1)配置xml文件

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
<?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" xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

<context:property-placeholder location="jdbc.properties"/>

<bean id="root" class="Root" scope="prototype"
p:name="root" p:driveName="smg" p:password="root" p:url="path:url"/>
byName会通过id来检索需要依赖的对象,并且注入
<bean id="cla" class="Cla">
<!-- 需要有对应的构造方法-->
<constructor-arg name="cla" value="bb"/>
</bean>

<bean id="cla1" class="Cla">
<!-- 需要有对应的get_xx和set_xx方法-->
<property name="cla" value="aa"/>
</bean>

<bean id="person" class="Person" autowire="byName">
<property name="name" value="zhangsan"/>
<property name="id" value="001"/>
</bean>

</beans>

2)写主类和依赖类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Cla {
public String cla;
Cla(){}
Cla(String cla){
this.cla = cla;
}
public String toString(){
return cla;
}
public String getCla(String cla){
return cla;
}

public void setCla(String cla) {
this.cla = cla;
}
}
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
public class Person {
private String name;
private String id;
private Cla cla;
public void setName(String name){
this.name = name;
}
public void setId(String id){
this.id= id;
}
public void setCla(Cla cla){
this.cla = cla;
}
public String getId(){
return id;
}
public String getName(){
return name;
}
public Cla getCla(){
return cla;
}
@Override
public String toString(){
return "name = " + name + " id = " + id + " cla = " +cla;
}
}

3)demo测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class demo_1 {
@Test
public void test1(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("UserBean.xml");
Person person = applicationContext.getBean(Person.class);
System.out.println(person);
}
}

2.byType

1)xml配置文件

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
<?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" xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

<context:property-placeholder location="jdbc.properties"/>

<bean id="root" class="Root" scope="prototype"
p:name="root" p:driveName="smg" p:password="root" p:url="path:url"/>

<!-- <bean id="cla" class="Cla">-->
<!-- <constructor-arg name="cla" value="aa"/>-->
<!-- </bean>-->
byType是通过检索class类来实现依赖注入,如果存在多个claBean对象,会报错
如果不存在claBean对象则会null
<bean id="cla1" class="Cla">
<!-- 需要有对应的get_xx和set_xx方法-->
<property name="cla" value="bb"/>
</bean>

<bean id="person" class="Person" autowire="byType">
<property name="name" value="zhangsan"/>
<property name="id" value="001"/>
</bean>

</beans>

其余和byName相同

Spring IOC基于注解的开发

IOC是帮助开发者创建项目中的需要的Bean对象,同时完成Bean之间的依赖注入,DI实现该功能有两种方式

1.基于xml配置

2.基于注解 基于注解还有两步操作

1)配置自动扫包 2)添加注解

配置xml文件

1
2
3
4
5
6
7
8
9
10
11
<?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" xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

<!-- <context:property-placeholder location="jdbc.properties"/>-->

<context:component-scan base-package="Spring"/>

</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
34
35
36
37
38
39
package Spring;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component(value="person")
public class Person {
@Autowired
@Qualifier("Moon")
public Spring.Moon moon;
@Value("zhangsan")
public String name;
@Value("001")
public String id;
public void setName(String name){
this.name = name;
}
public void setId(String id){
this.id = id;
}
public void setMoon(Spring.Moon moon){
this.moon = moon;
}
public String getName(){
return name;
}
public String getId(){
return id;
}
public Spring.Moon getMoon(){
return moon;
}
@Override
public String toString(){
return "name = " + name + " id = " + id + " moon = " + moon;
}
}

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
package Spring;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component("Moon")
public class Moon {
@Value("lisi")
public String name;
@Value("1e9")
public String distance;
public void setName(String name){
this.name = name;
}
public void setDistance(String distance){
this.distance = distance;
}
public String getName(){
return name;
}
public String getDistance(){
return distance;
}
@Override
public String toString(){
return "name = " + name + " distance = " + distance;
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package Spring;

import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class demo_1 {
@Test
public void test1(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("UserBean.xml");
Spring.Person person = applicationContext.getBean(Spring.Person.class);
System.out.println(person);
//String[] bean = applicationContext.getBeanDefinitionNames();
//for(String s : bean)
// System.out.println(s);
}
}

这里再补一个依赖类的写法

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
package Spring;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component("Moon")
public class Moon {
@Value("lisi")
public String name;
@Value("19")
public Integer distance;
public void setName(String name){
this.name = name;
}
public void setDistance(String distance){
this.distance = Integer.getInteger(distance);
}
public String getName(){
return name;
}
public Integer getDistance(){
return distance;
}
@Override
public String toString(){
return "name = " + name + " distance = " + distance;
}
}

@Value内的相当于是bean里面的属性,直接写到了属性里面,然后调用setxx方法,完成赋值

@Autowired依赖注入

@Qualifier将依赖注入改为byName。默认是byType

xml配置文件里面是扫包,然后读取里面的类,根据注解去完成Bean对象的创建

依赖类的@Component和主类中的@Qualifier内的名称要相符,如果不写Qualifier,就会通过class来找

Spring AOP

AOP面向切面编程

OOP面向对象编程,从另一个维度抽取出对象


Spring笔记
http://example.com/2023/10/25/spring/
作者
smg
发布于
2023年10月25日
许可协议