前置知识:
- Java
包含知识点
- IOC
- Bean
一些名词解释:
- 业务逻辑:例如:进销存的货品出库入库业务
- 系统服务:例如:货品出库入库时必须的日志记录
- 容器:意思是管理应用对象的配置和生命周期
框架
封装了特定的流程,让程序员专注于业务逻辑
IOC和Bean容器
接口
沟通的中介物的抽象化,说明了对外的交互,隐藏具体实现。
面向接口编程
- 分层,各层间只依赖接口而非实现类。
- 接口实现的变动不影响各层间的调用
- 隐藏具体实现和多态
IOC
控制反转:应用程序不负责依赖对象的创建和维护,而是由外部容器负责创建和维护。Martin Fowler指出:“获得依赖对象的过程被反转了”依赖的管理由自身管理,变为IOC容器主动注入。在运行期间,动态的将依赖关系注入到对象里。
DI(依赖注入)是一种IOC的实现方式
- 找到IOC容器
- 容器返回对象
- 使用对象
在Spring中,IOC对象都叫做Bean,
<bean id="oneInterface" class="com.xxxx.XxxImpl"></bean>
IOC实现原理
- 工厂+反射+XML配置文件
IOC+DI
<bean id="userService" class="top.linxz.java.UserServiceImpl"> <!-- IOC -->
<property name="name" value="李四"/> <!-- DI,不需要修改源码就注入了属性 -->
</bean>
Bean
Bean实例化三种方式
- 使用类构造器实例化(默认无参数)
- 使用静态工厂方法实例化(简单工厂模式)
- 使用实例工厂方法实例化(工厂方法模式)
Bean容器
- BeanFactory提供配置结构和基本功能,加载并初始化Bean
- ApplicationContext是容器,保存了Bean对象并在Spring中使用
- 初始化它的方式:
- 本地文件:new FileSystemXmlApplicationContext("F:/xxx/xxx.xml")
- Classpath:new ClassPathXmlApplicationContext("classpath:spring-context.xml")
- Web中则依赖servlet或listener
- listener: <listener-class>
- servlet:ContextLoaderServlet
- 初始化它的方式:
Spring注入方式
注入是指在启动Spring容器加载bean配置的时候,完成对变量的赋值行为
常用两种:
- 设值注入:Impl需要有injectionDAO的set方法
<bean id="xxx" class="com.xxx.xxxImpl">
<property name="injectionDAO" ref="injectionDAO"/>
<!--这个property就注入了下面那个bean-->
</bean>
<bean id="injectionDAO" class="com.xxx"></bean>
- 构造注入
<bean id="xxx" class="com.xxx.xxxImpl">
<constructor-arg name="injectionDAO" ref="injectionDAO"/>
<!--这个constructor-arg就在构造器里的对应参数里注入了下面那个bean-->
</bean>
<bean id="injectionDAO" class="com.xxx"></bean>
Bean专题
Bean配置项
- Id(IOC中唯一)
- Class
- Scope
- Constructor arguments
- Properties
- Autowiring mode
- lazy-initializaion mode
- Initialization/destruction method
Bean的作用域
- singleton:单例,一个bean容器(ApplicationContext)中一份,(Sping里默认是这个模式)
- prototype:每次使用bean时,重新创建新的实例
- request:每次http,request内有效
- session:session内有效
- global session:portlet(用于在多个web应用之间统一一个session)的web中有效
Bean的生命周期
- 定义:xml定义
- 初始化:
- 配置初始化的方法<bean init-method="init" /> 则调用bean里的public void init()方法
- 实现beans.factory.InitializaingBean接口的afterPropertiesSet()方法
- 全局的在<beans default-init-method />
- 三种方法顺序:实现方法比xml优先,全局默认被覆盖
- 使用:
- 销毁:
- 配置销毁方法<bean destroy-method="cleanup" /> 则调用bean里的public void cleanup()方法,配置了一定要有这个方法
- 实现beans.factory.DisposableBean接口的destroy方法
- 全局的在<beans default-destroy-method />
- 三种方法顺序:实现方法比xml优先,全局默认被覆盖
Aware接口
实现了Aware接口的bean初始化后可以获得相应资源
- BeanNameAware:获得声明bean的名字
- ...
Bean的自动装配(Autowiring)
- no
- byName:根据类的实例名字和属性ID完全一致的bean,在<beans default-autowire="byName">,不再需要<bean><property name="" ref="" />
- byType:根据类的类型匹配
- constructor:根据构造方法的参数
Bean装配的Resources
针对资源文件的统一接口
- ResourceLoader,getResource("")得到文件路径,可用字符串路径如下
- classpath:com/myapp/config.xml:
- file:/data/xx.xml
- http://myserver/logo.png
- (none) /data/config.xml
Bean的注解实现
classpath扫描和组件管理
使用Java注解定义Bean
- @Component是一个通用注解,可用于任何bean
- @Repository,注解DAO类,持久层
- @Service,注解Service类,即服务层
- @Controller,Controller,即控制层
元注解
如@Component可以用在一个注解上,
自动检测并注册Bean到ApplicationContext中
在XML配置通常用<context:component-scan base-package="org.example"/>包含了<context:annotation-config/>相当于启动注解。
使用过滤器自定义扫描
例子:把找出Stub和Repository并排除Respository
<beans>
<context:component-scan base-package="org.example">
<context:include-filter type="regex" expression=".*Stub.*Repository" />
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository" />
</context:component-scan>
</beans>
定义Bean
@xxx("xxxx")显式设置bean名字,默认是类的小写开头
作用域
@Scope("xxx")选择你的scope
@Required
通常用于bean属性的setter方法,必须在配置时就被填入
@Autowired
可用在setter上,也可以用在构造器和成员变量。
如果失败会抛异常,但@Autowired(required=false)就不会
Spring类的注入
可以用在Spring自己的类,如BeanFactory,ApplicationContext,Environment,ResourceLoader
List、Set、Map的注入
@Autowired注入List
和Set
或Map<String,x>
的类,这里的String是Bean的ID,如果希望List中的Bean有序,可用@Order
Qualifier
多个实现类时,缩小@Autowired的查找范围,缩小查找的注解的名字,具体指定用哪个实现类
基于Java容器的注解
@Bean是XML配置Bean的java版。通常配合@Configuration使用
@Configuration
public class AppConfig{
@Bean
public MyService myService(){
return new MyServiceImpl();
}
}
等于
<beans>
<bean id="myService" class="com.xxx.MyServiceImpl" />
</beans>
@ImportResource
@Configuration
@ImportResource("classpath:/com/acme/jdbc.properties")
public class AppConfig{
@Value("${jdbc.url}")
private String url;
@Bean
public DataSource dataSource(){
return new DriverManagerDataSource(url)
}
}
等于在XML
<beans>
<context:property-placeholder location="classpath:/com/acme/jdbc.properties" />
<bean class="com.xxx.DriverManagerDataSource">
<property name="url" value="${jdbc.url}" />
</bean>
参考
- Spring入门篇,moocer,https://www.imooc.com/learn/196
关于我:
linxinzhe,全栈工程师,目前供职于某500强通信企业。人工智能,区块链爱好者。
GitHub:https://github.com/linxinzhe
欢迎留言讨论,也欢迎关注我~
我也会关注你的哦!
网友评论