Spring框架基础
Spring框架基础
- 创建Spring
- Spring IOC容器
- 基于xml配置文件的方式实现Bean管理和注入属性
- 基于get set 方法
- 基于构造函数
- 基于注解的方式实现Bean管理和注入属性
- 用注解的方式创建对象
- 用注解的方实现属性注入
- 纯注解开发
创建Spring
创建maven工程,配置maven环境
在 pom.xml 中导入坐标依赖,org.springframework 是 Spring 框架的核心依赖,commons-logging 和 log4j 是和日志有关,junit 是Java 单元测试框架
<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.0.2.RELEASE</version></dependency><dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.2</version></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.12</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency>
</dependencies>
编写demo具体的实现方法
package com.qcby;public class Demo {public void hello() {System.out.println("hello world");}
}
创建Spring核心的配置文件
编写 Spring 核心的配置文件,将创建 demo 对象的权利交给 Spring 框架,IOC 管理 bean
<bean>
是 Spring XML 配置中声明 Bean 的核心标签,每个 <bean>
标签对应一个由 Spring 容器管理的对象,其中 id 是 Bean 的唯一标识,后续可以通过这个 id 从容器中获取对象,class 指定了这个 Bean 的具体类型,值为类的全路径名
编写传统创建对象和通过Spring框架获取对象的测试方法:
import com.qcby.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class Test {//传统的创建对象的方式@org.junit.Testpublic void run(){Demo demo = new Demo();demo.hello();}//通过Spring框架获取对象@org.junit.Testpublic void run1(){ApplicationContext ac = new ClassPathXmlApplicationContext("Spring.xml");Demo demo = (Demo) ac.getBean("demo");demo.hello();}
}
运行结果分别为:
这体现了 Spring IoC 的核心思想:对象的创建和管理由容器负责,开发者只需从容器中获取对象即可,无需手动 new 实例或管理依赖。
Spring的核心是控制反转(IOC)和面向切面(AOP),IOC即控制反转,将创建对象的过程交给spring进行管理,AOP即面向切面,在不修改源代码的情况之下进行代码功能的增强。
我们现在来讨论一下IOC,AOP后面再进行详细描述
Spring IOC容器
IOC 即 Inverse of Control,控制反转,将对象的创建权力反转给Spring框架
Spring框架对Bean(对象)的管理图示:
为什么需要Spring IOC容器:在java当中一个类想要使用另一个类的方法,就必须在这个类当中创建这个类的对象,那么可能会出现如下情况,比如A类当中创建着B对象,B类当中有C对象,C类当中有A对象,这个如果一个类出了问题,那么可能会导致这个框架出现问题。Spring 将创建对象的权利给了IOC,在IOC当中创建了ABC三个对象,那么我们我们其他的类只需要调用集合,大大的解决了程序耦合性的问题。
Spring 提供了IOC容器的实现的两种方式:
- BeanFactroy:IOC容器是Spring内部的使用接口,不提供给开发人员使用
选要注意的是 BeanFactroy 加载配置文件的时候不会去创建对象,只有在使用对象的时候才会去创建对象
BeanFactory ac = new ClassPathXmlApplicationContext("Spring.xml");
- ApplicationContext:BeanFactory接口的子接口,提供了更多更强大的功能,一般由开发人员进行使用。需要注意的是 ApplicationContext 加载配置文件的时候就会创建对象
ApplicationContext ac = new ClassPathXmlApplicationContext("Spring.xml");
基于xml配置文件的方式实现Bean管理和注入属性
注入属性基于get set 方法、基于构造函数
基于get set 方法
Demo.java
package com.qcby;import java.util.Arrays;
import java.util.List;
import java.util.Map;public class Demo {private String name;private int age;private String sex;private double money;private User user;private String[] address;private List<String> phone;private Map<String,String> map;@Overridepublic String toString() {return "Demo{" +"name='" + name + '\'' +", age=" + age +", sex='" + sex + '\'' +", money=" + money +", user=" + user +", address=" + Arrays.toString(address) +", phone=" + phone +", map=" + map +'}';}public String[] getAddress() {return address;}public void setAddress(String[] address) {this.address = address;}public List<String> getPhone() {return phone;}public void setPhone(List<String> phone) {this.phone = phone;}public Map<String, String> getMap() {return map;}public void setMap(Map<String, String> map) {this.map = map;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public double getMoney() {return money;}public void setMoney(double money) {this.money = money;}public User getUser() {return user;}public void setUser(User user) {this.user = user;}
}
User.java
package com.qcby;public class User {
}
Spring.xml
使用property注入属性,name=类当中的属性名称,value=注入的值, ref=对象映射
<bean id="demo" class="com.qcby.Demo"><property name="name" value="张三"/><property name="age" value="18"/><property name="sex" value="男"/><property name="money" value="100.00"/><property name="user" ref="user"/><property name="address"><array><value>北京</value><value>上海</value></array></property><property name="phone"><list><value>123456</value><value>456789</value></list></property><property name="map"><map><entry key="1" value="张三"/><entry key="2" value="李四"/></map></property></bean><bean id="user" class="com.qcby.User"/>
基于构造函数
Spring 容器在实例化 Bean 时,确实主要通过Java 反射机制创建对象,而不是直接使用 new 关键字。Spring 容器加载配置文件或扫描注解,获取 Bean 的全类名,通过反射 API((Class.forName(“com.qcby.Demo”))加载类的字节码获取 Class 对象,然后根据配置确定要使用的构造函数(默认优先使用无参构造函数),之后通过反射调用构造函数(如 clazz.newInstance() 或 constructor.newInstance(参数))动态创建对象。
Demo.java
package com.qcby;import java.util.Arrays;
import java.util.List;
import java.util.Map;public class Demo {private String name;private int age;private String sex;private double money;private User user;private String[] address;private List<String> phone;private Map<String,String> map;@Overridepublic String toString() {return "Demo{" +"name='" + name + '\'' +", age=" + age +", sex='" + sex + '\'' +", money=" + money +", user=" + user +", address=" + Arrays.toString(address) +", phone=" + phone +", map=" + map +'}';}public Demo(String name, int age, String sex, double money, User user, String[] address, List<String> phone, Map<String, String> map) {this.name = name;this.age = age;this.sex = sex;this.money = money;this.user = user;this.address = address;this.phone = phone;this.map = map;}
}
Spring.xml
<bean id="demo" class="com.qcby.Demo"><constructor-arg name="name" value="张三"/><constructor-arg name="age" value="18"/><constructor-arg name="sex" value="男"/><constructor-arg name="money" value="100.00"/><constructor-arg name="user" ref="user"/><constructor-arg name="address"><array><value>北京</value><value>上海</value></array></constructor-arg><constructor-arg name="phone"><list><value>"123456"</value><value>"456789"</value></list></constructor-arg><constructor-arg name="map"><map><entry key="1" value="张三"/><entry key="2" value="李四"/></map></constructor-arg></bean><bean id="user" class="com.qcby.User"/>
基于注解的方式实现Bean管理和注入属性
什么是注解:注解是代码特殊标记,格式:@注解名称(属性名称=属性值,属性名称=属性值...)
,使用注解,注解作用在类、方法、属性上面,使用注解的目的是为了简化XML配置
用注解的方式创建对象
Spring针对Bean管理中创建对象提供的注解:@Component
@Controller
@Service
@Repository
上边四个的功能体现在 spring 当中不区分,都可以用来创建bean实例,但是在其他框架当中是有区分的
开启注解的扫描工作
<context:component-scan base-package="com.qcby"/>
用注解的方实现属性注入
@Value
用于注入普通类型(基本数据类型以及包装类类型)
@Autowired
默认按类型进行自动装配(引用数据类型)
@Qualifier
不能单独使用必须和@Autowired
一起使用,强制使用名称注入
@Resource
Java提供的注解,也被支持,使用name属性,按名称注入
需要注意的是注解的生效依赖于类被 Spring 容器管理
package com.qcby;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;import java.util.Arrays;@Service(value = "per")
public class Person {@Value(value = "张三")private String name;@Value(value = "18")private int age;@Autowired()private Animal animal;@Value("#{new String[]{'北京','上海'}}")private String[] address;@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +", animal=" + animal +", address=" + Arrays.toString(address) +'}';}
}
纯注解开发
纯注解的方式是微服务架构开发的主要方式,纯注解的目的是替换掉所有的配置文件。
需要注意的是要编写配置类
@Configuration
声明是配置类,@ComponentScan
扫描具体包结构的
package com.qcby;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;@Configuration
@ComponentScan(basePackages = "com.qcby")
public class Config {}