一、Spring框架
1、Spring是一个由Java语言开发的框架。
2、Spring在项目开发时主要提供两种服务:IOC服务/AOP服务
3、目前为止,所有的Java项目中都会使用Spring框架
二、IOC服务
1、IOC服务,意为“控制反转”
2、IOC服务中,可以由Spring容器为开发人员提供项目运行时需要的对象
3、IOC服务简单来说,就是由Spring容器负责帮你创建需要的对象
三、Spring容器对象:
1、容器:存储对象的载体。一般指的是List,Set,Map,数组
2、容器对象:如果某个对象中的属性是集合,且这个集合用于存储其他的对象
四、IOC最终认识
-
之前在开发时,需要某个对象时,需要自己来负责创建;IOC服务中,当你需要某个对象时,可以向Spring容器对象索要。
五、为什么需要由Spring容器提供需要的对象
-
在开发时,某些对象的获得相对困难且繁琐,例如jdbc中的PreparedStatment对象和MyBatis中的SqlSession对象。
-
1、Class.forName(Driver接口);
-
2、Connection con = DriverManager.getConnection();
-
3、PreparedStatment ps = con.preparedStatment();
-
1、InputStream in = Resources.getResourceAsStream("mybatis.xml");-
-
2、 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
-
3、SqlSession sqlSession = factory.openSession(true);
-
public class Dept {
private Integer deptNo;
private String dname;
private String loc;
@Override
public String toString() {
return "Dept{" +
"deptNo=" + deptNo +
", dname='" + dname + '\'' +
", loc='" + loc + '\'' +
'}';
}
public Integer getDeptNo() {
return deptNo;
}
public void setDeptNo(Integer deptNo) {
this.deptNo = deptNo;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
public String getLoc() {
return loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
}
//====================================================
public class Emp {
private Integer empNo;
private String ename;
@Override
public String toString() {
return "Emp{" +
"empNo=" + empNo +
", ename='" + ename + '\'' +
'}';
}
public Integer getEmpNo() {
return empNo;
}
public void setEmpNo(Integer empNo) {
this.empNo = empNo;
}
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
}
public class ApplicationContext {
private static Map map ;//存储项目开发时的实例对象
//Spring 容器类第一次被加载时,将项目中指定类的对象创建出来保存到容器
static {
map = new HashMap();
map.put("dept",new Dept());
map.put("emp",new Emp());
}
public static Object getBean(String key ){
return map.get(key);
}
}
public class Tes_IOC {
public static void main(String[] args) {
Dept dept = (Dept) ApplicationContext.getBean("dept");
Emp emp = (Emp) ApplicationContext.getBean("emp");
System.out.println("dept对象"+dept);
System.out.println("emp对象"+emp);
}
}
六、Spring框架中的DI服务:
-
1、DI服务:依赖注入
-
2、DI服务从IOC服务衍生的一个服务,用于帮助开发人员为对象的属性进行初始化操作
/**
* @Target 注解描述当前自定义注解可以在哪些元素上进行声明
* @Retention 注解描述当前自定义的注解有效范围
* 1、开发阶段有效
* 2、在编译阶段有效
* 3、在运行时有效
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Value {
//声明Value注解中的属性
public String value() default "";
}
public class Dept {
@Value(value = "10")
private Integer deptNo;
@Value(value = "Accounting")
private String dname;
private String loc;
@Override
public String toString() {
return "Dept{" +
"deptNo=" + deptNo +
", dname='" + dname + '\'' +
", loc='" + loc + '\'' +
'}';
}
public Integer getDeptNo() {
return deptNo;
}
public void setDeptNo(Integer deptNo) {
this.deptNo = deptNo;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
public String getLoc() {
return loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
}
//==================================================
public class Emp {
@Value(value = "9527")
private Integer empNo;
@Value(value = "pm")
private String ename;
@Override
public String toString() {
return "Emp{" +
"empNo=" + empNo +
", ename='" + ename + '\'' +
'}';
}
public Integer getEmpNo() {
return empNo;
}
public void setEmpNo(Integer empNo) {
this.empNo = empNo;
}
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
}
public class ApplicationContext {
private static Map map ;//存储项目开发时的实例对象
//Spring 容器类第一次被加载时,将项目中指定类的对象创建出来保存到容器
static {
map = new HashMap();
try {
map.put("dept",init(Dept.class));
map.put("emp",init(Emp.class));
} catch (Exception e) {
e.printStackTrace();
}
}
//侦测指定类中是否绑定了@Value注解,如若绑定,那么根据注解中的值对当前属性进行赋值
private static Object init(Class classManager)throws Exception{
Object obj = null;
Field fieldArray[] = null;
//1、通过class文件来申请创建当前类的实例对象
obj = classManager.newInstance();
//2、通过class文件得到当前类文件中所有的属性信息
fieldArray = classManager.getDeclaredFields();
//3、循环遍历,如果发现某个属性上绑定了@Value注解,则需要将注解中的值赋值给当前属性
for (Field field:fieldArray){
//3.1、询问当前属性是否关联了@Value注解
if (field.isAnnotationPresent(Value.class)) {
Value value = field.getAnnotation(Value.class);
//从当前注解对象中得到value属性的值
String field_Value = value.value();
//将注解中的值赋值到当前对象的属性
field.setAccessible(true);
String typeName = field.getType().getSimpleName();
if ("Inteder".equals(typeName)) {
field.set(obj, Integer.valueOf(field_Value));
} else if ("Double".equals(typeName)) {
field.set(obj, Double.valueOf(field_Value));
} else if ("String".equals(typeName)) {
field.set(obj, field_Value);
}
}
}
return obj;
}
public static Object getBean(String key ){
return map.get(key);
}
}
public class Test_DI {
public static void main(String[] args) {
Emp emp = (Emp) ApplicationContext.getBean("emp");
System.out.println(emp.toString());
Dept dept = (Dept) ApplicationContext.getBean("dept");
System.out.println(dept.toString());
}
}
七、通过xml文件向Spring容器索要IOC服务
-
开发环境搭建
-
1、向Maven索要Spring框架中spring-context.jar
-
2、在resources下创建Spring框架的核心配置文件,通过该配置文件通知Spring容器当前项目中哪些类的对象需要由Spring容器来提供
-
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<bean id="student" class="com.pm.entity.Student">
</bean>
public class Student {
public void sayHello(String name){
System.out.println("hello : " + name);
}
}
public class TestMain {
/**
* ApplicationContext 的两个接口实现类
*
* 1、FileSystemXmlApplicationContext:创建Spring 容器对象可以在当前计算机任意硬盘上
* 读取指定的Spring核心配置文件
*
* 2、ClassPathXmlApplicationContext:创建的Spring容器对象只能在当前项目的编译路径下
* 读取指定的核心配置文件
*/
@Test
public void test1(){
//1、获取Spring容器对象,Spring容器对象在创建时自动读取指定的Spring核心配置。
ApplicationContext spring = new ClassPathXmlApplicationContext("spring.xml");
//2、向Spring容器对象索要Student类对象
Student stu = (Student) spring.getBean("student");
stu.sayHello("pm");
}
@Test
public void test2(){
//1、获取Spring容器对象,Spring容器对象在创建时自动读取指定的Spring核心配置。
ApplicationContext spring = new ClassPathXmlApplicationContext("spring.xml");
//2、连续向Spring容器索要两个Student类型对象
Student stu1 = (Student) spring.getBean("student");
Student stu2 = (Student) spring.getBean("student");
System.out.println("stu1:" + stu1.toString());
System.out.println("stu2:" + stu1.toString());
}
@Test
public void test3(){
//1、获取Spring容器对象,Spring容器对象在创建时自动读取指定的Spring核心配置。
ApplicationContext spring = new ClassPathXmlApplicationContext("spring.xml");
//2、获得Spring容器对象中所管理的所有实例对象的key
String keys[] = spring.getBeanDefinitionNames();
for (String key :
keys) {
System.out.println("key = "+key);
}
}
}
test1结果: hello : pm
test2结果:stu1:com.pm.entity.Student@6acdbdf5
stu2:com.pm.entity.Student@6acdbdf5
test3结果:key = student
八、通过xml文件向Spring容器索要DI服务
-
part1
public class School {
private String shcoolName;
private String address;
public String getShcoolName() {
return shcoolName;
}
public void setShcoolName(String shcoolName) {
this.shcoolName = shcoolName;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "School{" +
"shcoolName='" + shcoolName + '\'' +
", address='" + address + '\'' +
'}';
}
}
<bean id="school" class="com.pm.pack1.School">
<property name="address" value="大湾区卷王9527房"/>
<property name="shcoolName" value="卷王学院"/>
</bean>
public class TestMain {
@Test
public void test1(){
ApplicationContext spring = new ClassPathXmlApplicationContext("pack1/spring.xml");
School school=(School) spring.getBean("school");
System.out.println(school.toString());
}
}
-
part2
public class School {
private String shcoolName;
private String address;
public String getShcoolName() {
return shcoolName;
}
public void setShcoolName(String shcoolName) {
this.shcoolName = shcoolName;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "School{" +
"shcoolName='" + shcoolName + '\'' +
", address='" + address + '\'' +
'}';
}
}
//====================================================================
public class Student {
private int sid;
private String sname;
private School school; //表示学员隶属的学校
private List list;
public List getList() {
return list;
}
public void setList(List list) {
this.list = list;
}
public int getSid() {
return sid;
}
public void setSid(int sid) {
this.sid = sid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public School getSchool() {
return school;
}
public void setSchool(School school) {
this.school = school;
}
@Override
public String toString() {
return "Student{" +
"sid=" + sid +
", sname='" + sname + '\'' +
", school=" + school +
'}';
}
}
<bean id="myList" class="java.util.ArrayList"></bean>
<!--
property 通知Spring容器为当前对象中属性进行初始化操作
property 指向的属性必须匹配set方法
-->
<bean id="school" class="com.pm.pack1.School">
<property name="address" value="大湾区卷王9527房"/>
<property name="shcoolName" value="卷王学院"/>
</bean>
<!--
value 与 ref 区别
如果需要赋值的属性是[基本数据类型],此时需要使用value属性指定其初始值
如果需要赋值的属性是[高级引用数据类型],此时需要使用ref属性指定其初始值
ref指向一个在Spring容器已经存在的对象的key
-->
<bean id="student" class="com.pm.pack2.Student">
<property name="sid" value="10"/>
<property name="sname" value="mike"/>
<property name="school" ref="mySchool"/>
<property name="list" ref="myList"/>
</bean>
public class TestMain {
@Test
public void test1(){
ApplicationContext spring = new ClassPathXmlApplicationContext("pack2/spring.xml");
Student student=(Student)spring.getBean("student");
System.out.println(student.toString());
}
}
-
part3
public class Student {
private int sid;
private String sname;
public int getSid() {
return sid;
}
public void setSid(int sid) {
this.sid = sid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public Student(int sid, String sname) {
this.sid = sid;
this.sname = sname;
}
@Override
public String toString() {
return "Student{" +
"sid=" + sid +
", sname='" + sname + '\'' +
'}';
}
}
<!--
默认的情况下,Spring容器对象调用指定类的【无参构造方法】来创建当前类的实例对象的
如果当前类没有无参构造方法,此时可以通过constructor-arg标签要求Spring容器调用
对应的有参构造方法来创建当前类的实例对象
-->
<bean id="student" class="com.pm.pack3.Student">
<constructor-arg name="sid" value="20"/>
<constructor-arg name="sname" value="mike"/>
</bean>
public class TestMain {
@Test
public void test1(){
ApplicationContext spring = new ClassPathXmlApplicationContext("pack3/spring.xml");
Student stu = (Student)spring.getBean("student");
System.out.println(stu.toString());
}
}
test1结果:School{shcoolName='卷王学院', address='大湾区卷王9527房'}
test2结果:Student{sid=10, sname='mike', school=School{shcoolName='卷王学院', address='大湾区卷王9527房'}}
test3结果:Student{sid=20, sname='mike'}