一、通过配置文件创建类的对象
目录结构
User.java
package com.tang.spring; public class User { public void add() { System.out.println("add"); } }
bean.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"> <!-- 配置User对象创建--> <bean id="user" class="com.tang.spring.User"></bean> </beans>
测试类MyTest.java
package com.tang.spring.testdemo; import com.tang.spring.User; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MyTest { @Test public void testAdd() { //加载spring配置文件 ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml"); //获取配置创建的对象 User user = context.getBean("user",User.class); System.out.println(user); user.add(); } }
二、IOC容器
1、IOC底层原理
IOC(Inversion of Control):译为控制反转,把对象创建和对象之间的调用过程,交给Spring进行管理
目的:降低耦合度
IOC底层:工厂设计模式、xml解析、反射
我们可以把IOC容器的工作模式看做是工厂模式的升华,可以把IOC容器看作是一个工厂,这个工厂里要生产的对象都在配置文件中给出定义,然后利用编程语言的的反射编程,根据配置文件中给出的类名生成相应的对象。从实现来看,IOC是把以前在工厂方法里写死的对象生成代码,改变为由配置文件来定义,也就是把工厂和对象生成这两者独立分隔开来,目的就是提高灵活性和可维护性。
2、IOC接口(BeanFactory)
Spring提供IOC容器两种实现方式(两个接口):
BeanFactory:IOC容器基本实现,是Spring内部的使用接口,不推荐开发人员使用这种方式。加载配置文件的时候不会创建对象,使用对象的时候才去创建。
ApplicationContext:BeanFactory接口的子接口,提供更多更强大的功能,一般由开发人员使用。加载配置文件的时候就会将对象进行创建。
ApplicationContext主要实现类:
3、IOC操作:Bean管理
Bean管理指的是两个操作:
- Spring创建对象
- Spring注入属性
Bean管理有两种实现方式:
(1)基于xml配置文件方式实现
bean标签常用属性:
-
- id:bean的唯一标识,不能包含特殊字符
- class:bean类的全路径(包名+类名)
创建对象的时候,默认使用无参构造方法完成对象创建
注入属性的两种方式:
-
- 使用set方法注入属性
- 使用有参构造器注入属性
package com.tang.spring; public class User { private String name; public User() { } //使用有参构造器注入属性 public User(String name) { this.name = name; } //使用set方法注入属性 public void setName(String name) { this.name = name; } }
<!--set方法注入属性 Spring会通过反射调用set方法完成注入,故实体类中要写set方法 --> <bean id="user" class="com.tang.spring.User"> <!--使用property完成属性注入 name:类里面的属性名字 value:向属性注入的值 --> <property name="name" value="唐三藏"></property> </bean>
<!--有参构造方法注入属性--> <bean id="user" class="com.tang.spring.User"> <constructor-arg name="name" value="唐三藏"></constructor-arg> </bean>
注入外部bean
package com.tang.spring; public class PrintUser { private User user01; public void setUser01(User user01) { this.user01 = user01; } public void print(){ System.out.println(user01); } }
<!--有参构造方法注入属性--> <bean id="user" class="com.tang.spring.User"> <constructor-arg name="name" value="唐三藏"></constructor-arg> </bean> <bean id="printUser" class="com.tang.spring.PrintUser"> <!--注入User对象 name:属性名字,必须完全对应(属性名字和set方法名字要有一致性) ref:注入对象bean标签的id属性值 --> <property name="user01" ref="user"></property> </bean>
注入内部bean
package com.tang.spring; public class Dept { private String dname; public String getDname() { return dname; } public void setDname(String dname) { this.dname = dname; } }
package com.tang.spring; public class Empl { private String ename; private String gender; private Dept dept; public void setEname(String ename) { this.ename = ename; } public void setGender(String gender) { this.gender = gender; } public void setDept(Dept dept) { this.dept = dept; } public void add(){ System.out.println(ename+"--"+dept); } }
<bean id="empl" class="com.tang.spring.Empl"> <!--设置两个普通属性--> <property name="ename" value="zhangsan"></property> <property name="gender" value="女"></property> <!--设置对象类型属性--> <property name="dept"> <bean id="dept" class="com.tang.spring.Dept"> <property name="dname" value="财务部"></property> </bean> </property> </bean>
注入集合类型
package com.tang.spring; import java.util.List; public class Course { private List<String> cname; public void setCname(List<String> cname) { this.cname = cname; } }
package com.tang.spring; import java.util.List; import java.util.Map; public class Stu { private String[] courses; private List<String> list; private Map<String,String> map; private List<Course> courseList; public void setCourseList(List<Course> courseList) { this.courseList = courseList; } public void setCourses(String[] courses) { this.courses = courses; } public void setList(List<String> list) { this.list = list; } public void setMap(Map<String, String> map) { this.map = map; } }
普通bean:在配置文件中定义的bean类型就是返回类型
工厂bean:在配置文件中定义的bean类型可以和返回类型不一样
创建工厂bean过程:
第一步:创建作为工厂bean的类(实现FactoryBean接口)
第二步:实现接口方法,在实现的方法中定义返回的bean类型
package com.tang.spring; public class Course { private String cname; public void setCname(String cname) { this.cname = cname; } @Override public String toString() { return "Course{" + "cname='" + cname + '\'' + '}'; } }
package com.tang.spring; import org.springframework.beans.factory.FactoryBean; public class MyBean implements FactoryBean<Course> { //定义返回bean类型 @Override public Course getObject() throws Exception { Course course = new Course(); course.setCname("数据库"); return course; } @Override public Class<?> getObjectType() { return null; } @Override public boolean isSingleton() { return false; } }
(2)基于注解方式实现