Documentation
搭配工程文件学习测试
Spring是一个轻量级的控制反转(IoC)和面向切面编程(AOP)的框架
以下是对IoC内容的实践与理解:
首先,什么是IoC?
名词解释
IoC is also known as dependency injection (DI).
IoC——Inversion of control. (控制反转)
DI——Dependency Injection(依赖注入)
IoC特点
- 控制权由程序代码转移到了外部容器
- 由容器动态地将某种依赖关系注入到组件之中
- 组件之间的依赖关系由容器在运行期决定
正常业务逻辑
正常业务逻辑如下:
-
UserDao接口
-
UserDaoImpl实现类(实现类就是实现接口)
-
UserService 业务接口
-
UserServiceImpl 业务实现类
Q:这个时候业务层怎么调用Dao层?
A:业务层调用
业务实现类
去获取数据层
-
ServiceImpl
public class UserServiceImpl implements UserService{ private UserDao userDao = new UserDaoImpl(); public void getUser(){ userDao.getUser(); } }
-
Test
public class Test{ public static void main(String[] args){ //用户只接触业务层 UserService userService = new UserServiceImpl(); userService.getUser(); } }
Q:但是当增加一个新的Dao层实现方法,并且用户想调用,怎么实现?
A:新的dao层的方法是一个新的类,只能在业务处理类有调用到实现方法的时候修改
-
UserDapMySqlImpl
public class UserDapMySqlImpl implements UserDao{ public void getUser(){ System.out.pritnln("新的方法"); } }
-
ServiceImpl(此处调用,此处修改)
public class UserServiceImpl implements UserService{ private UserDao userDao = new UserDapMySqlImpl(); //这里修改 public void getUser(){ userDao.getUser(); } }
Q:每增加一个新的Dao方法,都要修改业务层实现方法,怎么不修改?
A:利用set方法进行动态实现值的注入
- ServiceImpl
public class UserServiceImpl implements UserService{
private UserDao userDao;
//利用set进行动态实现值的注入
public void setUserDao(UserDao userDao){
this.userDao = userDao;
}
public void getUser(){
userDao.getUser();
}
}
- Test
public class Test{
public static void main(String[] args){
//用户只接触业务层
UserService userService = new UserServiceImpl();
//随心调用
((UserServiceImpl)userService).setUserDao(new UserDapMySqlImpl);
((UserServiceImpl)userService).setUserDao(new UserDapImpl);
userService.getUser();
}
}
以上。正常的业务逻辑中,程序是主动创建对象,控制权在程序猿
手中;而使用set方法之后,程序不再具有主动性,而是变成了被动的接收对象,主动权在用户
手中。不再去管理对象的创建,耦合性大大降低,专注业务实现。
控制反转是什么?
IoC,是一种设计思想,而DI是实现IoC的一种方法。没有IoC的程序中,我们使用面向对象编程,对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序猿自己控制。控制反转则将对象的创建转移给第三方,也就是获得依赖对象的方式反转了。
Spring容器初始化
Spring容器在初始化时先读取配置文件
,根据配置文件或元数据创建与组织对象存入容器中
,程序使用时再从IoC容器中取出需要的对象。
配置Bean
采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的。
而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式
定义在实现类中,从而达到了零配置的目的。
以上,控制反转是一种通过描述(XML或注解)
并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)。
1、IoC创建对象的方式
(Bean被创建的调用方式)也就是 Bean注入
加载完XML就已经把所有对象创建了。
1)、使用无参构造
<!--无参构造,普通注入-->
<bean id="user" class="com.suren.pojo.User">
<property name="name" value="素人"/>
</bean>
2)、有参构造函数
-
下标
<!--有参构造 下标赋值--> <bean id="user" class="com.suren.pojo.User"> <constructor-arg index="0" value="素人"/> </bean>
-
类型
<!--有参构造 类型 不建议使用--> <bean id="user" class="com.suren.pojo.User"> <constructor-arg type="java.lang.String" value="素人"/> </bean>
-
参数名
<!--直接通过参数名--> <bean id="user" class="com.suren.pojo.User">--> <constructor-arg name="name" value="素人"/> </bean>
2、Spring配置
1)、别名
<alias name="user" alias="user2"/>
2)、Bean的配置
id : bean的唯一标识符,相当于变量名
class :bean对象所对应的全限定名:包名+类
name : 也是别名,可以用来获取
3)、 import
在applicationContext里包含以下,就能导入这些bean文件
<import resource="bean1.xml"/>
<import resource="bean2.xml"/>
3、依赖注入实现
1)、构造器注入(Bean注入
)
IoC创建对象,如上述
2)、 Set方式注入(推荐)
- 依赖注入:Set注入,为每个属性提供setter方法,对应属性
- 依赖:bean对象的创建依赖于容器
- 注入:bean对象的所有属性,由
容器来注入
-
集合类型的属性注入
Spring 对每个常用集合对象,提供单独元素完成注入
- List 对象 ---- 元素
- Set 对象 ---- 元素
- Map对象 ----
- Properties 对象 ---- 元素
(map和properties是
{}
输出)
3)、拓展方式注入
-
P空间 – properties —对应Set方法
将 子元素,简化为元素属性配置
xmlns:p="http://www.springframework.org/schema/p" <bean id="" class="" p:xx=""/>
-
C空间 —对应构造器方法
xmlns:c="http://www.springframework.org/schema/c" <bean id="" class="" c:xx=""/>
4、bean的自动装配
作用域
Scope | Description |
---|---|
singleton | (Default) Scopes a single bean definition to a single object instance for each Spring IoC container. |
prototype | Scopes a single bean definition to any number of object instances. |
request | Scopes a single bean definition to the lifecycle of a single HTTP request. That is, each HTTP request has its own instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring ApplicationContext . |
session | Scopes a single bean definition to the lifecycle of an HTTP Session . Only valid in the context of a web-aware Spring ApplicationContext . |
application | Scopes a single bean definition to the lifecycle of a ServletContext . Only valid in the context of a web-aware Spring ApplicationContext . |
websocket | Scopes a single bean definition to the lifecycle of a WebSocket . Only valid in the context of a web-aware Spring ApplicationContext . |
-
单例模式 singleton
<bean id="accountService" class="com.something.DefaultAccountService" scope="singleton"/>
-
原型模式 prototype
每次从容器中获取时,都会产生新的对象(hashcode可见)
<bean id="accountService" class="com.something.DefaultAccountService" scope="prototype"/>
三种装配方式
-
xml
-
java
-
隐式自动装配
<bean id="person" class="com.suren.pojo.Person"> <property name="name" value="素人"/> <property name="cat" ref="cat"/> <property name="dog" ref="dog"/> </bean> //等价 <bean id="person" class="com.suren.pojo.Person" autowire="byName"> <property name="name" value="素人"/> </bean>
-
使用注解实现自动装配
-
导入约束
xmlns:context="http://www.springframework.org/schema/context"
-
配置注解的支持
<context:annotation-config>
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> <context:annotation-config/> </beans>
-
@Autowired 直接在属性、方法上添加
- 使用之后,就可以去掉set方法
- @Nullable 等价方法 @Autowired (false)
-
如果bean文件id和class文件不同,可以用@Qualifier(value=“想要的id”),新版本可以跑
-
5、使用注解开发
- 属性注入
//相当于<bean id="user" class="com.suren.pojo.User"/>
@Component
public class User {
// 相当于<property name="name" value="素人"/>
@Value("素人")
public String name;
}
- 衍生的注解
功能一样,都是把类注入到容器中,组件的意思
-
自动装配
- @Autowired : 自动匹配通过类型。 如果Autowired不能唯一自动装上属性,通过@Qualifier(value="想要的id") - @Resource : 自动匹配通过名字。 - @Nullable : 表示这个字段可以为空
-
作用域
-
小结
6、▶️用javaconfig实现配置
(Spring_06)
1. @Configuration
这个注解可以注册到Spring容器中(本身就是一个Component
)
表示这是一个配置类,等价于xml配置文件
package org.springframework.context.annotation;
@java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE})
@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@java.lang.annotation.Documented
@org.springframework.stereotype.Component
public @interface Configuration {
@org.springframework.core.annotation.AliasFor(annotation = org.springframework.stereotype.Component.class)
java.lang.String value() default "";
boolean proxyBeanMethods() default true;
}
-
配置类
- 配置类的结合
-
测试类
//使用配置类,只能使用AnnotationConfig上下文获取容器,通过配置类的class对象加载 ApplicationContext context = new AnnotationConfigApplicationContext(UserConfig.class); User getUser=(User)context.getBean("getUser"); //这里是方法名 System.out.println(getUser.getName());