IOC:控制反转:将对象的创建权由Spring管理。 降低依赖关系。
一、模拟IOC
利用工厂模式模拟实现IOC:使用工厂模式创建services和dao
配置文件:bean.properties
accountDao=com.examples.dao.AccountDaoImpl
accountServices=com.examples.services.AccountServicesImpl
BeanFactory:
public class BeanFactory {
// 使用原生的不好用,Properties的load是无序的,使用子类进行有序保存到集合Properties
//private static Properties props;
private static OrderedProperties props;
private static Map<String ,Object> beans;
static {
props = new OrderedProperties();
//InputStream in = new FileInputStream(); 这个方式不合适。
//InputStream in = this.getClass().getResourceAsStream("bean.properties"); this不能放在static
InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
try {
props.load(in);
beans = new HashMap<String ,Object>();
Enumeration keys = props.keys();
while (keys.hasMoreElements()){
String key = keys.nextElement().toString();
String beanPath = props.getProperty(key);
Object value = Class.forName(beanPath).newInstance();
beans.put(key,value);
}
} catch (Exception e) {
throw new ExceptionInInitializerError("初始化失败,不存在配置文件");
}
}
public static Object getBean(String beanName){
return beans.get(beanName);
}
}
OrderedProperties:
public class OrderedProperties extends Properties {
private static final long serialVersionUID = -4627607243846121965L;
private final LinkedHashSet<Object> keys = new LinkedHashSet<Object>();
public Enumeration<Object> keys() {
return Collections.enumeration(keys);
}
public Object put(Object key, Object value) {
keys.add(key);
return super.put(key, value);
}
public Set<Object> keySet() {
return keys;
}
public Set<String> stringPropertyNames() {
Set<String> set = new LinkedHashSet<String>();
for (Object key : this.keys) {
set.add((String) key);
}
return set;
}
}
services层
AccountServicesImpl:
public class AccountServicesImpl implements AccountServices {
//耦合度过低,依赖性过强
//private AccountDao accountDao = new AccountDaoImpl();
private AccountDao accountDao =(AccountDao) BeanFactory.getBean("accountDao");
@Override
public void saveAccount() {
accountDao.saveAccount();
}
}
dao层
AccountDaoImpl:
public class AccountDaoImpl implements AccountDao {
@Override
public void saveAccount() {
System.out.println("DAO---保存账户数据");
}
}
客户端
public class client {
public static void main(String[] args) {
//耦合度过低,依赖性过强
//AccountServices accountServices = new AccountServicesImpl();
AccountServices accountServices = (AccountServices) BeanFactory.getBean("accountServices");
accountServices.saveAccount();
}
}
二、 Spring的IOC
bean的创建方式2.1 Spring生产Bean
<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">
<!--把对象的管理交给Spring,内容与bean.properties中的配置一致-->
<bean id="accountDao" class="com.myspring.dao.AccountDaoImpl"></bean>
<bean id="accountServices" class="com.myspring.services.AccountServicesImpl"></bean>
</beans>
public class client {
public static void main(String[] args) {
ApplicationContext ApplicationContext = new ClassPathXmlApplicationContext("bean.xml");
AccountServices accountServices = (AccountServices) ApplicationContext.getBean("accountServices");
AccountDao accountDao = ApplicationContext.getBean("accountDao",AccountDao.class);
System.out.println(accountServices.toString()+"||"+accountDao.toString());
}
}
ApplicationContext
ApplicationContext相比 BeanFactory
在其基础上扩展了功能。如:事件通知(ApplicationEventPublisher接口),该接口定义了事件的发布机制;可参考:https://blog.51cto.com/wjzxp/5421639
Spring基于ApplicationContext
和BeanFactory
加载的对象的方式不同:
- 多例模式下使用
BeanFactory
(延迟加载配置文件中的对象); - 单例模式下使用
ApplicationContext
(立即加载配置文件中的对象);
ApplicationContext和BeanFactory加载配置文件方式区别:
BeanFactory:Resource。
ApplicationContext:
1.ClassPathXmlApplicationContext:可以加载类路径下的配置文件。
2.FileSystemXmlApplicationContext:可以加载磁盘任意路径下的有访问权限的文件。
3.AnnotationConfigApplicationContext:读取注解创建容器。
2.2 Spring对Bean的管理。
Spring主要管理Bean的内容:
1.创建Bean对象的方式
2.bean对象的作用范围
3.bean对象的生命周期
1.创建Bean对象的方式
1.1创建Bean对象的方式:构造方法。
<?xml version="1.0" encoding="UTF-8"?>
<!--
两部分: 1.根标签beans的别名:xmlns="http://www.springframework.org/schema/beans"
2.约束文件:schemaLocation引入约束,然后给约束地址起个别名xsi
-->
<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="accountDao" class="com.myspring.dao.AccountDaoImpl"></bean>-->
<!-- 第一种:使用默认的构造方法:在配置文件中使用Bean标签,
配置id和class属性之后,且没有其他属性和标签时,如果该类中没有默认的构造方法,则无法创建对象。-->
<bean id="accountServices" class="com.myspring.services.AccountServicesImpl"></bean>
</beans>
1.2.创建Bean对象的方式:工厂类提供的方法。
<?xml version="1.0" encoding="UTF-8"?>
<!--
两部分: 1.根标签beans的别名:xmlns="http://www.springframework.org/schema/beans"
2.约束文件:schemaLocation引入约束,然后给约束地址起个别名xsi
-->
<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">
<!-- 第二种:使用普通工厂中的方法创建的对象(使用某个类中的方法创建对象并存入Spring容器)-->
<bean id="InstanceFactory" class="com.myspring.demos.InstanceFactory"></bean>
<bean id="accountServices" factory-bean="InstanceFactory" factory-method="getAccountServices"></bean>
</beans>
工厂类 InstanceFactory
/*模拟jar包中的工厂类 InstanceFactory.class
* */
public class InstanceFactory {
public AccountServices getAccountServices(){
System.out.println("我是工厂类");
return new AccountServicesImpl();
}
}
1.3.创建Bean对象的方式:工厂类提供的静态方法。
<?xml version="1.0" encoding="UTF-8"?>
<!--
两部分: 1.根标签beans的别名:xmlns="http://www.springframework.org/schema/beans"
2.约束文件:schemaLocation引入约束,然后给约束地址起个别名xsi
-->
<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">
<!-- 第三种:使用工厂中的静态方法创建的对象(使用某个类中的静态方法创建对象并存入Spring容器)
factory-method:不写这个属性的时候,就跟第一个是一致,然而StaticFactory类中不一定有可用的构造方法。-->
<bean id="accountServices" class="com.myspring.demos.StaticFactory" factory-method="getAccountServices"></bean>
</beans>
工厂类:StaticFactory
/*模拟jar包中的工厂类StaticFactory.class
* */
public class StaticFactory {
public static AccountServices getAccountServices(){
System.out.println("我是静态方法");
return new AccountServicesImpl();
}
}
通用客户端:
public class client {
public static void main(String[] args) {
ApplicationContext ApplicationContext = new ClassPathXmlApplicationContext("bean.xml");
AccountServices accountServices = (AccountServices) ApplicationContext.getBean("accountServices");
System.out.println(accountServices.toString());
}
}
2.Bean对象的作用范围
<?xml version="1.0" encoding="UTF-8"?>
<!--
两部分: 1.根标签beans的别名:xmlns="http://www.springframework.org/schema/beans"
2.约束文件:schemaLocation引入约束,然后给约束地址起个别名xsi
-->
<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">
<!-- scope的取值:
singleton:单例
prototype:多例
request:作用于WEB应用的请求范围
session:作用于WEB应用的会话范围
global-session:集群模式下的会话范围(全局会话范围),非集群就是session范围。
-->
<bean id="accountServices" class="com.myspring.services.AccountServicesImpl" scope="singleton"></bean>
</beans>
3.Bean对象的生命周期
<?xml version="1.0" encoding="UTF-8"?>
<!--
两部分: 1.根标签beans的别名:xmlns="http://www.springframework.org/schema/beans"
2.约束文件:schemaLocation引入约束,然后给约束地址起个别名xsi
-->
<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="accountServices" class="com.myspring.services.AccountServicesImpl"
scope="singleton" init-method="init" destroy-method="destory"></bean>
</beans>
AccountServicesImpl:
public class AccountServicesImpl implements AccountServices {
//这里是有参参构造方法
public AccountServicesImpl(){
System.out.println("构造……");
}
@Override
public void saveAccount() {
System.out.println("services");
}
public void init(){
System.out.println("init……");
}
public void destory(){
System.out.println("destory……");
}
}
客户端:
public class client {
public static void main(String[] args) {
ClassPathXmlApplicationContext ApplicationContext = new ClassPathXmlApplicationContext("bean.xml");
AccountServices accountServices = (AccountServices) ApplicationContext.getBean("accountServices");
System.out.println(accountServices.toString());
ApplicationContext.close();
System.out.println("close----");
}
}
单例结果:
单例结果.png多例结果:
多例结果.png
网友评论