Spring的依赖注入
1.1依赖注入案例
1.1.1定义Pet类
package com.jt.demo4;
public interface Pet {
void hello();
}
1.1.2定义Dog类
注解:@Component==>将该类交给Spring容器管理 key:小写类名 value:反射机制创建对象
- 默认值时小写的类名,可以另外单独命名(@Component("/abc"))
package com.jt.demo4;
@Component//将该类交给Spring容器进行管理 key:dog(类名首字母小写) value:反射机制创建对象
public class Dog implements Pet {
@Override
public void hello() {
System.out.println("快到圣诞节了!!!");
}
public Dog() {
System.out.println("dog的无参构造!!!");
}
}
1.1.3定义User类
注解:@Component==>将User对象交给容器管理
@Autowired==>可以将容器中的对象进行注入(默认类型注入)
- 按照类型注入: 如果注入的类型是接口;则自动查找其实现类对象进行注入
- 注意事项: 一般Spring框架内部的接口都是单实现;特殊情况下可以多实现
- 按照名称注入:@Autowired + @Qualifier(“dog”)==>按照id(类的小写名称即Map中的key值)进行注入
package com.jt.demo4;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component //将User对象交给容器管理
public class User {
/**
* 注入:将spring容器中的对象进行引用
* @Autowired: 可以将容器中的对象进行注入
* 1.按照类型注入: 如果注入的类型是接口;则自动查找其实现类对象进行注入
* 注意事项: 一般Spring框架内部的接口都是单实现;特殊情况下可以多实现
* 2.按照名称注入:
*/
@Autowired
private Pet pet;
public void hello() {
pet.hello();
}
public User() {
System.out.println("我是User的无参");
}
}
1.1.4 编辑配置类
注解:@Configuration:标识该类为配置类
**@ComponentScan(“com.jt.demo4”)**扫描本包及子孙包的注解
package com.jt.demo4;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.jt.demo4")
public class SpringConfig {
}
1.1.5 编辑测试代码
package com.jt.demo4;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class SpringDI {
public static void main(String[] args) {
ApplicationContext context =
new AnnotationConfigApplicationContext(SpringConfig.class);
User user = context.getBean(User.class);
user.hello();
}
}
1.1.6运行流程(类型注入)
1.2 多实现类案例讲解
1.2.1 关于案例说明
一般条件下Spring接口都是单实实现,如果遇到多实现,则需要利用按名称注入方式(@Autowired + @Qualifier(“dog”))
程序报错
-
解决方法:利用名称注入@Autowired+@Qualifier(“dog”)
1.3MVC设计思想
1.3.1传统代码结构
说明:如果将所有业务代码都写到一个方法中,则导致后期维护耦合性高,为了提高程序的扩展性,将程序按照MVC设计思想 进行管理
1.3.2MVC设计思想说明
M:Model 数据层
V:View 视图层
C:Control 控制层
总结:MVC主要的目的降低代码的耦合性,提高扩展性,方便后续开发
1.3.3三层代码结构
说明: 基于MVC设计思想的启发,在后端为了提高代码的扩展性,一般将后端代码分为三层.
分层:
- Controller层 主要与页面进行交互 @Controller
- Service层 主要实现后端的业务逻辑 @Service
- Dao层/Mapper层 主要与数据库进行交互 也把该层称之为 “持久层” @Respository/Mapper
1.4"三层"代码结构实现
1.4.1代码结构说明
-
包名:mapper 类两个 一个接口UesrMapper/一个类UserMapperImpl
-
包名:service 类两个 一个接口UesrService/一个类UserServiceImpl
-
包名:controller 一个类:UserController
知识说明:存在业务关系时,被调用的一般会有接口和实现类
1.5@Value注解说明
1.5.1 编辑properties文件
#1.数据结构; key=value
#2.无需添加多余的引号
#3.注意多余的空格
#4.程序在读取properties文件时,默认采用ISO-8859-1编码!!!中文必乱码
name=张三
1.5.2 编辑UserMapper
public interface UserMapper {
void addUser();
}
1.5.3 编辑UserMapperImpl
注解
- @PropertySource(value=“classpath:/addUser.properties”,encoding = “UTF-8”)
- Spring根据指定的路径,加载properties配置文件 数据以键值对Map<key,value>添加到了Spring容器中
- 见注解@PropertySource就
- 写classpath:配置的路径
- 写encoding=“utf-8”:配置字符集
package com.jt.demo6.mapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Repository;
@Repository
//spring根据指定的路径,加载properties配置文件 数据添加到spring容器中
@PropertySource(value="classpath:/addUser.properties",encoding = "UTF-8")
public class UserMapperImpl implements UserMapper{
/**
* @Value 注解的作用: 为属性赋值
* 需求: 从spring容器中动态获取数据
*/
@Value("${name}")
//@Value("张三") //直接写法,扩展性不好
private String name;
@Override
public void addUser() {
System.out.println("新增用户:" + name);
}
}
1.5.4 编辑测试类
package com.jt.demo6;
import com.jt.demo6.config.SpringConfig;
import com.jt.demo6.mapper.UserMapper;
import com.jt.demo6.mapper.UserMapperImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class SpringValue {
public static void main(String[] args) {
ApplicationContext context =
new AnnotationConfigApplicationContext(SpringConfig.class);
//获取的对象 实现类和接口都可以.
UserMapper userMapper = context.getBean(UserMapper.class);
userMapper.addUser();
}
}
mvc架构运行机制
Spring容器开始启动===>调用配置类SpringConfig–>@CompontScan("")扫描
扫描1—>扫描Controller–>通过@Autowired注入Service(由于现在还没扫描到Service所以先忽略@Controller注解下去找Service)=>挂起
扫描2—>扫描mapper–>找到@Repository将mapper实现类MapperImpl交给容器管理
扫描3—>扫描service–>找到注解@Autowired(此时spring容器中只有一个对象(Mapper实现类,controller还没有完成,所以controller不在容器中)将UserMapper注入(面向接口开发,所以不传实现类)—>扫描到@Service将Service交给容器管理(此时容器两个对象)------>回到扫描 1 的挂起
扫描1.1=>挂起—>将Service注入到Controller—>扫描@controller将Controller交给容器
=>>>>>>>Spring容器启动成功(此时三个对象在容器中)
==>context.getBean(UserController.class);拿到controller
==>调用
调用图解
1.6关于IOC-DI的总结
-
什么是IOC:控制反转,将对象交给Spring容器管理,由容器管理对象生命周期
-
什么是DI:依赖注入,为当前对象注入属性
-
总结: 使用IOC-DI可以极大程度上实现代码的松耦合(解耦)
常用注解
- @ComponentScan 包扫描注解 扫描注解
- @Bean 标识该方法的返回值交给Spring容器管理
- @Scope 控制多例和单例
- @Scope(“prototype”)//表示多例对象
- @Scope(“singleton”)//表示单例对象
- @Lazy 懒加载
- @PostConstruct 初始化方法
- @PreDestroy 销毁方法
- @Component 将当前类未来的对象交给容器管理
- @Autowired 按照类型进行注入
- @Qualifier 按照名称进行注入
- @Repository 标识持久层注解
- @Service 标识Service层
- @Controller 标识Controller层
- @Value 为属性赋值
- @PropertySource 加载指定路径的配置文件properties