Spring Framework
kecho

Spring Framework 是一个功能强大的 Java 应用程序框架,旨在提供高效且可扩展的开发环境。它结合了轻量级的容器和依赖注入功能,提供了一种使用 POJO 进行容器配置和面向切面的编程的简单方法,以及一组用于 AOP 的模块。

Spring 两大核心机制:

  • IoC(控制反转):工厂模式
  • AOP(面向切面编程):代理模式

开发步骤

1、创建 Maven 工程,在 pom.xml 导入依赖:

1
2
3
4
5
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-context</artifactId>
<version>6.2.4</version>
</dependency>

2、在 resources 路径下创建 spring.xml

1
2
3
4
5
6
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="student" class="com.kecho.entity.Student"/>
</beans>

3、获取 IoC 容器中已经创建的对象:

1
2
3
4
5
6
7
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
// 通过 bean id 获取,返回值需要强制类型转换
Student student = (Student) context.getBean("student");

// 也可以通过类名获取,但要确保容器中只有一个该类型的 bean
// Student student = context.getBean(Student.class);
System.out.println(student.toString());

常用标签

bean

bean 标签用于创建一个对象,id 是唯一标识,class 是完全限定类名,name 可以同时取多个别名,别名之间可以使用空格或逗号或分号分隔。

1
<bean id="student" class="com.kecho.entity.Student" name="student1 student2 student3"/>

alias

alias 可用于配置别名,alias 的 name 对应需要取别名的 bean 的 id。

1
2
<bean id="student" class="com.kecho.entity.Student"/>
<alias name="student" alias="stuNew" />

import

import 用于导入其它配置文件。

1
2
<import resource="beans1.xml"/>
<import resource="beans2.xml"/>

创建顺序

IoC 容器默认情况下是通过 spring.xml 中 bean 的配置顺序来决定创建顺序的,配置在前⾯的 bean 会先创建。在不更改配置顺序的前提下,通过 depends-on 来设置 bean 之间的依赖关系,从而调整 bean 的创建顺序。

1
2
<bean id="student" class="com.kecho.entity.Student" depends-on="cat"/>
<bean id="cat" class="com.kecho.entity.Cat"/>

上述代码的结果是先创建 Cat,再创建 Student 对象。

创建方式

IoC 容器通过读取 spring.xml 配置文件,按照顺序加载 bean 标签来创建对象,相当于替代了手动去 new 一个对象的过程,而创建对象的方式主要有两种:构造函数和 Setter 方法。

通过构造函数

IoC 容器通过对应构造函数去创建对象,这也要求实体类必须有对应的构造函数。

  • 无参构造函数(实体类必须有无参构造函数)
1
<bean id="student" class="com.kecho.entity.Student"></bean>
  • 有参构造函数(实体类必须有相同参数列表的有参构造函数)
1
2
3
4
5
<bean id="student" class="com.kecho.entity.Student">
<constructor-arg name="id" value="1"/>
<constructor-arg name="name" value="kecho"/>
<constructor-arg name="age" value="18"/>
</bean>

使用 name 时,参数顺序必须和构造函数中的参数顺序保持一致,其中 String 类型会自动转 int 类型(实体类 Student 中的 id 和 age 均为 int 类型)。

你也可以使用 index 来避免顺序不一致导致可能出现的问题:

1
2
3
4
5
<bean id="student" class="com.kecho.entity.Student">
<constructor-arg index="1" value="kecho"/>
<constructor-arg index="2" value="18"/>
<constructor-arg index="0" value="1"/>
</bean>

还可以使用 type 根据参数类型来匹配构造函数创建 bean(如果有多个有参构造函数,通过参数类型无法匹配到唯一的构造函数时会报错):

1
2
3
4
5
<bean id="student" class="com.kecho.entity.Student">
<constructor-arg type="int" value="1"/>
<constructor-arg type="java.lang.String" value="kecho"/>
<constructor-arg type="int" value="18"/>
</bean>

通过 Setter 方法

IoC 容器通过 Setter 方法去创建对象,这要求对应字段在实体类中必须有对应的 Setter 方法。

1
2
3
4
5
<bean id="student" class="com.kecho.entity.Student">
<property name="id" value="1"/>
<property name="name" value="kecho"/>
<property name="age" value="18"/>
</bean>

如果我想把 name 的值设置为 <小二>,因为字符串包含了特殊字符,应该改用 CDATA 格式:

1
2
3
4
5
6
7
<bean id="student" class="com.kecho.entity.Student">
<property name="id" value="1"/>
<property name="name">
<value><![CDATA[<小二>]]]></value>
</property>
<property name="age" value="18"/>
</bean>

两种创建方式的写法非常相似,主要是 constructor-argproperty 的不同,接下来的示例主要以 Setter 方法为主,构造器注入同理。

依赖注入

DI 是指 bean 之间的依赖注入,用于设置对象之间的级联关系。此时应该改用 ref 而不能改用 value,否则会抛出类型转换异常。除了 ref,还有数组、 List、Set、Map、Properties 类型,下面将使用 Setter 方式注入展示各种类型的写法:

实体类 Student:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class Student {
private String name;
private Cat cat;
private String[] books;
private List<String> hobbys;
private Set<String> games;
private Map<String,String> card;
private String spouse;
private Properties info;
}

spring.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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<bean id="cat" class="com.kecho.entity.Cat"/>
<bean id="student" class="com.kecho.entity.Student">
<!-- 普通值注入 value -->
<property name="name" value="张三" />
<!-- 引用注入 ref -->
<property name="cat" ref="cat"/>
<!-- 数组 -->
<property name="books">
<array>
<value>红楼梦</value>
<value>西游记</value>
</array>
</property>
<!-- List -->
<property name="hobbys">
<list>
<value>听歌</value>
<value>敲代码</value>
</list>
</property>
<!-- Set -->
<property name="games">
<set>
<value>LOL</value>
<value>王者荣耀</value>
</set>
</property>
<!-- Map -->
<property name="card">
<map>
<entry key="身份证" value="123456123412121234"/>
</map>
</property>
<!-- null -->
<property name="spouse">
<null/>
</property>
<!-- Properties -->
<property name="info">
<props>
<prop key="学号">111111</prop>
<prop key="性别"></prop>
</props>
</property>
</bean>

上面如果改用构造器注入又改怎么写呢?只需要将 property 改成 constructor-arg 即可。

命名空间

c 命名空间

c 命名空间对应构造器注入。

使用 c 命名空间应在 xml 头部引入约束:xmlns:c="http://www.springframework.org/schema/c"

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

<bean id="cat" class="com.kecho.entity.Cat" c:name="咪咪"/>
<bean id="student" class="com.kecho.entity.Student"
c:name="kecho" c:id="1" c:age="18" c:cat-ref="cat"/>
</beans>

p 命名空间

p 命名空间对应 Setter 方法注入。

使用 p 命名空间应在 xml 头部引入约束:xmlns:p="http://www.springframework.org/schema/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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

<bean id="cat" class="com.kecho.entity.Cat" p:name="咪咪"/>

<bean id="student" class="com.kecho.entity.Student"
p:name="kecho" p:id="1" p:age="18" p:cat-ref="cat"/>
</beans>

作用域

bean 是根据 scope 来⽣成,表示 bean 的作⽤域,scope 有4种类型:

  • singleton,单例,表示通过容器获取的对象是唯⼀的,默认值。
  • prototype,原型,表示通过容器获取的对象是不同的。
  • request,请求,表示在⼀次 HTTP 请求内有效。
  • session,会话,表示在⼀个⽤户会话内有效。

requset,session 适⽤于 Web 项⽬。

singleton 模式下,只要加载 IoC 容器,⽆论是否从 IoC 中取出 bean,配置⽂件中的 bean 都会被创建。prototype 模式下,如果不从 IoC 中取 bean,则不创建对象,取⼀次 bean,就会创建⼀个对象。

1
<bean id="student" class="com.kecho.entity.Student" scope="prototype"/>

也可以通过对类添加注解 @Scope("prototype") 来实现同样功能。

懒加载

默认情况下,ApplicationContext 的实现会急切地创建和配置所有的单例 bean,你可以通过将 bean 定义标记为懒加载来阻止单例 bean 的预实例化。懒加载的 bean 告诉 IoC 容器在第一次被请求时创建一个 bean 实例,而不是在启动时。

1
<bean id="student" class="com.example.Student" lazy-init="true"/>

当懒加载 bean 是被未懒加载的单例 bean 所依赖时,ApplicationContext 会在启动时创建懒加载 bean。

你也可以通过使用 <beans> 元素上的 default-lazy-init 属性来控制容器级的懒加载:

1
2
3
<beans default-lazy-init="true">
<!-- no beans will be pre-instantiated... -->
</beans>

读取外部资源

实际开发中,数据库的配置⼀般会单独保存到后缀为 properties 的⽂件中,⽅便维护和修改,如果使⽤ Spring 来加载数据源,就需要在 spring.xml 中读取 properties 中的数据,这就是读取外部资源。

jdbc.properties

1
2
3
4
user = root
password = root
url = jdbc:mysql://localhost:3306/library
driverName = com.mysql.cj.jdbc.Driver

spring.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?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="classpath:jdbc.properties"/>
<!-- SpEL -->
<bean id="dataSource" class="com.southwind.entity.DataSource">
<property name="user" value="${user}"/>
<property name="password" value="${password}"/>
<property name="driverName" value="${driverName}"/>
<property name="url" value="${url}"/>
</bean>
</beans>

工厂方法

IoC 通过⼯⼚模式创建 bean 有两种⽅式:静态⼯⼚⽅法和实例⼯⼚⽅法,区别在于静态⼯⼚类不需要实例化,实例⼯⼚类需要实例化。

静态⼯⼚⽅法

1、创建 Car 类

1
2
3
4
5
6
@Data
@AllArgsConstructor
public class Car {
private Integer num;
private String brand;
}

2、创建静态⼯⼚类、静态⼯⼚⽅法

1
2
3
4
5
6
7
8
9
10
11
public class StaticCarFactory{
private static Map<Integer, Car> carMap;
static {
carMap = new HashMap<>();
carMap.put(1,new Car(1,"奥迪"));
carMap.put(2,new Car(2,"奥拓"));
}
public static Car getCar(Integer num){
return carMap.get(num);
}
}

3、spring.xml

1
2
3
<bean id="car1" class="com.example.factory.StaticCarFactory" factory-method="getCar">
<constructor-arg value="1"></constructor-arg>
</bean>

factory-method 指向静态⽅法,constructor-arg 的 value 属性是调⽤静态⽅法传⼊的参数。

实例⼯⼚⽅法

1、创建实例⼯⼚类、⼯⼚⽅法

1
2
3
4
5
6
7
8
9
10
11
public class InstanceCarFactory{
private Map<Integer, Car> carMap;
public InstanceCarFactory() {
carMap = new HashMap<>();
carMap.put(1,new Car(1,"奥迪"));
carMap.put(2,new Car(2,"奥拓"));
}
public Car getCar(Integer num){
return carMap.get(num);
}
}

2、spring.xml

1
2
3
4
<bean id="instanceCarFactory" class="com.example.factory.InstanceCarFactory"/>
<bean id="car2" factory-bean="instanceCarFactory" factory-method="getCar">
<constructor-arg value="2"></constructor-arg>
</bean>

静态⼯⼚⽅法创建 Car 对象,不需要实例化⼯⼚对象,因为静态⼯⼚的静态⽅法,不需要创建对象即可调⽤,spring.xml 中只需要配置⼀个 bean,即最终的结果 Car 即可。

实例⼯⼚⽅法创建 Car 对象,需要实例化⼯⼚对象,因为 getCar ⽅法是⾮静态的,就必须通过实例化对象才能调⽤,所以就必须要创建⼯⼚对象,spring.xml 中需要配置两个 bean,⼀个是⼯⼚ bean,⼀个是 Car bean。

自动装载

已知有两个实体类 Student 和 Cat。

Student:

1
2
3
4
5
6
7
8
@Data
@ToString
public class Student {
private int id;
private String name;
private int age;
private Cat cat;
}

Cat:

1
2
3
4
@Data
public class Cat {
private String name;
}

spring.xml:

1
2
3
4
5
6
7
8
<bean id="cat" class="com.kecho.entity.Cat">
<property name="name" value="咪咪"/>
</bean>
<bean id="student" class="com.kecho.entity.Student" autowire="byName">
<property name="id" value="1"/>
<property name="name" value="kecho"/>
<property name="age" value="18"/>
</bean>

最终得到 Student(id=1, name=kecho, age=18, cat=Cat(name=咪咪)),通过 autowire 可以自动地将 cat 装载到 student 中,即使未显示使用 ref 声明。

