Spring官网:https://spring.io/
Spring是与2003年新奇的一个轻量级的java开发框架,它是为了解决企业引用开发的复杂新二创建的。Spring的核心是控制反转(IOC)和面向切面编程(AOP)。
Spring的主要作用是为代码“解耦”,降低代码间的耦合度。就是让对象和对象、模块和模块之间不是使用代码关联,而是通过配置来说明。即在Spring中说明对象或者模块的关系。
Spring根据代码的功能特点,使用IOC降低业务之间耦合度。IOC是的主业务在相互调用过程中,不用自己维护关系了,即不用自己创建需要使用的对象了。而是由Spring容器统一管理,自动“注入”,即就是自动赋值。使用AOP使得系统级服务得到最大的复用,且不用再由程序员手动将系统服务“混杂”到主业务逻辑中了,而是有Spring容器统一完成。
总之:Spring是一个容器,它是整合其他框架的框架,它的核心是IOC和AOP,它是由20多个模块组成。
耦合度:事物之间的关联程度。比如一块布耦合度非常高,用这块布做的衣服,耦合度就相对低一点。

Data Access(数据库整合):
JDBC, ORM, OXM, JMS, Transaction
Web(MVC Web 开发):
Web, Servlet, Portlet, Struts
AOP(切面编程)
AOP 框架: Aspects
JVM的代理:Instrumentation;
发送消息:Messaging;
Core Container(核心容器):
Beans: 管理 Beans
Core: Spring 核心
Context: 配置文件
ExpressionLanguage: SpEL 表达式
Test(Junit 整合)
控制反转IOC(Inversion of Control)是一种思想。由于Spring容器进行对象的创建和依赖注入。程序员取出直接使用。
正转:由程序员创建对象和依赖注入称为正转。
Student student = new Student();
student.setName("张三");
反转:由Spring容器创建对象和依赖注入称为反转,将控制权从程序员手中夺走。
<bean id="student" class="com.www.spring.demo.Student">
<property name="id" value="100"/>
<property name="account" value="张三"/>
bean>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>5.2.2.RELEASEversion>
dependency>
public class Admin {
private Integer id;
private String name;
private String num;
private String account;
public Admin(Integer id, String name, String num) {
this.id = id;
this.name = name;
this.num = num;
}
public Admin() {
}
public void doSome() {
System.out.println("执行此方法");
}
}
<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="admin" class="com.www.spring.modle.Admin"/>
beans>
public void test1(){
//使用Spring容器创建的对象 默认调用无参构造
//1.指定spring配置文件的名称
String config = "applicationContext.xml";
//2.创建表示spring容器的对象 ApplicationContext
//ApplicationContext 表示spring的容器
//ClassPathXmlApplicationContext:表示从类路径中加载spring的配置文件
ApplicationContext ac = new ClassPathXmlApplicationContext(config);//此时构造方法执行,创建对象
//在创建spring对象时会创建配置文件中所有的对象
//从容器中获取某个对象,要调用对象的方法
//getBean("配置文件中的bean的id值")
Admin admin = (Admin) ac.getBean("admin");
admin.doSome();
}
以上创建对象的过程虽然看起来过程复杂,且漫长,但是有没有发现此过程中我们是没有new过的,直接通过配置文件以及名字就创建对象了。
spring中常用到的方法:
public void test2(){
String config = "applicationContext.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(config);
//getBeanDefinitionCount():容器中定义的对象的个数
int nums = ac.getBeanDefinitionCount();
System.out.println("容器中定义的对象的个数"+nums);
//getBeanDefinitionNames():容器中定义的每个对象的名字
String names[] = ac.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
}
创建非自定的对象:
<bean id="mydate" class="java.util.Date"/>
di:创建对象并给属性赋值。
两种实现方法:
<bean id="student" class="com.www.spring.modle.Student">
<property name="name" value="张三"/>
<property name="id" value="1"/>
<property name="num" value="1001"/>
bean>
<bean id="student1" class="com.www.spring.modle.Student">
<property name="name" value="张四"/>
<property name="id" value="2"/>
<property name="num" value="1002"/>
<property name="admin" ref="admin"/>
bean>
<bean id="admin" class="com.www.spring.modle.Admin">
<property name="name" value="admin"/>
<property name="id" value="1"/>
bean>
使用constructor-arg标签
一个constructor-arg标签表示构造方法的一个参数
name:属性表示构造方法的形参名
index:表示构造方法的参数的位置,从左往右 0 1 2 3…
ref:构造方法的形参是引用类型
value:构造方法的形参是简单类型
<bean id="student2" class="com.www.spring.modle.Student">
<constructor-arg name="name" value="张武">constructor-arg>
<constructor-arg name="num" value="1003">constructor-arg>
<constructor-arg name="admin" ref="admin">constructor-arg>
bean>
<bean id="student3" class="com.www.spring.modle.Student">
<constructor-arg index="1" value="1004">constructor-arg>
<constructor-arg index="0" value="张流">constructor-arg>
<constructor-arg index="2" ref="admin">constructor-arg>
bean>
<bean id="student4" class="com.www.spring.modle.Student">
<constructor-arg value="张流">constructor-arg>
<constructor-arg value="1004">constructor-arg>
<constructor-arg ref="admin">constructor-arg>
bean>
引用类型的自动注入:Spring框架根据某些规则给引用类型赋值。不用自己给引用类型赋值使用的规则常用的是byName,byType。
<bean id="student5" class="com.www.spring.modle.Student" autowire="byName">
<property name="name" value="张其"/>
<property name="id" value="7"/>
<property name="num" value="1007"/>
bean>
2.byType(按类型注入):java类中引用类型的数据类型和spring容器中(配置文件)bean的class属性是同源关系的,这样的bean可以赋值给引用类型
同源的意思:
注 : byType中, 在xml中声明的bean只能有有一个符合条件的
<bean id="student6" class="com.www.spring.modle.Student" autowire="byName">
<property name="name" value="张其"/>
<property name="id" value="7"/>
<property name="num" value="1007"/>
bean>
当类的声明非常多的时候,将所有的声明都放在一个配置文件中是不可取的;在做项目的时候,多人使用同一个配置文件时,是及其容易出现错误的;
多配制文件的优势:
多文件的分配方式:
具体操作:
<bean id="student" class="com.www.spring.modle.Student" autowire="byType">
<property name="name" value="张其"/>
<property name="id" value="7"/>
<property name="num" value="1007"/>
bean>
<bean id="admin" class="com.www.spring.modle.Admin">
<property name="name" value="admin"/>
<property name="id" value="1"/>
bean>
<import resource="classpath:be01/spring-Student.xml"/>
<import resource="classpath:be01/spring-Admin.xml"/>
public void test4(){
//加载总文件
String config = "be01/spring-Total.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(config);
Student student = ac.getBean("student",Student.class);
System.out.println(student);
}
以上主配置文件中import可以使用通配符
<import resource="classpath:be01/spring-*.xml"/>
<context:component-scan base-package="com.www.spring"/>
添加完component-scan标签后配置文件会多出:
xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
//写法1:
//@component(value = “admin)
//等同于
//写法2:省略value
//@component(指定对象的名称)
//写法3:不指定对象的名称,由spring默认名称:首字母小写的类名。
//@component
@Component(value = "admin")//等同于
public class Admin {
private Integer id;
private String name;
private String num;
private String account;
public Admin(String name, String num, String account) {
this.name = name;
this.num = num;
this.account = account;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNum() {
return num;
}
public void setNum(String num) {
this.num = num;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public Admin(Integer id, String name, String num) {
this.id = id;
this.name = name;
this.num = num;
}
public Admin() {
System.out.println("无参构造方法");
}
public void doSome() {
System.out.println("执行此方法");
}
@Override
public String toString() {
return "Admin{" +
"id=" + id +
", name='" + name + '\'' +
", num='" + num + '\'' +
", account='" + account + '\'' +
'}';
}
}
@Respotory:(用在持久层上面的)与@component功能一致,创建的是dao对象,dao对象是能访问数据库的。
@service:(用在业务逻辑层类上面的) 与@component功能一致,放在service的实现类上面,创建service对象,service对象是做业务处理,可以有事务功能的。
@controller:(用在控制器上面的)与@component功能一致,放在控制器(处理器)类的上面,创建控制器对象的,控制器对象,能够接受用户提交的参数,显示请求结果。
以上注解与@component功能一致,语法相同,但是各自还有额外功能,他们是给项目分层的。
/*
可以写在属性定义的上面,无需set方法,比较常用
也可以写在set方法上面
*/
@Component("student")
@Data
public class Student {
private Integer id;
@Value( "张吧")
private String name;
@Value(value = "1008")
private String num;
private Admin admin;
public Student() {
}
public Student(String name, String num, Admin admin) {
this.name = name;
this.num = num;
this.admin = admin;
}
}
@Autowired
private Admin admin;
如果使用byName的方式:需要借助@Qualifier(value = “对象名称”)
@Autowired
@Qualifier(value = "admin")//这里的admin是Admin类创建对象的名称,相当于bean的id
private Admin admin;//这里的admin是Student类中属性名
//两个注解不分先后
@Autowired中有一个属性:required
required=true :表示引用类型赋值失败,程序终止,程序报错
required=false:表示引用类型赋值失败,程序不终止,引用类型为null
先使用byName自动注入,如果byName赋值失败,再改用byType自动注入。
只想使用byName一种方式时:
@Resource(name = "admin")
private Admin admin;
配置文件:
优点:代码和值是完全分开的,对于经常改值的,可以用配置文件;
缺点:语法繁杂,与代码完全分开,浏览源代码时,不知道对应的值。
注解:
优点:快捷方便,速度快,代码简洁;不经常改变的用注解比较方便
缺点:硬编入java代码中,修改后需要重新编译