Spring5-IOC
# Spring4-IOC和Bean
# 1. 高内聚低耦合
高内聚是说模块内部要高度聚合,低耦合是说模块与模块之间的耦合度要尽量低。前者是说模块内部的关系,后者是说模块与模块直接按的关系。高内聚是模块功能的专一性高,独立性强。低耦合是模块之间的联系要尽量少,尽量简单,这句话描述模块设计的两个方面。
# 2. Spring简介
# 2.1 Spring是什么
Spring诞生之初,主要的目的是用来替代更加重量级的企业级技术,尤其是EJB,相对与EIB来说Spring提供了更加轻量级和简单的编程模型。它增强了简单老式的Java对象POJO的功能,使其具备了之前只有EJB和其他企业级Java规范才有的功能。
Spring是一个开源框架,Spring是于2003年兴起的一个轻量级的Java开发框架,由Rod Johnson在其著作Expert One-On-One J2EE Development and Design中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。简单来说,Spring是一个轻量级的控制反转(IOC/DI)和面向切面(AOP)的容器框架。 同时还提供了如下功能:
Spring体系: spring平台太广泛了,spring全家桶.spring的IOC/DI ,AOP,管理data,web部分[springMVC] ,以及springboot,springCloud等等.
# 2.2 核心容器
- **Core模块:**封装了框架依赖的最底层部分,包括资源访问、类型转换及一些常用工具类。
- Beans模块:提供了框架的基础部分,包括反转控制和依赖注入。其中Bean Factory是容器核心(工厂),本质是“工厂设计模式”的实现,而且无需变成实现“单例设计模式”,单例完全由容器控制,而且提倡面向接口编程,而非面向实现编程;所有应用程序对象及对象间关系由框架管理,从而真正把你从程序逻辑中把维护对象之间的依赖关系提取出来,所有这些依赖关系都由BeanFactory来维护。
- Context模块:以Core和Beans为基础,集成Beans模块功能并添加资源绑定、数据验证、国际化、Java EE支持、容器生命周期、事件**传播等;核心接口是ApplicationContext。
- **EL模块:**提供强大的表达式语言支持,支持访问和修改属性值,方法调用,支持访问及修改数组、容器和索引器,命名变量,支持算数和逻辑运算,支持从Spring 容器获取Bean,它也支持列表投影、选择和一般的列表聚合等。
- **AOP模块:**Spring AOP模块提供了符合 AOP Alliance规范的面向方(切)面的编程(aspect-oriented programming)实现,提供比如日志记录、权限控制、性能统计等通用功能和业务逻辑分离的技术,并且能动态的把这些功能添加到需要的代码中;这样各专其职,降低业务逻辑和通用功能的耦合。
- **DataACCESS模块:**Spring本身的 JDBC, 和其他的框架整合 ORM(Mybatis Hibernate)
- **WEB模块:**Web的部分(Spring MVC),和其他框架如:Struts2整合的部分;
# 2.3 Spring能做什么?
Spring能程序员简化开发:
Spring根据配置文件来进行创建及组装对象间依赖关系(IOC),只需要改配置文件即可,无需重新编译。Spring能帮我们根据配置文件创建及组装对象之间的依赖关系。
重复业务逻辑的处理,在AOP思想中,Spring 面向切面编程能帮助我们无耦合的实现日志记录,性能统计,安全控制等。
原始的支持jdbc事务处理繁琐,Spring能非常简单的帮我们管理数据库事务。
Spring还提供了与第三方ORM框架无缝集成,而且自己也提供了一套JDBC访问模板,来方便数据库访问。
Spring还提供与第三方Web(如Struts、JSF)框架无缝集成,而且自己也提供了一套Spring MVC框架,来方便web层搭建。
Spring能方便的与Java EE(如Java Mail、任务调度)整合,与更多技术整合(比如缓存框架)。
# 2.4 Spring的优点
非常轻量级的容器,低侵入,代码污染低。独立于各种应用服务器.DI(IOC)降低了业务对象替换复杂性;spring调度.;
Spring官方下载:
http://repo.spring.io/libs-release-local/org/springframework/
托管在github上的地址:
https://github.com/spring-projects/spring-framework/releases
# 3. 控制反转
# 3.1概念
**IOC:**Inversion of Control控制反转:不是什么技术,而是一种设计思想,其作用是实例化具体的bean,动态装配bean
- 类的一些属性:(例如UserService中的userDao成员属性)是由当前类(UserService)自己控制其实例化,现在不是由当前类(UserService)自己控制。现在Spring是利用接口来控制的。由原来控制实现转为Spring现在来控制接口(由上反转)。
- 我们可以使用xml或者注解来进行相关配置,Spring会根据配置和约定,对对象进行实例化和属性装配。、
**DI:**Dependency Injection依赖注入:一些成员属性(例如User Service这个i部分的userDao成员属性)依赖Spring容器来注入,组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。
好处:是Spring的核心机制,可以使Spring的bean以配置文件组织在一起,而不是硬编码方式耦合,耦合性相对来降低了;两外,注入是使用配置文件来实现,这样修改来非常的方便。
依赖注入和控制反转是对同一事情的不同描述,从某个方面将,就是他们描述的角度不同。IOC是说不需要程序员管理和控制bean,是解耦的目的,DI是手段。IOC是指让生成类的方式由传统方式new反过来,既程序员不调用new,需要类的时候由Spring等框架注入(DI)。
# 3.2 SpringIOC容器解析
Spring Ioc容器的代表就是org.springframework.beans包中的BeanFactory接口,BeanFactory接口提供了IoC容器最基本功能;而org.springframework.context包下的ApplicationContext接口扩展了BeanFactory,还提供了与Spring AOP集成、国际化处理、事件传播及提供不同层次的context实现 (如针对web应用的WebApplicationContext)。简单说, BeanFactory提供了IOC容器最基本功能,而 ApplicationContext 则增加了更多支持企业级功能支持。ApplicationContext完全继承BeanFactory,因而BeanFactory所具有的语义也适用于ApplicationContext。
容器实现一览: • XmlBeanFactory:BeanFactory实现,提供基本的IOC容器功能,可以从classpath或文件系统等获取资源; (1) File file = new File("fileSystemConfig.xml"); Resource resource = new FileSystemResource(file); BeanFactory beanFactory = new XmlBeanFactory(resource); (2)Resource resource = new ClassPathResource("classpath.xml"); BeanFactory beanFactory = new XmlBeanFactory(resource); • ClassPathXmlApplicationContext:ApplicationContext实现,从classpath获取配置文件; BeanFactory beanFactory =new ClassPathXmlApplicationContext("classpath.xml"); • FileSystemXmlApplicationContext:ApplicationContext实现,从文件系统获取配置文件。 BeanFactory beanFactory = new FileSystemXmlApplicationContext("fileSystemConfig.xml");
# 3.3 获取Bean
# ApplicationContext接口获取Bean方法简介:
Object getBean(String name) 根据名称返回一个Bean,客户端需要自己进行类型转换;参数name可以使bean的属性id的值或者是name的值.
T getBean(String name, Class
requiredType) 根据名称和指定的类型返回一个Bean,客户端无需自己进行类型转换,如果类型转换失败,容器抛出异常;返回的是指定名称同时指定类型的bean对象: T getBean(Class
requiredType) 根据指定的类型返回一个Bean,客户端无需自己进行类型转换,如果没有或有多于一个Bean存在容器将抛出异常;
# 3.4 IOC容器是如何工作的
- 配置文件的准备工作:在配置文件applicationContext.xml中声明Bean,也就是为Bean配置元数据。
- IOC容器解析元数据: IOC容器的Bean Reader读取并解析配置文件,根据定义生成BeanDefinition配置元数据对象,IOC容器根据BeanDefinition进行实例化、配置及组装Bean。
- 实例化IOC容器:由客户端实例化容器,获取需要的Bean。
# 3.5 ClassPathXMLApplicationContext和ApplicationContext
# 4. Bean的表示以及说明
# 4.1 Bean表示和说明
Spring IOC容器目的就是管理Bean,这些Bean将根据配置文件中的Bean定义进行创建,而Bean定义在容器内部由BeanDefinition对象表示,该定义主要包含以下信息:
- 全限定类名(FQN):用于定义Bean的实现类;
- Bean行为定义:这些定义了Bean在容器中的行为;包括作用域(单例、原型创建)、是否惰性初始化及生命周期等;
- Bean创建方式定义:说明是通过构造器还是工厂方法创建Bean;
- Bean之间关系定义:即对其他bean的引用,也就是依赖关系定义,这些引用bean也可以称之为同事bean 或依赖bean,也就是依赖注入。
一般配置文件结构如下:
<beans>
<import resource=”resource1.xml”/>
<bean id=”bean1” class=””></bean>
<bean id=”bean2” class=””></bean>
<bean name=”bean2” class=””></bean>
<alias alias="bean3" name="bean2"/>
<import resource=“resource2.xml”/>
</beans>
2
3
4
5
6
7
8
1、
2、alias用于定义Bean别名的;
3、import用于导入其他配置文件的Bean定义,这是为了加载多个配置文件,当然也可以把这些配置文件构造为一个数组(new String[] {“config1.xml”, config2.xml})传给ApplicationContext实现进行加载多个配置文件,那一个更适合由用户决定;这两种方式都是通过调用Bean Definition Reader 读取Bean定义,内部实现没有任何区别。
注xml配置文件中
<bean id="u" class="com.etc.dao.impl.UserDaoImpl" > </bean>
或
<bean name="u" class="com.etc.dao.impl.UserDaoImpl" > </bean>
2
3
标签中的属性id与name作用是一样,区别在于id中不可以含有特殊字符,而name中可以有特殊字符;id是确定该bean的唯一属性,而name可以指定一个或者多个名称,各个名称之间用逗号或分号分开。后面的为bean的别名。
测试如下代码功能:
<?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-4.0.xsd">
<!-- 第一种写法 只包含了class -->
<bean class="com.etc.entity.Message">
<property name="msg" value="记得晚上一起吃饭"></property>
</bean>
<!-- 第二种写法 包含了id class -->
<bean id="m2" class="com.etc.entity.Message">
<property name="msg" value="记得晚上一起打豆豆"></property>
</bean>
<!-- 第三种写法 包含了name class -->
<bean name="m3" class="com.etc.entity.Message">
<property name="msg" value="记得晚上一起看电影"></property>
</bean>
<!-- 第四种写法 包含了 class -->
<bean class="com.etc.entity.Message" id="m4">
<property name="msg" value="记得晚上一起相亲"></property>
</bean>
<!-- m4的别名 -->
<alias name="m4" alias="malias" />
</beans>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
测试类
public class TestMessage {
@Test
public void iocTest01()
{
BeanFactory bf=new ClassPathXmlApplicationContext("applicationContext.xml");
Message m=bf.getBean(Message.class);
System.out.println(m);
}
@Test
public void iocTest02()
{
BeanFactory bf=new ClassPathXmlApplicationContext("applicationContext.xml");
Message m=(Message)bf.getBean("m2");
System.out.println(m);
}
@Test
public void iocTest03()
{
BeanFactory bf=new ClassPathXmlApplicationContext("applicationContext.xml");
Message m=(Message)bf.getBean("m3");
System.out.println(m);
}
@Test
public void iocTest04()
{
BeanFactory bf=new ClassPathXmlApplicationContext("applicationContext.xml");
Message m=(Message)bf.getBean("malias");
System.out.println(m);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
Bean命名约定:Bean的命名遵循XML命名规范,但最好符合Java命名规范,由“字母、数字、下划线组成”,而且应该养成一个良好的命名习惯, 比如采用“驼峰式”,即第一个单词首字母开始,从第二个单词开始首字母大写开始,这样可以增加可读性。
# 5. 注入方法(setter,constructor;接口注入等)
# 5.1 setter注入类型
就是在bean中使用setXX方法进行注入,因此需要在bean类中,成员属性需要setXX,方法如下:
package com.etc.dao;
import com.etc.entity.News;
public class NewsDao {
private News news;
public void setNews(News news) {
this.news = news;
}
public void getNews()
{
System.out.println("newsDao :"+news);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
配置文件:
<!- bean管理 [实例bean] -->
<bean id="news" class="com.etc.entity.News">
<!-- 给属性赋值[注入] 注入的是简单类型字面值,使用value -->
<property name="id" value="1"></property>
<property name="title" value="测试title"></property>
</bean>
<bean id="newsdao" class="com.etc.dao.NewsDao">
<!-- 下面的赋值是一个News对象,所以使用ref -->
<!-- 使用property给news赋值的时候,其实会调用setter方法,ref="news" 引用一个叫news的bean -->
<property name="news" ref="news"></property>
</bean>
2
3
4
5
6
7
8
9
10
11
12
# 5.2 构造方法
首先在bean类中需要有成员属性作为参数的构造方法
代码如下:
public class News implements Serializable{
private int id;
private String title;
public News(){
}
public class (int id , String title){
super();
this.id = id;
this.title = title;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
Spring配置文件:
<bean id="news3" class="com.etc.entity.News">
<!-- 构造注入1使用index -->
<constructor-arg index="0" value="3"></constructor-arg>
<constructor-arg index="1" value="测试标题3"></constructor-arg>
</bean>
<bean id="news4" class="com.etc.entity.News">
<!-- 构造注入1使用index -->
<constructor-arg name="id" value="4"></constructor-arg>
<constructor-arg name="title" value="测试标题4"></constructor-arg>
</bean>
2
3
4
5
6
7
8
9
10
11
测试类:
News news = context.getBean("news3",News.class);
System.out.println("news: " + news.getId() + "," + news.getTitle());
2
# 6. 注入类型
# 6.1 简单属性的注入
当bean中存在简单属性时的注入方法:
<bean id="u" class="com.etx.entity.Users">
<property name="name" value="张三" />
<property name="id">
<value> 123 </value>
</property>
</bean>
2
3
4
5
6
测试类
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Users u = (Users)context.getBean("u");
System.out.println(u.getId() + "," + u.getName());
2
3
# 6.2 集合注入
Spring不仅能注入简单类型数据,还能注入集合(Collection、无序集合Set、有序集合List)类型、数组(Array)类型、字典(Map)类型数据、Properties类型数据。
实体类:
public class BlogType {
private List<Blog> list;
private Map<Integer , Blog> map;
public List<Blog> getList() {
return list;
}
public void setList(List<Blog> list) {
this.list = list;
}
public Map<Integer, Blog> getMap() {
return map;
}
public void setMap(Map<Integer, Blog> map) {
this.map = map;
}
@Override
public String toString() {
return "BlogType [list=" + list + " , map =" + map + " ]";
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
配置文件:
<!-- spring的方式创建一个bean对象 -->
<bean class="com.etc.entity.Blog" id="blog">
<!-- 给对象的属性赋值 装配,也叫注入.字面值 -->
<property name="id" value="1"></property>
<property name="title" value="spring一统江湖"></property>
</bean>
<bean class="com.etc.entity.Blog" id="blog2">
<!-- 给对象的属性赋值 装配,也叫注入.字面值 -->
<property name="id" value="2"></property>
<property name="title" value="spring一统江湖2"></property>
</bean>
<!-- blogType -->
<bean class="com.etc.entity.BlogType" id="blogtype">
<!-- 注入 List -->
<property name="list">
<list>
<ref bean="blog" />
<ref bean="blog2" />
</list>
</property>
<!-- 注入 map -->
<property name="map">
<map>
<entry key="1" value-ref="blog"></entry>
<entry key="2" value-ref="blog2"></entry>
</map>
</property>
</bean>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
测试类
public class TestBlogType {
public static void main(String[] args) {
//实例化ApplicationContext对象
ApplicationContext context = new ClassPathXmlApplicationContext("app_type.xml");
BlogType bt = context.getBean("blogtype",BlogType.class);
System.out.println(bt);
}
}
blog无参数的构造...
blog无参数的构造...
BlogType [list=[Blog{id=1, title='spring一统江湖', author='null'}, Blog{id=2, title='spring一统江湖2', author='null'}] , map ={1=Blog{id=1, title='spring一统江湖', author='null'}, 2=Blog{id=2, title='spring一统江湖2', author='null'}} ]
2
3
4
5
6
7
8
9
10
11
12
13
14
# 7. 注入小结
# 7.1 注入方法
# 7.2 注入类型
1)数组:
2)列表: 了解
3)集合:
4)字典:了解
简写:
全写:
# 8. Bean的作用域
作用域即scope,在面向对象程序设计中一般指对象或变量之间的可见范围。而在Spring容器中是指其创建Bean对象相对于其他Bean对象的请求可见范围。
Spring提供singleton和prototype两种基本作用域,另外提供request、session、globalsession三种web作用域;Spring还允许用户制定自己的作用域。
利用
Scope值:
- singleton单例:每次取出的bean都是同一个bean。默认就是这个
- prototype原型:每次取的bean时,都会重新创建一个新的bean,是懒加载。
- request:一次请求一个bean定义对应一个实力(web相关)
- session:一个session定义对应一个实例(web相关)
- globalsession类似于session作用域,只是其用于portlet环境的web应用。如果在非portlet环境被视为session作用域(web相关)
# 9. 自动装配autowire
自动装配就是Spring来自动的注入依赖对象。
Spring的装配支持no\byName\byType\constructor四种自动装配,默认就是no指不支持自动装配的
自动装配的好处是减少构造器注入和setter注入配置,减少配置文件的长度。自动装配通过配置
default:表示使用默认的自动装配,默认就是自动装配需要在
标签中使用default-autowire属性指定,其支持no\byName\byType\constructor四种自动装配,如果需要覆盖默认自动装配; no:意思是不支持自动装配,必须明确指定依赖
byType:按照类型来进行装配,但是要求同一个类型的bean在xml中只能由一个,调用setter方法
byName:通过设置Bean定义属性autowire="byName",意思是根据名字进行制装配,只能用于setter注入。
接口:
public interface HelloInterface{
public String sayHello(String name);
}
2
3
实现类
public class HelloEnglish implements HelloInterface{
public String sayHello(String name){
return "Hello..:" + name;
}
}
2
3
4
5
public class HelloChinese implements HelloInterface{
public String sayHello(String name){
retunr "你好呀" + name;
}
}
2
3
4
5
实体类
public class HelloService{
private HelloInterface hellointer;
public HelloInterface getHellointer(){
return hellointer;
}
public void setHellointer(HelloInterface hellointer){
this.hellointer = hellointer;
}
public void sysHello(String name){
System.out.println("HelloService..." + hellointer.sayHello(name));
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
配置文件
<?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">
<bean class="com.etc.blog.entity.HelloChinese" id="hc">
</bean>
<bean class="com.etc.blog.entity.HelloEnglish" id="he">
</bean>
<bean class="com.etc.blog.service.HelloService" id="hs">
<!-- 注入 -->
<property name="hellointer" ref="he"></property>
</bean>
</beans>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
测试类
@SpringJUnitConfig(locations = "classpath:applicationContext.xml")
public class TestPersonJunit5Spring5 {
// @Autowired
@Autowired
HelloService hs;
@Test
public void test1() {
hs.sayHello("Lao zhang");
}
}
2
3
4
5
6
7
8
9
10
11
# 10. Bean生命周期
# 10.1 生命周期
# 1. 装配bean
是指将java对象转换为Spring = > bean的过程。
注意:Spring支持xml方式,java代码方式,自动装配等。
<bean class="com.etc.blog.entity.Blog" init-method="init_method">
<property name="title" value="测试生命周期"></property>
</bean>
2
3
# 2. 加载applicationContext.xml并实例化
加载applicationContext.xml并实例化,可以通过ClassPathXmlApplicationContext()来加载,当bean为singleton时,改过程就实例化对象,而不需要等待调用applicationContext.getBean()获取bean时才实例化对象。
public static void main(String[] args){
//应用的上下文,用它来获取bean对象
ApplicationContext context = new ClassPathXmlApplicationContext(applicationContext.xml);
//找Spring容器 拿对象
Blog blog = (Blog)context.getBean("blog");
}
2
3
4
5
6
# 3. 属性注入
bean属性注入为bean,底层采用反射方式注入bean
public void setId(int id){
Syetem.out.println("setId..." + id);
this.id=id;
}
2
3
4
# 4. 实现BeanNameAware接口,获取bean id(name)
public class Blog implements Serializable,BeanNAmeAware{
@Override
public void setBeanName(String name){
System.out.println("beanname:" + name);
}
}
2
3
4
5
6
# 5. 实现BeanFactoryAware,获取bean工厂
public class Blog implements Serializable,BeanNameAware,BeanFactoryAware{
@Override
public void setBeanFactory(BeanFactory beanFactory)throws BeansException{
System.out.println("beanFactory:" + beanFactory);
}
}
2
3
4
5
6
# 6. 实现applicationContextAware,获取应用上下文
public class Blog implements ApplicationContextAware{
@Override
public void setApplicationContext(ApplicationContext applicationContext)throws BeansException{
System.out.println("applicationContextAware:" + applicationContextAware);
}
}
2
3
4
5
6
# 7. 实现后置处理器BeanPostProcessor获取before和after,改过程是通过AOP方式实现的,在before和after之间。先带哦用brfore方法,我们自定义类来实现这个接口。
public class TestBeanPostProcessor implements BeanPostProcessor{
@Override
public Object postProcessAfterInitialization(Object bean,String beanName)throws BeansException{
System.out.println("TestBeanPostProcess postProcessAfterInitialization");
return BeanPostProcessor.super.postProcessAfterInitialization(bean,beanNAme);
}
}
2
3
4
5
6
7
# 8. 实现InitializingBean的afterPropertiesSet(),获取初始化方法
public class BLog implements InitializingBean{
@Override
public void afterPropertiesSet() throws Exception{
System.out.println("afterPropertiesSet");
}
}
2
3
4
5
6
# 9. 调用自定义初始化方法。init-method
public void init_method{
System.out.println(7---->:Blog init_method方法);
}
2
3
<bean class="com.etc.blog.entity.Blog" id="b1" init-method="init_method" destory-method="destory_method">
<property name="title" value="测试生命周期"></property>
</bean>
2
3
# 10. 调用Bean后置处理器after
@Override
public Object postProcessAfterInitialization(Object bean,String beanName) throws BeansExcepyion{
System.out.println("********TestpostProcessAfterInitialization******************");
return BeanProcessor.super.postProcessAfterInitialization(bean,beanName);
}
2
3
4
5
# 11. 关闭容器AbstractApplicationContext.registerShutDownHook()
如果不关闭,我们无法看到destory销毁的两个方法;这段代码11不算生命周期的一部分。
public class TestLifeCycle{
@Test
public void test1(){
//非懒加载context实例化的时候就会构造bean对象出来
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//Blog blog = context.getBean(Blog.class);
context.registerShutdownHook();
}
}
2
3
4
5
6
7
8
9
# 12. 调用DisposableBean的destory()
@Override
public void destory() throws Exception{
System.out.println("destory...");
}
2
3
4
# 13. 调用自定义销毁方法destory-method
public void destory_method(){
System.out.println("9---->Blog destory_method方法");
}
2
3
# 控制台输出
# 11. 小结
1、 Spring简介,轻量级的开源框架,低侵入式,核心模块: corebean管理 IOC DI;DataAccessORm框架,web支持的部分;AOP的部分.
2、 Xml 配置bean :
3、 Spring中的bean的scope:
4、 Bean的管理:
5、 IOC/DI :概念,要会描述,能和别人讲清楚。
6、 classPathxmlApplicationContext类继承关系? BeanFactory的关系? getBean()方法的三种参数写法
7、 **注入方式: setter****注入[**最重要] 构造注入
8、 注入类型: 简单类型/引用/集合类型等等
9、 Bean的生命周期
# 12. BeanFactory与ApplicationContext的关系和区别
context包的核心是ApplicationContext接口。它由BeanFactory接口派生而来,因而提供了BeanFactory所有的功能。为了以一种更向面向框架的方式工作以及对上下文进行分层和实现继承,context包还提供了以下的功能:
• MessageSource, 提供国际化的消息访问
• 资源访问,如URL和文件
• 事件传播,实现了ApplicationListener接口的bean
• 载入多个(有继承关系)上下文 ,使得每一个上下文都专注于一个特定的层次,比如应用的web层
由于ApplicationContext包括了BeanFactory所有的功能,所以通常建议优先采用ApplicationContext。除了一些受限的场合比如内存的消耗可能很关键,过多的内存占用可能导致反应速度下降。接下来的章节将叙述由ApplicationContext在BeanFactory的基础上所添加的那些功能。
BeanFactroy采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化,这样,我们就不能发现一些存在的spring的配置问题。而ApplicationContext则相反,它是在容器启动时,一次性创建了所有的Bean。这样,在容器启动时,我们就可以发现Spring中存在的配置错误
# 13. 简单工厂
工厂是一种设计模式: 简单工厂,抽象工厂;
工厂是生成产品的;
# 13.1 概念
简单工厂模式是类的创建模式,又叫做静态工厂方法(Static Factory Method)模式。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。
• 模式的核心是工厂类,决定在什么时候创建哪一个类的实例,而调用者则可以免除直接创建对象的责任。简单工厂模式通过这种做法实现了对责任的分割,当系统引入新的实现方式的时候无需修改调用者
# 13.2 结构组成
PhoneFactory(工厂):核心部分,负责实现创建所有产品的内部逻辑,工厂类可以被外界直接调用,创建所需对象.
Phone(抽象类产品):工厂类所创建的所有对象的父类,封装了产品对象的公共方法,所有的具体产品为其子类对象
HuweiPhone MiPhone(具体产品):简单工厂模式的创建目标,所有被创建的对象都是某个具体类的实例。它要实现抽象产品中声明的抽象方法(有关抽象类)
# 调用工厂获取对象
public static void main(String[] args){
//去工厂拿对象
Phone huaweiPhone = PhoneFactory.createPhone("huawei");
huaweiPhone.takePhoto();
Phone miPhone = PhoneFActory.createPhone("mi");
miPhone.takePhoto();
}
2
3
4
5
6
7
# 配置文件
Spring支持自定义工厂的方式创建对象,我们不使用spring的BeanFactory,但是可以将我们自己建立的这个工厂配置在spring的配置文件中.
<bean class="com.zretc.entity.PhoneFactory" id="iphone" factory-method="createPhone">
<constructor-arg name="type" value="iphone"></construcrtor-arg>
</bean>
<bean class="com.zretc.entity.PhoneFactory" id="huawei" factory-method="createPhone">
<constructor-arg name="type" value="huawei"></construcrtor-arg>
</bean>
2
3
4
5
6
7
# 测试类
@Test
public void testGetNews(){
ClassPathXmlApplicationContext context = new classPathXmlApplicationContext(beanFactory.xml);
Iphone iphone = context.getBean("iphone",Iphone.class);
iphone.takePhoto();
HuaweiPhone huawei = context.getBean("huawei",HuaweiPhone.class);
huawei.takePhoto();
}
2
3
4
5
6
7
8
9
10