前言
Spring框架的介绍
1.Spring框架的概述:
- Spring是一个开放源代码的设计层面框架,它解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用。
- Spring是于2003 年兴起的一个轻量级的Java开发框架,由Rod Johnson在其著作Expert One-On-One J2EE.Development and Design中阐述的部分理念和原型衍生而来。
- 它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。
- Spring的核心是控制反转(IOC)和面向切面(AOP)。简单来说,Spring是一个分层的JavaSE/EEfull-stack(一站式) 轻量级开源框架。
2.Spring框架的优点
- 方便解耦,简化开发,Spring就是一个大工厂,可以将所有对象创建和依赖关系维护,交给Spring管理,这也是IOC的作用。
- AOP编程的支持,Spring提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能。
- 声明式事务的支持,只需要通过配置就可以完成对事务的管理,而无需手动编程。
- 方便程序的测试,Spring对Junit4支持,可以通过注解方便的测试Spring程序。
- 方便集成各种优秀框架,Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts2、Hibernate、MyBatis等)的直接支持。
- 降低JavaEE API的使用难度,Spring 对JavaEE开发中非常难用的一些API(JDBC、JavaMail等),都提供了封装,使这些API应用难度大大降低。
我们学习Spring 主要学习Spring的两大点:
1.IOC(控制权反转)
2.AOP(面向切面编程)
接下来我们就IOC,进行讨论,想要了解AOP的小伙伴们,请见小编的Spring AOP一文spring AOP-CSDN博客
什么是IOC
用一句通俗的话来讲就是把创建对象的过程交给Spring 框架进行管理。
回顾一下我们以前创建对象的方法,有new 构造器()或者反射。
为什么会有IOC技术
为了降低代码的耦合度
在这里就好像一个大齿轮一样,三个紧密相连,如果其中一个损坏,那么剩下的两个很难运行
这时候我们就需要一个“”中间人”。在程序启动的时候,自动把a,b,c对象生成,并且封装在一个容器当中,需要用到时候就在类里面调用。
IOC实操
1.导入相关依赖
<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>
2.编写Spring核心的配置文件
在resources目录下创建applicationContext.xml的配置文件,名称是可以任意的,但是一般都会使用默认名称。(小编写的是Application.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">
<!--IOC管理bean-->
<!--id:类的唯一标识符 class:类的全路径名-->
<bean id="demo" class="com.qcby.service.Demo" />
</beans>
3.Spring对对象的管理
1)配置文件创建对象
test类当中:
// 传统创建对象的方法
@Test
public void run(){
Demo2 demo = new Demo2();
demo.hello();
}
@Test
// Spring创建对象的方法
public void run_spring(){
//创建Spring工厂,加载配置文件
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("Application.xml");
//获取bean对象
Demo2 demo2 = (Demo2) applicationContext.getBean("demo2");
demo2.hello();
applicationContext.getBean("user");
}
demo2.Hello 调用相关方法
applicationContext.getBean("user") 获取user对象
Application.xml 文件:
<!-- id是唯一标识符,class跟的是类的全路径名,可以通过反射的方式创建对象-->
<bean id="demo2" class="com.qcby.service.Demo2"/>
<bean id="user" class="com.qcby.service.User"/>
先去加载xml文件,在xml文件当中加载做好的相关配置(映射扫描生成想要的对象)
2)配置文件注入属性
set方法注入属性
属性、数组、集合等的set注入
类user2:
import java.util.List;
import java.util.Map;
public class User2 {
private int age;
private String name;
private Demo2 demo2;
private String str;
private List<String> list;
private Map<String,String> map;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Demo2 getDemo2() {
return demo2;
}
public void setDemo2(Demo2 demo2) {
this.demo2 = demo2;
}
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
public Map<String, String> getMap() {
return map;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
@Override
public String toString() {
return "User2{" +
"age=" + age +
", name='" + name + '\'' +
", demo2=" + demo2 +
", str='" + str + '\'' +
", list=" + list +
", map=" + map +
'}';
}
Application.xml:
<!-- 属性注入-->
<!-- 使用property完成属性注入-->
<!-- name 类里面的属性名称-->
<!-- value 向属性注入值-->
<!-- ref 对象映射-->
<bean id="user2" class="com.qcby.service.User2">
<property name="age" value="20"/>
<property name="name" value="张三"/>
<property name="demo2" ref="demo2"/>
<property name="str" >
<array>
<value>张三</value>
<value>李四</value>
<value>王五</value>
</array>
</property>
<property name="list">
<list>
<value>熊大</value>
<value>熊二</value>
<value>光头强</value>
</list>
</property>
<property name="map">
<map>
<entry key="张三" value="法外狂徒"/>
<entry key="星辰" value="小编本身"/>
</map>
</property>
</bean>
构造器方法注入属性
Application.xml
<bean id="demo2" class="com.qcby.service.Demo2"/>
<bean id="user2" class="com.qcby.service.User2">
<constructor-arg name="age" value="20"/>
<constructor-arg name="name" value="张三"/>
<constructor-arg name="demo2" ref="demo2"/>
<constructor-arg name="str">
<array>
<value>张三</value>
<value>李四</value>
<value>王五</value>
</array>
</constructor-arg>
<constructor-arg name="list" >
<list>
<value>熊大</value>
<value>熊二</value>
</list>
</constructor-arg>
<constructor-arg name="map">
<map>
<entry key="abc" value="de"/>
<entry key="cba" value="ed"/>
</map>
</constructor-arg>
</bean>
User2
import java.util.Arrays;
import java.util.List;
import java.util.Map;
public class User2 {
private int age;
private String name;
private Demo2 demo2;
private String[] str;
private List<String> list;
private Map<String,String> map;
//利用构造器赋值
public User2(int age, String name, Demo2 demo2, String[] str, List<String> list, Map<String, String> map) {
this.age = age;
this.name = name;
this.demo2 = demo2;
this.str = str;
this.list = list;
this.map = map;
}
@Override
public String toString() {
return "User2{" +
"age=" + age +
", name='" + name + '\'' +
", demo2=" + demo2 +
", str=" + Arrays.toString(str) +
", list=" + list +
", map=" + map +
'}';
}
测试:
@Test
public void run_set(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("Application.xml");
User2 user2 = (User2) applicationContext.getBean("user2");
System.out.println(user2.toString());
}
3)注解方式创建对象
1.什么是注解
- 注解是代码的特殊标记,格式:@注解名称(属性名称=属性值,属性名称=属性值...)
- 使用注解,注解作用在类上面,方法上面,属性上面
- 使用注解的目的:简化XML配置
2.Spring针对Bean管理中创建对象提供的注解(都可以用来创建bean实例)
@Component 普通的类
@Controller 表现层
@Service 业务层
@Repository 持久层
可以在配置文件里面加上@Bean也可以交给spring去管理
3.用注解的功能
配置文件
<?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:aop="http://www.springframework.org/schema/aop"
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 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 配置固定要扫描的包-->
<context:component-scan base-package="com.qcby.service"/>
</beans>
在需要管理的类上增加Component注解
import org.springframework.stereotype.Component;
@Component(value = "demo2")
public class Demo2 {
public void hello(){
System.out.println("Hello,world!");
}
}
编写实现类
@Test
public void run_0(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("Application.xml");
//ClassPathXmlApplicationContext 括号里跟的是相对路径 FileSystemXmlApplicationContext 括号里跟的是绝对路径
Demo2 demo2 = (Demo2) applicationContext.getBean("demo2");
demo2.hello();
}
4)注解方式注入属性
@Value 用于注入普通类型(String,int,double等类型)
@Autowired 默认按类型进行自动装配(引用类型)
@Qualifier 不能单独使用必须和@Autowired一起使用,强制使用名称注入
@Resource Java提供的注解,也被支持。使用name属性,按名称注入
// 默认当前类名就是ID名称,首字母小写
@Component(value = "c")
// @Controller
// @Service(value = "c")
// @Repository(valu = "c")
public class Car {
// 注解注入值,属性set方法是可以省略不写的。
// 只有一个属性,属性的名称是value,value是可以省略不写的
@Value("大奔2")
private String cname;
@Value(value = "400000")
private Double money;
// 也不用提供set方法
// 按类型自动装配的注解,和id名称没有关系
@Autowired
// 按id的名称注入,Qualifier不能单独使用,需要Autowired一起使用。
// @Qualifier(value = "person")
// @Resource Java提供的注解,按名称注入对象,属性名称是name
// @Resource(name = "person")
private Person person;
@Override
public String toString() {
return "Car{" +
"cname='" + cname + '\'' +
", money=" + money +
", person=" + person +
'}';
}
}
@Controller
//@Component(value = "person")
public class Person {
@Value("张三")
private String pname;
@Override
public String toString() {
return "Person{" +
"pname='" + pname + '\'' +
'}';
}
}
@Test
public void run1(){
// 工厂
ApplicationContext ac = new
ClassPathXmlApplicationContext("applicationContext.xml");
// 获取对象
Car car = (Car) ac.getBean("c");
System.out.println(car);
}
IOC技术总结
ApplicationContext 接口,工厂的接口,使用该接口可以获取到具体的Bean对象。该接口下有两个具体的实现类。
SpringCloud 配置中心
ClassPathXmlApplicationContext,加载类路径下的Spring配置文件。
FileSystemXmlApplicationContext,加载本地磁盘下的Spring配置文件。
小编提醒
Spring IOC bean 默认是单例的,在IOC容器中只会存在一个bean的实例,无论一次还是多次调用,始终指向的是同一个bean对象
创建了两个对象:最后实际调用的还是同一个对象,从输出的地址相同可以看出
如果想变成多例,在配置文件里面bean标签scope属性加上参数控制单多例,也可以加上一个注解,也是scope属性。