目录结构
- 自定义工厂模拟spring容器,实例化类对象
public interface AccountDao {
public void saveAcount();
}
public class AccountDaoImpl implements AccountDao {
@Override
public void saveAcount() {
out.println("AccountDaoImpl.java--saveAcount--12-->"+ "请求成功");
}
}
public interface AccountService {
public void saveAccount();
}
public class AccountServiceImpl implements AccountService {
private AccountDaoImpl dao= (AccountDaoImpl) BeanFactory.getBean("accountDaoImpl");
@Override
public void saveAccount() {
dao.saveAcount();
out.printf("AccountServiceImpl.java--saveAccount--10--> ","保存成功");
}
}
/**
* @ Author: WangGQ
* @ Date: 2019/12/26 20:37
* @ Version: 1.0
* @ Description: 创建对象工厂
*/
public class BeanFactory {
public static Properties pros;
public static Map<String,Object> beans;
static {
try {
pros = new Properties();
InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("beans.properties");
pros.load(in);
//----改造----start---
Enumeration enums=pros.keys();
beans=new HashMap<String,Object>(); //实例化容器
while (enums.hasMoreElements()){
try {
String key = (String) enums.nextElement();
String keyPath=pros.getProperty(key);
Object obj=Class.forName(keyPath).newInstance();
beans.put(key,obj);
}catch (Exception e){
e.printStackTrace();
}
}
//----改造----end---
} catch (IOException e) {
throw new ExceptionInInitializerError("读取配置文件失败");
}
}
/**
* @ Author: WangGQ
* @ Date: 2019/12/26 21:04
* @ Version: 1.0
* @ Description: 获取bean,Class.forName(beanPath).newInstance()调用的是类的默认的构造方法,所以创建的bean是多例的
*/
public static Object getBean(String beanName){
Object obj = null;
try{
String beanPath=pros.getProperty(beanName);
obj=Class.forName(beanPath).newInstance();
}catch (Exception e){
e.printStackTrace();
}
return obj;
}
public static Object createBean(String beanName){
return beans.get(beanName);
}
}
public class test1 {
public static void main(String[] args) {
// AccountServiceImpl service= (AccountServiceImpl) BeanFactory.getBean("accountServiceImpl");
AccountServiceImpl service= (AccountServiceImpl) BeanFactory.createBean("accountServiceImpl");
service.saveAccount();
}
}
//运行结果
AccountDaoImpl.java--saveAcount--12-->请求成功
AccountServiceImpl.java--saveAccount--10-->
Process finished with exit code 0
- beans.properties
accountDaoImpl=com.gsau.dao.impl.AccountDaoImpl
accountServiceImpl=com.gsau.service.impl.AccountServiceImpl
使用spring ApplicationContext获取实例化类对象
package com.gsau.factory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @ Description: 使用spring容器获取bean实例
* @ Date: 2019/12/27 9:57
* @ Author: wgq
* @ Version: 1.0
*/
public class SpringBeanFactory {
public static ApplicationContext ioc=null;
/**
* @ Description: 初始初始化Spring容器
* @ Date: 2019/12/27 10:22
* @ Author: wgq
* @ Version: 1.0
*/
static {
ioc= new ClassPathXmlApplicationContext("SpringBeans.xml");
}
/**
* @ Description: 取容器中组件
* @ Date: 2019/12/27 10:22
* @ Author: wgq
* @ Version: 1.0
*/
public static Object getBean(String beanName){
return ioc.getBean(beanName);
}
public static < obj > obj getBean(String beanName,Class<obj> obj){
return ioc.getBean(beanName,obj);
}
}
-
ApplicationContext 接口继承关系
-
ApplicationContext 接口实现关系
-
ApplicationContext 接口的实现类功能
- .ClassPathXmlApplicationContext: 它是从类的根路径下加载配置文件 推荐使用这种
- . FileSystemXmlApplicationContext: 它是从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置。
- . AnnotationConfigApplicationContext: 当我们使用注解配置容器对象时,需要使用此类来创建 spring 容器。它用来读取注解
-
BeanFactory 和 ApplicationContext 的区别
- 1. BeanFactory 才是 Spring 容器中的顶层接口,ApplicationContext 是它的子接口
- 2. BeanFactory 和 ApplicationContext 的区别:创建对象的时间点不一样
- 3. ApplicationContext:只要一读取配置文件,默认情况下就会创建对象。
- 4. BeanFactory:什么使用什么时候创建对象。
-
Spring 实例化 Bean 的三种方式
1. 使用默认无参构造函数
2.Spring 管理工厂-使用工厂的静态方法创建对象
3.spring 管理实例工厂-使用实例工厂的方法创建对象<!--在默认情况下:它会根据默认无参构造函数来创建类对象。如果 bean 中没有默认无参构造函数,将会创建失败。--> <bean id="person" class="com.gsau.entity.Person"></bean> <!--此种方式是::spring 管理静态工厂-使用静态工厂的方法创建对象 使用 SpringBeanFactory 类中的静态方法 instanceBean 创建对象,并存入 spring 容器 id 属性:指定 bean 的 id,用于从容器中获取 class 属性:指定静态工厂的全限定类名 factory-method 属性:指定生产对象的静态方法--> <bean id="emp" class="com.gsau.factory.SpringBeanFactory" factory-method="instanceBean"></bean> <!-- 此种方式是: spring 管理实例工厂-使用实例工厂的方法创建对象 先把工厂的创建交给 spring 来管理。 然后在使用工厂的 bean 来调用里面的方法 factory-bean 属性:用于指定实例工厂 bean 的 id。 factory-method 属性:用于指定实例工厂中创建对象的方法。 --> <bean id="springBeanFactory" class="com.gsau.factory.SpringBeanFactory"></bean> <bean id="dept" factory-bean="springBeanFactory" factory-method="createBean"></bean>
import com.gsau.entity.Dept; import com.gsau.entity.Emp; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @ Description: 使用spring容器获取bean实例 * @ Date: 2019/12/27 9:57 * @ Author: wgq * @ Version: 1.0 */ public class SpringBeanFactory { public static ApplicationContext ioc=null; /** * @ Description: 初始初始化Spring容器 * @ Date: 2019/12/27 10:22 * @ Author: wgq * @ Version: 1.0 */ static { ioc= new ClassPathXmlApplicationContext("SpringBeans.xml"); } /** * @ Description: 取容器中组件 * @ Date: 2019/12/27 10:22 * @ Author: wgq * @ Version: 1.0 */ public static Object getBean(String beanName){ return ioc.getBean(beanName); } public static < obj > obj getBean(String beanName,Class<obj> obj){ return ioc.getBean(beanName,obj); } /** * @ Description: 用于测试bean创建的三种方式:使用自定义工厂类 * @ Date: 2019/12/27 13:52 * @ Author: wgq * @ Version: 1.0 */ public static Object instanceBean(){ return new Emp(); } /** * @ Description: 用于测试bean创建的三种方式: 使用实例工厂的方法创建对象 * @ Date: 2019/12/27 14:14 * @ Author: wgq * @ Version: 1.0 */ public Object createBean(){ return new Dept(); } } //测试类 public class test1 { public static void main(String[] args) { // AccountServiceImpl service= (AccountServiceImpl) BeanFactory.getBean("accountServiceImpl"); AccountServiceImpl service= SpringBeanFactory.getBean("accountServiceImpl",AccountServiceImpl.class); Person person=SpringBeanFactory.getBean("person", Person.class); Emp emp=SpringBeanFactory.getBean("emp", Emp.class); Dept dept=SpringBeanFactory.getBean("dept", Dept.class); System.out.println("test1-test1-13->"+person.toString()); System.out.println("test1-test1-17->"+emp.id); System.out.println("test1-test1-20->"+dept.name); service.saveAccount(); } }
-
Spring IOC 中 bean 标签和管理对象细节
- bean 标签
- 作用:
用于配置对象让 spring 来创建的,默认情况下它调用的是类中的无参构造函数。如果没有无参构造函数则不能创建成功 - 属性:
id:给对象在容器中提供一个唯一标识。用于获取对象。
class:指定类的全限定类名。用于反射创建对象。默认情况下调用无参构造函数。
scope:指定对象的作用范围。
singleton :默认值,单例的.
prototype :多例的.
request :WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 request 域中.
session :WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 session 域中.
global session :WEB 项目中,应用在 Portlet 环境.如果没有 Portlet 环境那么 globalSession 相当于 session.
init-method:指定类中的初始化方法名称。
destroy-method:指定类中销毁方法名称。
- 作用:
- bean 的作用范围和生命周期
- 单例对象:scope=“singleton”:
每次访问对象时,都会重新创建对象实例
生命周期:
1. 对象出生:当应用加载,创建容器时,对象就被创建了。
2. 对象活着:只要容器在,对象一直活着。
3. 对象死亡:当应用卸载,销毁容器时,对象就被销毁了。 - 多例对象 :scope=“prototype”:
一个应用只有一个对象的实例。它的作用范围就是整个引用
person 生命周期:
1. 对象出生:当使用对象时,创建新的对象实例。
2. 对象活着:只要对象在使用中,就一直活着。
3. 对象死亡:当对象长时间不用时,被 java 的垃圾回收器回收了
- 单例对象:scope=“singleton”:
- bean 标签
-
spring 的依赖注入
依赖注入: Dependency Injection。它是 spring 框架核心 ioc 的具体实现。我们的程序在编写时,通过控制反转,把对象的创建交给了 spring,但是代码中不可能出现没有依赖的情况。 ioc 解耦只是降低他们的依赖关系,但不会消除。例如:我们的业务层仍会调用持久层的方法。那这种业务层和持久层的依赖关系,在使用 spring 之后,就让 spring 来维护了。
简单的说: 就是坐等框架把持久层对象传入业务层,而不用我们自己去获取。- 能注入的对象:
- 能注入的数据有:
- 1.基本数据类型和String
- 2.其他的bean类型(在配置文件或者注解中配置过的本)
- 3.复杂类型/map类型
- 注入的方式:
- 1.使用构造函数
- 2.使用set方法操作
- 3.使用注解提供
- 能注入的数据有:
- 能注入的对象: