Spring 学习
Spring 基础介绍
学习轻量级的控制反转(IOC),面向切面(AOP)
什么是 Spring?
- 通过 IOC 的技术达到松耦合的目的
- AOP 的支持,允许通过分离应用的业务逻辑与系统级服务进行内聚性的开发。系统级的服务:与具体的业务代码无关,无论什么都需要应用的服务
- 包含并管理应用对象的配置和生命周期,这个意义上是一种容器
- 将简单的组件组合称为复杂的应用,这个意义上是框架
Why Spring?
我们将对象的生命周期的管理交给了 Spring,所有的对象都叫做 bean,管理对象的容器叫做 bean 容器,省去了对象的创建和开销的过程。
作用
- 容器
- 对多种技术的支持
- AOP:事务管理,日志等
- 提供了众多方便的辅助类(JDBC 等)
适用范围
- 单独使用 Bean 容器,Bean 管理
- 使用 AOP 进行切面处理
- 其他的,如对消息的支持
Spring 框架
框架与类库
- 框架封装了逻辑、高内聚的,类库则是松散的工具的组合
- 框架专注于某一领域,类库更通用
Spring IOC 容器
接口及面向接口编程
接口:声明没有实现
抽象类:与一般的一样,除了不能实例化
什么是 IOC
控制反转,控制权的转移,我们并不负责依赖对象的创建和维护,而是需要使用的时候,由外部容器负责创建和维护。
DI(依赖注入),负责对象组装功能。在 IOC 容器在运行期间,动态的将某种依赖关系注入到对象当中。
目的 :创建对象并且组装对象之间的关系。
获得依赖对象的过程被反转了。
Spring 的 Bean 配置和初始化
Spring 对于 Bean 整个的使用有两种方式:一种是通过注解,一种是基于 xml 的配置。
xml 里面
初始化过程,基础,两个包
- BeanFactory 提供配置结构和基本功能,加载并初始化 Bean
- ApplicationContext 保存了 Bean 对象,也就是容器。加载方式:
加载本地文件;绝对路径
Classpath;相对路径
web 应用中依赖 servlet 或者 Listener
Spring 注入
容器加载 bean 的时候,完成对变量的赋值行为。
常用的两种方式:设值注入,构造注入
设值注入
也就是通过 set 的方式注入。
1 | <bean id="injection" class="top.wuxiya.spring.Hello"> |
构造注入
也就是通过 构造方法的方式注入。
注意:当通过构造注入的时候,构造器传入的变量名称必须与 name 设定的一致。
构造中,看 name。name 名称与传入的变量名匹配。
set 注入中,看类型。
一般来说最好都一样就不用区分了。
1 | <bean id="injectionService" class="top.wuxiya.spring.Hello"> |
DAO——数据库
service——业务逻辑的部分
Bean 的配置
Bean 的配置项
获取 Bean 的两种方式:通过 Id 来获取,通过 Bean 的类型来获取
- Id:唯一标识
- Class:实例化的具体类——必须
- Scope:作用域
- 构造器参数
- Properties:属性
- 懒加载模式
- 自动装配的模式
- 初始化和销毁的方法
Bean 的作用域
- singleton:单例模式,一个 Bean 容器中只存在一个。默认
- prototype:每次请求都创建新的实例,destroy 方式不生效
- request:每次 http 请求创建一个实例且仅在但钱 request 内有效
- session:同上,当前 session 中有效
- glodbal session:单点登陆??
Bean 的生命周期
初始化两种
- 一种为在 Bean 声明中添加 init-method=”methodName”
- 实现 InitializingBean 接口,覆盖 afterPropertiesSet(),自动调用这个方法
销毁两种
- 一种为在 Bean 声明中添加 destory-method=”methodName,cleanup”
- 实现 DisposableBean 接口,覆盖 destroy(),自动调用这个方法
全局初始化和销毁方法
在 beans 中添加,default-init-method=”name”,default-destory-method=”name”
默认的方法可以不被实现,并且只要局部有一种实现就被覆盖。
局部初始化的两种方式,必须实现,其中接口的优先级大于方法的添加。
Aware 接口
- 实现了 Aware 接口的 bean 在初始化之后,可以获取对应资源
- 对 Spring 进行简单的扩展提供了方便的入口
- 可以对 Spring 对应资源进行操作(慎重)
比如得到加载当前 bean 的上下文
Bean 的自动装配(Autowiring)
- No 不做任何操作,默认
- byname:根据属性名。设置
,并且需要设置 set 方法。这个和 set 注入类似(看传入名),只不过不用再每一个 bean 里面显示声明 property。 - byType:bean 的类型。多个类型抛异常。和 bean 的 ID 没有关系,在 set 方法(看类型)中匹配类型。
- constructor:应用于构造器参数。在构造方法中查找构造器方法传入的类型。没有找到抛异常
Resources
针对资源文件的统一接口
Bean 的注解
Bean 管理的类注解实现
类的注解
- @Component 是一个通用注解,可用于任何 bean
- @Repository:用于注解 DAO 类,即持久层
- @Service:Service 类,服务层
- @Controller 用于 Controller 类,即控制层(MVC)
元注解:许多注解可以作为自己的代码,即“元数据注解”。可以用于领域给注解。还可以定制注解
类的自动检测及 Bean 的注册
- 默认情况下,类被自动发现并注册 bean 的条件是:使用@Component,@Repository,@Service,@Controller 注解或者使用@Component 的自定义注解
- 使用过滤器进行自定义扫描,修改自动发现的行文
- 还可以禁用自动发现与注册
定义 bean
- 可以显示指定 Bean 的 name。否则默认是类名的小写。
- 还可以自定义命名的规则(一定要包含一个无参的构造器)。
作用域@Scope
- @Scope(“prototype”)
@Repository - 也可以自定义设置 scope
代理方式
使用 scoped-proxy 属性指定代理,有三个值可选:no,interfaces,targetClass
Bean 的(Autowiring)注解说明
@Required(不常用)
- 是用于 bean 属性的 setter 方法
- 表示受影响的 bean 属性必须在配置时被填充,通过在 bean 定义或通过自动装配一个明确的属性值
@Autowired
使用 1
- 传统的 setter 方法
- 也可以用于构造器或者成员变量
- 我们可以注解那些众所周知的解析依赖性接口,比如:BeanFactory,MessageSource 等
注意
- 默认情况下,如果找不到和实施的 bean 会抛出异常,所有可以用@Autowired(required=false)来避免
- 每一个类只能有一个构造器被标注为 true
- 如果为 true 的必要属性,那么建议用@Resource
使用 2
- 可以通过添加注解给需要该类型实例的数组的字段和方法,以提供 ApplicationContext 中所有特定类型的 bean
public void setFunc(Setname){
this.name=name;
}
List;
Map<String,BeanType>(String 为 bean 的 id) - 如果希望数组有序,可以让 bean 实现@Order 注解(Order 只针对 List 或 set)
注意
@Autowired 是由两种类型的 Bean 进行处理的,因此自定义这两种类的时候,我们需要通过
@Qualifier
可以指定特定的唯一的 bean,当子类有多个类型的时候。
我们一般用@Resource 来通过注解,这是一个与所声明类型无关的匹配过程。
- @Auto 用于属性,构造器,多参数方法,允许在参数级别使用@Qual 缩小范围
- @Resource 适用于成员变量、只有一个参数的 setter 方法,使用构造器,多参数用@Qual
1 |
|
基于 Java 的容器注解
@Configuration
- @Configuration(类注解,相当于一个配置类)
@Bean(方法注解)
public Myservice myService(){
return new MyserviceImpl();
//相当于定义了一个 id 叫做 myService 的 Bean
}
@Bean(默认单例)
- 自定义 Bean 的那么@Bean(name=”myName”)。默认的是方法的名称
@Bean(init-method=””)
@Bean(destroyMethod=””)
@ImportResource,加载资源文件
配置数据库
在 xml 中,用<context:property-placeholder location=”…./jdbc.properties”>
下面用${jdbc.url}(username,password)
仍然
@Configuration
@ImportResource(“classpath:…”)
@Value(“${jdbc.url}”)
@Value(“${jdbc.username}”)
- 需要注意的是,username 拿到的是登录系统的用户名,因此一般来说数据库的用户名都加 jdbc
也就说与操作系统重复的都需要进行性注意
@Scope
- @Bean
@Scope(value=”session”,proxyMode=)
基于泛型的自动装配
@Resource
- 注解变量或者 setter
- @–(name=””),默认是属性名和 setter 方法得出