创建Maven工程,导入spring依赖
org.springframework spring-context {spring版本号}
lombok可以帮助开发者自动生成实体类相关的方法
假设实体类为Student
引入lombok依赖:
org.projectlombok lombok {lombok版本号}
import lombok.Data;@Data
public class Student {private Integer id;private String name;private Integer age;
}
@Data为自动生成实体类方法
也可以使用如下参数:
参数 | 作用 |
@Getter | 添加get方法 |
@Setter | 添加set方法 |
@NoArgsConstructor | 添加无参构造器 |
@AllArgsConstructor | 添加有参构造器 |
public class Test {public static void main(String[] args) {Student student=new Student();System.out.println(student.toString());}
}
Spring写法:
在resource下创建一个文件spring.xml:
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下:
student类中添加了有参构造函数:
import lombok.AllArgsConstructor;
import lombok.Data;@Data
@AllArgsConstructor
public class Student {private Integer id;private String name;private Integer age;
}
使用constructor-arg给构造函数赋值
也可以不写name,构造函数会根据变量次序依次赋值:
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关系:
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 studentList;
}
bean加入新的学生类后将新加的bean装到list中:
bean根据scope来表示bean的作用域,有四种类型:
request、session适用于web项目
新建一个实体类User
import lombok.Data;@Data
public class User {private Integer id;private String name;
}
配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_scope.xml");User user1=(User) applicationContext.getBean("user");User user2=(User) applicationContext.getBean("user");System.out.println(user1==user2);}
}
singleton模式,该模式下只要加载IoC容器,无论是否从IoC中取出bean,配置文件中的bean都会被创建
加作用域:
prototype模式,如果不从IoC中取bean,则不创建对象,取一次就会创建一个对象
Spring的继承不同于Java中的继承,区别:Java中的继承是针对于类的,Spring的继承是针对于对象bean的。
Spring的继承中,子bean可以继承父bean中的所有成员变量的值。
创建一个user2继承于user1:
主类:
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:
主类:
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的顺序
上述先创建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
必须加入上面几行不然报错!
所以得到下面的xml:
xml里必须引入:
xmlns:p="http://www.springframework.org/schema/p
p命名空间可以用来简化bean的配置:
以student和classes为例:
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 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);}
}
配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 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);}
}
配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来完成注入
自动装载有两种方式:
例:
实体类:
import lombok.Data;@Data
public class Person {private Integer id;private String name;private Car car;
}
在spring.xml中配置Car和Person对应的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。
实现该功能有两种方式:
基于注解两步操作:
例:
建一个实体类,加入@Component标签:
import lombok.Data;
import org.springframework.stereotype.Component;import javax.sql.DataSource;
@Data
@Component
public class Repository {private DataSource dataSource;
}
将spring.xml加入扫描范围,自动扫包
主类运行便可注入
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中的
实际开发中会将程序分为三层:
关系 Controller–>Service–>Repository
如下分别用xml方法和注解方法来演示该关系:
spring.xml:
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;}
}
主类:
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:
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 {@Autowiredprivate 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 {@Autowiredprivate MyRepository myRepository;@Overridepublic 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 {@Overridepublic String doReopository(Double score) {String result="";if(score<60){result ="不合格";}else if(score>=60&&score<=80){result="及格";}else if(score>80){result="优秀";}return result;}
}
主类:
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解析+反射
具体思路: