创建Maven工程,导入spring依赖
<dependency>
<groupid>org.springframework</groupid>
<artifactid>spring-context</artifactid>
<version>{spring版本号}</version>
</dependency>
lombok可以帮助开发者自动生成实体类相关的方法
假设实体类为Student
引入lombok依赖:
<dependency>
<groupid>org.projectlombok</groupid>
<artifactid>lombok</artifactid>
<version>{lombok版本号}</version>
</dependency>
import lombok.Data;
@Data
public class Student {
private Integer id;
private String name;
private Integer age;
}
@Data为自动生成实体类方法
也可以使用如下参数:
参数作用@Getter添加get方法@Setter添加set方法@NoArgsConstructor添加无参构造器@AllArgsConstructor添加有参构造器 创建一个对象: 原生Java写法:
public class Test {
public static void main(String[] args) {
Student student=new Student();
System.out.println(student.toString());
}
}
Spring写法:
在resource下创建一个文件spring.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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="student" class="test.Student">
</bean></beans>
IoC容器通过读取spring.xml配置文件加载bean标签来创建对象
调用API获取IoC中已经存在的对象
主类:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring.xml");
Student student= (Student) applicationContext.getBean("student");
System.out.println(student.toString());
}
}
IoC容器创建bean的两种方式:
- 无参构造函数
使用property给成员变量赋值,在spring.xml下:
<bean id="student" class="test.Student">
<property name="id" value="1"></property>
<property name="name" value="test"></property>
<property name="age" value="22"></property>
</bean>
- 有参构造函数
student类中添加了有参构造函数:
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class Student {
private Integer id;
private String name;
private Integer age;
}
使用constructor-arg给构造函数赋值
<bean id="student" class="test.Student">
<constructor-arg name="id" value="1"></constructor-arg>
<constructor-arg name="name" value="test"></constructor-arg>
<constructor-arg name="age" value="22"></constructor-arg>
</bean>
也可以不写name,构造函数会根据变量次序依次赋值:
<bean id="student" class="test.Student">
<constructor-arg value="1"></constructor-arg>
<constructor-arg value="test"></constructor-arg>
<constructor-arg value="22"></constructor-arg>
</bean>
DI指bean之间的依赖注入,设置对象之间的级联关系
用以下方法可以拿出所有bean名称:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring-di.xml");
String[] names= applicationContext.getBeanDefinitionNames();
for(String name:names)
{
System.out.println(name);
}
}
}
创建新的spring-di.xml文件,确立新的bean关系:
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- Classes-->
<bean id="classes" class="test.Classes">
<property name="id" value="1"></property>
<property name="name" value="t1"></property>
</bean>
<bean id="student" class="test.Student">
<property name="id" value="1"></property>
<property name="name" value="test"></property>
<property name="age" value="22"></property>
<property name="classes" ref="classes"></property>
</bean>
</beans>
Main方法:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring_di.xml");
Classes classes=(Classes) applicationContext.getBean("classes");
Student student=(Student) applicationContext.getBean("student");
System.out.println(classes.toString());
System.out.println(student.toString());
}
}
bean之间的级联需要使用ref属性完成映射,而不能直接使用value,否则会抛出类型转换异常。
换一种关系,班级实体类如下:
import lombok.Data;
import java.util.List;
@Data
public class Classes {
private Integer id;
private String name;
private List<student> studentList;
}
</student>
bean加入新的学生类后将新加的bean装到list中:
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- Classes-->
<bean id="classes" class="test.Classes">
<property name="id" value="1"></property>
<property name="name" value="t1"></property>
<property name="studentList">
<list>
<ref bean="student"></ref>
<ref bean="student2"></ref>
</list>
</property>
</bean>
<bean id="student" class="test.Student">
<property name="id" value="1"></property>
<property name="name" value="test"></property>
<property name="age" value="22"></property>
</bean>
<bean id="student2" class="test.Student">
<property name="id" value="2"></property>
<property name="name" value="test2"></property>
<property name="age" value="23"></property>
</bean>
</beans>
bean根据scope来表示bean的作用域,有四种类型:
- singleton,单例,表示通过Spring容器获取的对象是唯一的,默认值
- prototype,原型,表示通过Spring容器获取的对象是不同的
- request,请求,表示在一次Http请求内有效
- session,会话,表示在一个用户会话内有效
request、session适用于web项目
新建一个实体类User
import lombok.Data;
@Data
public class User {
private Integer id;
private String name;
}
配bean:
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" class="test.User">
<property name="id" value="1"></property>
<property name="name" value="test"></property>
</bean>
</beans>
执行主程序:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring_scope.xml");
User user1=(User) applicationContext.getBean("user");
User user2=(User) applicationContext.getBean("user");
System.out.println(user1==user2);
}
}
singleton模式,该模式下只要加载IoC容器,无论是否从IoC中取出bean,配置文件中的bean都会被创建
加作用域:
<bean id="user" class="test.User" scope="prototype">
<property name="id" value="1"></property>
<property name="name" value="test"></property>
</bean>
prototype模式,如果不从IoC中取bean,则不创建对象,取一次就会创建一个对象
Spring的继承不同于Java中的继承,区别:Java中的继承是针对于类的,Spring的继承是针对于对象bean的。
Spring的继承中,子bean可以继承父bean中的所有成员变量的值。
创建一个user2继承于user1:
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user1" class="test.User">
<property name="id" value="1"></property>
<property name="name" value="test"></property>
</bean>
<bean id="user2" class="test.User" parent="user1"></bean>
</beans>
主类:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring_scope.xml");
User user1=(User) applicationContext.getBean("user1");
User user2=(User) applicationContext.getBean("user2");
System.out.println(user1.toString());
System.out.println(user2.toString());
}
}
运行发现user2继承了user1的值
通过设置bean标签的parent属性建立继承关系,同时子bean可以覆盖父bean的值
不同的类的继承:
建一个Account类:
import lombok.Data;
@Data
public class Account {
private Integer id;
private String name;
}
bean:
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user1" class="test.User">
<property name="id" value="1"></property>
<property name="name" value="test"></property>
</bean>
<bean id="user2" class="test.User" parent="user1"></bean>
<bean id="account" class="test.Account" parent="user1"></bean>
</beans>
主类:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring_scope.xml");
User user1=(User) applicationContext.getBean("user1");
Account account=(Account) applicationContext.getBean("account");
System.out.println(user1.toString());
System.out.println(account.toString());
}
}
Spring的继承是针对对象的,所以子bean和父bean并不需要属于同一个数据类型,只要其成员变量列表一致即可。
用来设置两个bean的创建顺序。
IoC容器默认情况下是通过spring.xml中bean的配置顺序来决定创建顺序的,配置在前面的bean会先创建
在不更改spring.xml配置顺序的前提下通过设置bean之间以来顺序来调整bean的顺序
<bean id="user" class="test.User" depends-on="account"></bean>
<bean id="account" class="test.Account"></bean>
上述先创建account,再创建user
实际开发中,数据库配置一般会单独保存起来,保存到后缀为properties的文件中,方便维护和修改,如果使用Spring来加载数据源,就需要再spring.xml中读取properties中的数据,这就是读取外部资源。
需要在xml文件中加入:
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
<context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
必须加入上面几行不然报错!
所以得到下面的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" xmlns:context="http://www.springframework.org/schema/context" xsi:schemalocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--导入外部资源-->
<context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
<!--SpEL-->
<bean id="datasource" class="test.DataSource">
<property name="user" value="${user}"></property>
<property name="password" value="${password}"></property>
<property name="url" value="${url}"></property>
<property name="driverName" value="${driverName}"></property>
</bean>
</beans>
xml里必须引入:
xmlns:p="http://www.springframework.org/schema/p
p命名空间可以用来简化bean的配置:
以student和classes为例:
<bean id="classes" class="test.Classes" p:id="1" p:name="class1">
<bean id="student" class="test.Student" p:id="1" p:name="test" p:age="22" p:classes-ref="classes">
</bean></bean>
IoC通过工厂模式创建bean有两种方式:
- 静态工厂方法
- 实例工厂方法
区别在于静态工厂不需要实例化,实例工厂需要实例化
例:
创建Car类
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class Car {
private Integer num;
private String brand;
}
创建静态工厂类
import java.util.HashMap;
import java.util.Map;
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);
}
}
</integer,>
配bean
<bean id="car" class="test.factory.StaticCarFactory" factory-method="getCar">
<constructor-arg value="1"></constructor-arg>
</bean>
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import test.Car;
public class Test {
public static void main(String[] args) {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring_factory.xml");
Car car=(Car) applicationContext.getBean("car");
System.out.println(car.toString());
}
}
factory-method指向静态方法
constructor-arg的value属性是调用静态方法传入的参数
创建实例工厂类
import java.util.HashMap;
import java.util.Map;
public class InstanceCarFactory {
private static 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);
}
}
</integer,>
配bean
<!--实例工厂-->
<bean id="instanceCarFactory" class="test.factory.InstanceCarFactory"></bean>
<!--通过实例工厂获取Car-->
<bean id="car" factory-bean="instanceCarFactory" factory-method="getCar">
<constructor-arg value="2"></constructor-arg>
</bean>
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import test.Car;
public class Test {
public static void main(String[] args) {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring_factory.xml");
Car car=(Car) applicationContext.getBean("car");
System.out.println(car.toString());
}
区别:
静态工厂方法创建Car对象,不需要实例化工厂对象,因为静态工厂方法不需要创建对象即可调用。
实例工厂方法创建Car对象,需要实例化工厂对象,因为getCar方法是非静态的,就必须实例化对象才能调用,所以必须要创建工厂对象,spring.xml中需要配置两个bean,一个是工厂bean,一个是Car bean
spring.xml 是class+factory-method的形式是直接调用类中的方法
spring.xml是factory-bean+factory-method的形式则是调用工厂bean中的工厂方法,必须先创建工厂方法
自动装载是Spring提供的一种更加简便的方式来完成DI,不需要手动配置property,IoC容器会自动选择bean来完成注入
自动装载有两种方式:
- byName,通过属性名完成自动装载
- byType,通过属性对应的数据类型完成自动装载
例:
实体类:
import lombok.Data;
@Data
public class Person {
private Integer id;
private String name;
private Car car;
}
在spring.xml中配置Car和Person对应的bean,并且通过自动装载完成依赖注入。
<bean id="person" class="test.Person" autowire="byName">
<property name="id" value="1"></property>
<property name="name" value="test"></property>
</bean>
<bean id="car" class="test.Car">
<constructor-arg name="num" value="1"></constructor-arg>
<constructor-arg name="brand" value="奥迪"></constructor-arg>
</bean>
主类:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import test.Person;
public class Test {
public static void main(String[] args) {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring_autowire.xml");
Person person=(Person) applicationContext.getBean("person");
System.out.println(person.toString());
}
}
byType进行自动装载时,必须保证IoC中只有一个符合条件的bean,否则会抛出异常。
Spring IoC的作用是帮助开发者创建项目中所需要的bean,同时完成bean之间的依赖注入关系,DI。
实现该功能有两种方式:
- 基于xml配置
- 基于注解
基于注解两步操作:
- 配置自动扫包
- 添加注解
例:
建一个实体类,加入@Component标签:
import lombok.Data;
import org.springframework.stereotype.Component;
import javax.sql.DataSource;
@Data
@Component
public class Repository {
private DataSource dataSource;
}
将spring.xml加入扫描范围,自动扫包
<context:component-scan base-package="test"></context:component-scan>
主类运行便可注入
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import test.Repository;
public class Test {
public static void main(String[] args) {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring_annotation.xml");
Repository repository=(Repository) applicationContext.getBean("repository");
System.out.println(repository.toString());
}
}
配置自动扫包添加注解来注入,类首字母改成小写就是默认的id
换id名则在标签里写id名
@Component(value="id名")
将DataSource注入给Repository:
给Repository加@Autowired标签,@Qualifier是byName的形式注入,不加默认为byType
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Data
@Component
public class Repository {
@Autowired
@Qualifier(value = "ds")
private DataSource dataSource;
}
类DataSource并赋值:
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Data
@Component(value = "ds")
public class DataSource {
@Value("root")
private String user;
@Value("root")
private String password;
@Value("jdbc:mysql://localhost:3306/library")
private String url;
@Value("com.mysql.jdbc.Driver")
private String driverName;
}
表示将IoC中id为ds的bean注入到repository中
实体类中普通的成员变量(String、包装类)可以通过@Value注解进行赋值
等同于spring.xml中的
<bean id="ds" class="test.DataSource">
<property name="user" value="root"></property>
<property name="password" value="root"></property>
<property name="url" value="jdbc:mysql://localhost:3306/library"></property>
<property name="driverName" value="com.mysql.jdbc.Driver"></property>
</bean>
实际开发中会将程序分为三层:
- Controller
- Service
- Repositroy(DAO)
关系 Controller–>Service–>Repository
如下分别用xml方法和注解方法来演示该关系:
spring.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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="controller" class="com.test.controller.MyController">
<property name="myService" ref="service"></property>
</bean>
<bean id="service" class="com.test.service.Impl.MyServiceImpl">
<property name="myRepository" ref="repository"></property>
</bean>
<bean id="repository" class="com.test.repository.impl.MyrepositoryImpl"></bean>
</beans>
Controller类:
import com.test.service.MyService;
import lombok.Setter;
@Setter
public class MyController {
private MyService myService;
public String service(Double score){
return myService.doService(score);
}
}
Service接口及实现类:
接口:
public interface MyService {
public String doService(Double score);
}
实现类:
import com.test.repository.MyRepository;
import com.test.service.MyService;
import lombok.Setter;
@Setter
public class MyServiceImpl implements MyService {
private MyRepository myRepository;
public String doService(Double score) {
return myRepository.doReopository(score);
}
}
Repository接口及实现类:
接口:
public interface MyRepository {
public String doReopository(Double score);
}
实现类:
import com.test.repository.MyRepository;
public class MyrepositoryImpl implements MyRepository {
public String doReopository(Double score) {
String result="";
if(score<60){ result="不合格" ; } else if(score>=60&&score<=80) { result="及格" ; } else if(score>80)
{
result="优秀";
}
return result;
}
}
</=80)></60){>
主类:
import com.test.controller.MyController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring.xml");
MyController myController=applicationContext.getBean("controller",MyController.class);
String result=myController.service(new Double(77));
System.out.println(result);
}
}
spring.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" xmlns:context="http://www.springframework.org/schema/context" xsi:schemalocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--配置自动扫包-->
<context:component-scan base-package="com.test"></context:component-scan>
</beans>
Controller类:
import com.test.service.MyService;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Setter
@Component
public class MyController {
@Autowired
private MyService myService;
public String service(Double score){
return myService.doService(score);
}
}
Service接口及实现类:
接口:
public interface MyService {
public String doService(Double score);
}
实现类:
import com.test.repository.MyRepository;
import com.test.service.MyService;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Setter
@Component
public class MyServiceImpl implements MyService {
@Autowired
private MyRepository myRepository;
@Override
public String doService(Double score) {
return myRepository.doReopository(score);
}
}
Repository接口及实现类:
接口:
public interface MyRepository {
public String doReopository(Double score);
}
实现类:
import com.test.repository.MyRepository;
import lombok.Setter;
import org.springframework.stereotype.Component;
@Setter
@Component
public class MyrepositoryImpl implements MyRepository {
@Override
public String doReopository(Double score) {
String result="";
if(score<60){ result="不合格" ; } else if(score>=60&&score<=80) { result="及格" ; } else if(score>80)
{
result="优秀";
}
return result;
}
}
</=80)></60){>
主类:
import com.test.controller.MyController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring.xml");
MyController myController=applicationContext.getBean(MyController.class);
String result=myController.service(new Double(77));
System.out.println(result);
}
}
@Component也可以在各层分别写成写成:@Controller、@Service、@Repository
核心技术点:XML解析+反射
具体思路:
Original: https://blog.csdn.net/weixin_41489136/article/details/127826381
Author: 盛者无名
Title: Spring基础之IoC
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/661075/
转载文章受原作者版权保护。转载请注明原作者出处!