autowire 有两个值:byName 和 byType。

byName 会去找和 set 方法后面的值相同的 bean id 的 bean 自动装载,没有相同的则会报错。

byType 会去找和成员变量的数据类型相同的 bean 自动装载,如果容器中有两个相同类型的 bean 则会报错。

基于注解开发

使用注解开发需要:

  • 导入 context 约束
  • 配置注解支持

以下创建 bean 时没有使用到 Setter 方法。

手动创建

需要在 xml 中手动声明 bean:

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"
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:annotation-config/>

<bean id="cat" class="com.kecho.entity.Cat"/>
<bean id="student" class="com.kecho.entity.Student"/>

</beans>

此时可以使用 @Value 来设置属性值,使用 @Autowired 实现自动装载:

1
2
3
4
5
6
7
8
9
10
11
public class Student {
@Value("1")
private int id;
@Value("kecho")
private String name;
@Value("18")
private int age;

@Autowired
private Cat cat;
}

如果容器中没有这个 bean,@Autowired 会自动装配失败报错,可以使用 @Autowired(require = false) 来允许为空。

@Autowired 默认通过 byType 的方式来查找 bean,如果存在多个相同类型的 bean 也会无法自动装配,可以加上 @Qualifier(value = "beanid") 指定装配相应 id 的 bean,不带参数的 @Qualifier 默认指定 id 与属性名对应的 bean。

除了使用 @Autowired,Java 也有自己的注解 @Resource 实现相同的功能,也可以通过 @Resource(name = "bean id") 指定 bean id 来自动装配对应的 bean。

不同于 @Autowired 通过 byType 的方式来查找 bean,@Resource 默认通过 byName 的方式实现,如果找不到名字则通过 byType 的方式。

自动扫描

为了避免每个 bean 都需要自己手动去创建,可以配置扫描包:

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"
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:annotation-config/>
<context:component-scan base-package="com.kecho.entity"/>

</beans>

此时使用 @Component 来自动加载:

1
2
3
4
5
6
7
8
9
10
11
@Component
public class Student {
@Value("1")
private int id;
@Value("kecho")
private String name;
@Value("18")
private int age;
@Autowired(required = false)
private Cat cat;
}

除了 @Component 外,还有 @Repository@Service@Controller,这些注解的功能是一样的。

@Configuration

除了在 xml 配置文件中进行创建 bean、配置 context 约束、配置扫描包路径、配置注解的支持等等,还可以在 Java 类中进行配置:

MyConfig 类:

1
2
3
4
5
6
7
8
9
@Configuration // 相当于 beans 标签

public class MyConfig {
// 相当于一个 bean 标签
@Bean
public Student myStudent() { // Student 是 bean 的类型,myStudent 是 bean id
return new Student(1, "kecho", 18);
}
}

获取 bean:

1
2
3
// 不再通过 xml 文件获取上下文
ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
User user = context.getBean("myUser", User.class);

如果要自动扫描包来加载 bean,可以为 MyConfig 类设置 @ComponentScan("com.kecho.entity"),同时搭配 @Component 来自动加载 bean。如下:

MyConfig 类:

1
2
3
4
5
@Configuration
@ComponentScan("com.kecho.entity")
public class MyConfig {

}

Student 类:

1
2
3
4
5
6
7
8
9
10
11
@Component
public class Student {
@Value("1")
private int id;
@Value("kecho")
private String name;
@Value("18")
private int age;
@Autowired(required = false)
private Cat cat;
}

IoC

控制反转(Inversion of Control,简称 IoC)是一种设计思想,它将对象的创建和依赖关系的管理交给容器,而不是在代码中直接控制对象的创建和依赖关系。IoC 的核心思想是通过容器来管理对象的生命周期和依赖关系,从而实现对象之间的松耦合。

思想

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
/* dao */
public interface Fruit {
public void get();
}

/* daoImpl */
public class Apple implements Fruit {
public void get(){
System.out.println("get a Apple");
}
}

public class Banana implements Fruit {
public void get(){
System.out.println("get a Banana");
}
}

/* service */
public interface UserService {
public void getFruit();
}

/* serviceImpl */
public UserServiceImpl implements UserService {
private Fruit fruit = new Apple();

public void getFruit() {
fruit.get();
}
}

/* 主程序测试 */
public class MyTest {
public static void main(String[] args) {
UserService user = new UserServiceImpl();
user.getFruit(); // 输出 "get a Apple"
}
}

目前的控制权在业务层,每次用户需求改变时业务层也要跟着改变,即需要修改 UserServiceImpl 中的代码,如果工程量较大修改起来会很麻烦,而且修改代码容易对其它业务造成影响,可以考虑把控制权交给用户。

修改业务层的代码实现控制权的转换,程序由主动创建对象变为被动接收对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/* serviceImpl */
public class UserServiceImpl implements UserService {
private Fruit fruit;

// 利用 set 方法动态获取值的注入
public void setFruit(Fruit fruit) {
this.fruit = fruit;
}
public void getFruit() {
this.fruit.get();
}
}

/* 主程序测试 */
public class MyTest {
public static void main(String[] args) {
UserService user = new UserServiceImpl();
user.setFruit(new Apple());
//user.setFruit(new Banana());
user.getFruit();
}
}

在 spring.xml 中就是这么配置:

1
2
3
4
5
<bean id="apple" class="com.example.dao.Apple"/>
<bean id="banana" class="com.example.dao.Banana"/>
<bean id="userServiceImpl" class="com.example.service.UserServiceImpl">
<property name="fruit" ref="apple" />
</bean>

实现原理

核⼼技术点:XML 解析 + 反射机制

具体的思路:

1、根据需求编写 XML ⽂件,配置需要创建的 bean。

2、编写程序读取 XML ⽂件,获取 bean 相关信息,类、属性、id。

3、根据第 2 步获取到的信息,结合反射机制动态创建对象,同时完成属性的赋值。

4、将创建好的 bean 存⼊ Map 集合,设置 key - value 映射,key 就是 bean 中 id 值,value 就是 bean 对象。

5、提供⽅法从 Map 中通过 id 获取到对应的 value。

下面将自定义一个 MyClassPathXmlApplicationContext 类来实现。

首先需要在 pom.xml 引入依赖解析 xml 文件:

1
2
3
4
5
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>

自定义 MyClassPathXmlApplicationContext 类(这里假设 bean 的属性仅为 int 或 String 类型):

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
public class MyClassPathXmlApplicationContext implements ApplicationContext {
private Map<String, Object> iocMap;

public MyClassPathXmlApplicationContext(String path) {
iocMap = new HashMap<>();
parseXml(path);
}

public void parseXml(String path){

SAXReader reader = new SAXReader();
try {
Document document = reader.read("src/main/resources/" + path);
Element rootElement = document.getRootElement();
Iterator<Element> elementIterator = rootElement.elementIterator();
while (elementIterator.hasNext()) {
Element bean = elementIterator.next();
String beanID = bean.attributeValue("id");
String beanClassName = bean.attributeValue("class");
// 反射创建对象
Class myClass = Class.forName(beanClassName);
Constructor constructor = myClass.getConstructor();
Object object = constructor.newInstance();
// 给属性赋值
Iterator<Element> propertyIterator = bean.elementIterator();
while (propertyIterator.hasNext()) {
Element property = propertyIterator.next();
String propertyName = property.attributeValue("name");
String propertyValue = property.attributeValue("value");
// 获取 setter 方法
String methodName = "set" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
// 获取属性和方法
Field field = myClass.getDeclaredField(propertyName);
Method method = myClass.getMethod(methodName, field.getType());
Object value = propertyValue;
// 类型转换(这里假设 bean 的属性仅为 int 或 String 类型)
switch (field.getType().getName()){
case "java.lang.String":
break;
case "int":
case "java.lang.Integer":
value = Integer.parseInt(propertyValue);
break;
}
// 调用方法
method.invoke(object, value);
}
// 存入 Map
iocMap.put(beanID, object);
}
} catch (Exception e){
e.printStackTrace();
}
}

@Override
public Object getBean(String beanID) throws BeansException {
return iocMap.get(beanID);
}

// 省略其它需要重写的方法......
}

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

<bean id="student" class="com.kecho.entity.Student">
<property name="id" value="1"/>
<property name="name" value="kecho"/>
<property name="age" value="18"/>
</bean>

</beans>

测试类:

1
2
3
4
5
public static void main(String[] args  ){
ApplicationContext context = new MyClassPathXmlApplicationContext("spring.xml");
Student student = (Student) context.getBean("student");
System.out.println(student);
}

AOP