Spring IoC&DI

1. IoC & DI ⼊⻔

1.1 Spring 是什么?

         Spring是⼀个开源框架, 他让我们的开发更加简单. 他⽀持⼴泛的应⽤场
景, 有着活跃⽽庞⼤的社区, 这也是Spring能够⻓久不衰的原因
        Spring 是包含了众多⼯具⽅法的 IoC 容器

1.1.1 什么是容器?

容器是⽤来容纳某种物品的(基本)装置。

List/Map -> 数据存储容器
Tomcat -> Web 容器

1.1.2 什么是 IoC?

        在类上⾯添加 @RestController 和 @Controller 注解, 就是把这个对象交给Spring管理, Spring 框架启动时就会加载该类. 把对象交 给Spring管理, 就是IoC思想.

IoC: Inversion of Control (控制反转), 也就是说 Spring 是⼀个"控制反转"的容器.

1.2 IoC 介绍

接下来我们通过案例来了解⼀下什么是IoC
需求: 造⼀辆⻋

1.2.1 传统程序开发

我们的实现思路是这样的:
先设计轮⼦(Tire),然后根据轮⼦的⼤⼩设计底盘(Bottom),接着根据底盘设计⻋⾝(Framework),最 后根据⻋⾝设计好整个汽⻋(Car)。这⾥就出现了⼀个"依赖"关系:汽⻋依赖⻋⾝,⻋⾝依赖底盘,底 盘依赖轮⼦.
1 public class NewCarExample {
2 public static void main(String[] args) {
3 Car car = new Car();
4 car.run();
5 }
6
7 /**
8 * 汽⻋对象
9 */
10 static class Car {
11 private Framework framework;
12
13 public Car() {
14 framework = new Framework();
15 System.out.println("Car init....");
16 }
17 public void run(){
18 System.out.println("Car run...");
19 }
20 }
21
22 /**
23 * ⻋⾝类
24 */
25 static class Framework {
26 private Bottom bottom;
27
28 public Framework() {
29 bottom = new Bottom();
30 System.out.println("Framework init...");
31 }
32 }
33
34 /**
35 * 底盘类
36 */
37 static class Bottom {
38 private Tire tire;
39
40 public Bottom() {
41 this.tire = new Tire();
42 System.out.println("Bottom init...");
43 }
44 }
45
46 /**
47 * 轮胎类
48 */
49 static class Tire {
50 // 尺⼨
51 private int size;
52
53 public Tire(){
54 this.size = 17;
55 System.out.println("轮胎尺⼨:" + size);
56 }
57 }
58 }

1.2.2 问题分析

程序的耦合度⾮常⾼(修改⼀处代码, 影响其他处的代码修改)
修改之后, 其他调⽤程序也会报错, 我们需要继续修改

1.2.3 解决⽅案

        先设计汽⻋的⼤概样⼦,然后根据汽⻋的样⼦来设计⻋⾝,根据⻋⾝来设计 底盘,最后根据底盘来设计轮⼦. 这时候,依赖关系就倒置过来了:轮⼦依赖底盘, 底盘依赖⻋⾝, ⻋⾝依赖汽⻋
        此时,我们只需要将原来由⾃⼰创建的下级类,改为传递的⽅式(也就是注⼊的⽅式),因为我们不 需要在当前类中创建下级类了,所以下级类即使发⽣变化(创建或减少参数),当前类本⾝也⽆需修 改任何代码,这样就完成了程序的解耦.

1.2.4 IoC程序开发

1 public class IocCarExample {
2 public static void main(String[] args) {
3 Tire tire = new Tire(20);
4 Bottom bottom = new Bottom(tire);
5 Framework framework = new Framework(bottom);
6 Car car = new Car(framework);
7 car.run();
8 }
9
10 static class Car {
11 private Framework framework;
12
13 public Car(Framework framework) {
14 this.framework = framework;
15 System.out.println("Car init....");
16 }
17 public void run() {
18 System.out.println("Car run...");
19 }
20 }
21
22 static class Framework {
23 private Bottom bottom;
24
25 public Framework(Bottom bottom) {
26 this.bottom = bottom;
27 System.out.println("Framework init...");
28 }
29 }
30
31 static class Bottom {
32 private Tire tire;
33
34 public Bottom(Tire tire) {
35 this.tire = tire;
36 System.out.println("Bottom init...");
37 }
38 }
39
40 static class Tire {
41 private int size;
42
43 public Tire(int size) {
44 this.size = size;
45 System.out.println("轮胎尺⼨:" + size);
46 }
47 }
48 }

优点:资源不由使⽤资源的双⽅管理,⽽由不使⽤资源的第三⽅管理

1. 资源集中管理: IoC容器会帮我们管理⼀些资源(对象等), 我们需要使⽤时, 只需要从IoC容器中去取
就可以了
2. 我们在创建实例的时候不需要了解其中的细节, 降低了使⽤资源双⽅的依赖程度, 也就是耦合度.

1.3 DI 介绍

DI: Dependency Injection(依赖注⼊)
容器在运⾏期间, 动态的为应⽤程序提供运⾏时所依赖的资源,称之为依赖注⼊。
上述代码为例

2. IoC & DI 使⽤

        既然 Spring 是⼀个 IoC(控制反转)容器,作为容器, 那么它就具备两个最基础的功能:
        Spring 容器 管理的主要是对象, 这些对象, 我们称之为"Bean". 我们把这些对象交由Spring管理, 由 Spring来负责对象的创建和销毁. 我们程序只需要告诉Spring, 哪些需要存, 以及如何从Spring中出 对象

3. IoC 详解

        IoC控制反转,就是将对象的控制权交给Spring的IOC容器,由IOC容器创建及管理对
象,也就是bean的存储

3.1 Bean的存储

Spring框架为了更好的服务web应⽤程序, 提供了更丰富的注解.
共有两类注解类型可以实现:
1. 类注解:@Controller、@Service、@Repository、@Component、@Configuration.
2. ⽅法注解:@Bean

3.1.1 @Controller(控制器存储)

使⽤ @Controller 存储 bean 的代码如下所⽰:
1 @Controller // 将对象存储到 Spring 中
2 public class UserController {
3 public void sayHi(){
4 System.out.println("hi,UserController...");
5 }
6 }
从Spring容器中获取对象
1 @SpringBootApplication
2 public class SpringIocDemoApplication {
3
4 public static void main(String[] args) {
5 //获取Spring上下⽂对象
6 ApplicationContext context = SpringApplication.run(SpringIocDemoApplicatio
7 //从Spring上下⽂中获取对象
8 UserController userController = context.getBean(UserController.class);
9 //使⽤对象
10 userController.sayHi();
11 }
12 }
        因为对象都交给 Spring 管理了,所以获取对象要从 Spring 中获取,那么就得先得到 Spring 的上下 ⽂
        这个上下⽂, 就是指当前的运⾏环境, 也可以看作是⼀个容器, 容器⾥存了很多内容, 这些内容是当前 运⾏的环境
获取bean对象的其他⽅式
1 public interface BeanFactory {
2 
3 
4 
5 // 1. 根据bean名称获取bean
6 Object getBean(String var1) throws BeansException;
7 // 2. 根据bean名称和类型获取bean
8 <T> T getBean(String var1, Class<T> var2) throws BeansException;
9 // 3. 按bean名称和构造函数参数动态创建bean,只适⽤于具有原型(prototype)作⽤域的bean
10 Object getBean(String var1, Object... var2) throws BeansException;
11 // 4. 根据类型获取bean
12 <T> T getBean(Class<T> var1) throws BeansException;
13 // 5. 按bean类型和构造函数参数动态创建bean, 只适⽤于具有原型(prototype)作⽤域的bean
14 <T> T getBean(Class<T> var1, Object... var2) throws BeansException;
15 
16 
17 }
Bean 命名约定
1.Spring bean是Spring框架在运⾏时管理的对象, Spring会给管理的对象起⼀个名字.
2.程序开发⼈员不需要为bean指定名称(BeanId), 如果没有显式的提供名称(BeanId),Spring容器将为该 bean⽣成唯⼀的名称
3.命名约定使⽤Java标准约定作为实例字段名. 也就是说,bean名称以⼩写字⺟开头,然后使⽤驼峰式 ⼤⼩写.
⽐如
类名: UserController, Bean的名称为: userController
类名: AccountManager, Bean的名称为: accountManager
类名: AccountService, Bean的名称为: accountService
根据这个命名规则, 我们来获取Bean
1 @SpringBootApplication
2 public class SpringIocDemoApplication {
3
4 public static void main(String[] args) {
5 //获取Spring上下⽂对象
6 ApplicationContext context = SpringApplication.run(SpringIocDemoApplicatio
7 //从Spring上下⽂中获取对象
8 //根据bean类型, 从Spring上下⽂中获取对象
9 UserController userController1 = context.getBean(UserController.class);
10 //根据bean名称, 从Spring上下⽂中获取对象
11 UserController userController2 = (UserController) context.getBean("userCon
12 //根据bean类型+名称, 从Spring上下⽂中获取对象
13 UserController userController3 = context.getBean("userController",UserCont
14 
15 System.out.println(userController1);
16 System.out.println(userController2);
17 System.out.println(userController3);
18 }
19 }

3.1.2 @Service(服务存储)

使⽤ @Service 存储 bean 的代码如下所⽰:

1 @Service
2 public class UserService {
3 public void sayHi(String name) {
4 System.out.println("Hi," + name);
5 }
6 }
读取 bean 的代码:
1 @SpringBootApplication
2 public class SpringIocDemoApplication {
3
4 public static void main(String[] args) {
5 //获取Spring上下⽂对象
6 ApplicationContext context = SpringApplication.run(SpringIocDemoApplicatio
7 //从Spring中获取UserService对象
8 UserService userService = context.getBean(UserService.class);
9 //使⽤对象
10 userService.sayHi();
11 }
}

3.1.3 @Repository(仓库存储)

使⽤ @Repository 存储 bean 的代码如下所⽰:
1 @Repository
2 public class UserRepository {
3 public void sayHi() {
4 System.out.println("Hi, UserRepository~");
5 }
6 }
读取 bean 的代码:
1 @SpringBootApplication
2 public class SpringIocDemoApplication {
3
4 public static void main(String[] args) {
5 //获取Spring上下⽂对象
6 ApplicationContext context = SpringApplication.run(SpringIocDemoApplicatio
7 //从Spring上下⽂中获取对象
8 UserRepository userRepository = context.getBean(UserRepository.class);
9 //使⽤对象
10 userRepository.sayHi();
11 }
12 }

3.1.4 @Component(组件存储)

使⽤ @Component 存储 bean 的代码如下所⽰:
1 @Component
2 public class UserComponent {
3 public void sayHi() {
4 System.out.println("Hi, UserComponent~");
5 }
6 }
读取 bean 的代码:
1 @SpringBootApplication
2 public class SpringIocDemoApplication {
3
4 public static void main(String[] args) {
5 //获取Spring上下⽂对象
6 ApplicationContext context = SpringApplication.run(SpringIocDemoApplicatio
7 //从Spring上下⽂中获取对象
8 UserComponent userComponent = context.getBean(UserComponent.class);
9 //使⽤对象
10 userComponent.sayHi();
11 }
12 }

3.1.5 @Configuration(配置存储)

使⽤ @Configuration 存储 bean 的代码如下所⽰:
1 @Configuration
2 public class UserConfiguration {
3 public void sayHi() {
4 System.out.println("Hi,UserConfiguration~");
5 }
6 }
读取 bean 的代码:
1 @SpringBootApplication
2 public class SpringIocDemoApplication {
3
4 public static void main(String[] args) {
5 //获取Spring上下⽂对象
6 ApplicationContext context = SpringApplication.run(SpringIocDemoApplicatio
7 //从Spring上下⽂中获取对象
8 UserConfiguration userConfiguration = context.getBean(UserConfiguration.cl
9 //使⽤对象
10 userConfiguration.sayHi();
11 }
12 }

3.2 为什么要这么多类注解?

这个也是和应⽤分层是呼应的. 让程序员看到类注解之后,就能直接了解当前类的⽤途.
@Controller:控制层, 接收请求, 对请求进⾏处理, 并进⾏响应.
@Servie:业务逻辑层, 处理具体的业务逻辑.
@Repository:数据访问层,也称为持久层. 负责数据访问操作
@Configuration:配置层. 处理项⽬中的⼀些配置信息
程序的应⽤分层,调⽤流程如下:

3.3 ⽅法注解 @Bean

类注解是添加到某个类上的, 但是存在两个问题:
1. 使⽤外部包⾥的类, 没办法添加类注解
2. ⼀个类, 需要多个对象, ⽐如多个数据源

3.3.1 ⽅法注解要配合类注解使⽤

在 Spring 框架的设计中,⽅法注解 @Bean 要配合类注解才能将对象正常的存储到 Spring 容器中

1 @Component
2 public class BeanConfig {
3 @Bean
4 public User user(){
5 User user = new User();
6 user.setName("zhangsan");
7 user.setAge(18);
8 return user;
9 }
10 }
1 @SpringBootApplication
2 public class SpringIocDemoApplication {
3
4 public static void main(String[] args) {
5 //获取Spring上下⽂对象
6 ApplicationContext context = SpringApplication.run(SpringIocDemoApplicatio
7 //从Spring上下⽂中获取对象
8 User user = context.getBean(User.class);
9 //使⽤对象
10 System.out.println(user);
11 }
12 }

3.3.2 定义多个对象

对于同⼀个类, 如何定义多个对象呢?
⽐如多数据源的场景, 类是同⼀个, 但是配置不同, 指向不同的数据源
1 @Component
2 public class BeanConfig {
3 @Bean
4 public User user1(){
5 User user = new User();
6 user.setName("zhangsan");
7 user.setAge(18);
8 return user;
9 }
10
11 @Bean
12 public User user2(){
13 User user = new User();
14 user.setName("lisi");
15 user.setAge(19);
16 return user;
17 }
18 }
定义了多个对象的话, 我们根据类型获取对象, 获取的是哪个对象呢?
1 @SpringBootApplication
2 public class SpringIocDemoApplication {
3
4 public static void main(String[] args) {
5 //获取Spring上下⽂对象
6 ApplicationContext context = SpringApplication.run(SpringIocDemoApplicatio
7 //从Spring上下⽂中获取对象
8 User user = context.getBean(User.class);
9 //使⽤对象
10 System.out.println(user);
11 }
12 }

报错信息显⽰: 期望只有⼀个匹配, 结果发现了两个, user1, user2
从报错信息中, 可以看出来, @Bean 注解的bean, bean的名称就是它的⽅法名
接下来我们根据名称来获取bean对象
1 @SpringBootApplication
2 public class SpringIocDemoApplication {
3
4 public static void main(String[] args) {
5 //获取Spring上下⽂对象
6 ApplicationContext context = SpringApplication.run(SpringIocDemoApplicatio
7 //根据bean名称, 从Spring上下⽂中获取对象
8 User user1 = (User) context.getBean("user1");
9 User user2 = (User) context.getBean("user2");
10 System.out.println(user1);
11 System.out.println(user2);
12 }
13 }

结果:

可以看到, @Bean 可以针对同⼀个类, 定义多个对象.

3.3.3 重命名 Bean

可以通过设置 name 属性给 Bean 对象进⾏重命名操作
1 @Bean(name = {"u1","user1"})
2 public User user1(){
3 User user = new User();
4 user.setName("zhangsan");
5 user.setAge(18);
6 return user;
7 }
此时我们使⽤ u1 就可以获取到 User 对象了,如下代码所⽰:
1 @SpringBootApplication
2 public class SpringIocDemoApplication {
3
4 public static void main(String[] args) {
5 //获取Spring上下⽂对象
6 ApplicationContext context = SpringApplication.run(SpringIocDemoApplicatio
7 //从Spring上下⽂中获取对象
8 User u1 = (User) context.getBean("u1");
9 //使⽤对象
10 System.out.println(u1);
11 }
12 }
name={} 可以省略,如下代码所⽰:
1 @Bean({"u1","user1"})
2 public User user1(){
3 User user = new User();
4 user.setName("zhangsan");
5 user.setAge(18);
6 return user;
7 }
只有⼀个名称时, {}也可以省略, 如:
1 @Bean("u1")
2 public User user1(){
3 User user = new User();
4 user.setName("zhangsan");
5 user.setAge(18);
6 return user;
7 }

3.4 扫描路径

Q: 使⽤前⾯学习的四个注解声明的bean,⼀定会⽣效吗?
A: 不⼀定(原因:bean想要⽣效,还需要被Spring扫描)
下⾯我们通过修改项⽬⼯程的⽬录结构,来测试bean对象是否⽣效:
再运⾏代码:
1 @SpringBootApplication
2 public class SpringIocDemoApplication {
3
4 public static void main(String[] args) {
5 //获取Spring上下⽂对象
6 ApplicationContext context = SpringApplication.run(SpringIocDemoApplicatio
7 //从Spring上下⽂中获取对象
8 User u1 = (User) context.getBean("u1");
9 //使⽤对象
10 System.out.println(u1);
11 }
12 }

解释: 没有bean的名称为u1
为什么没有找到bean对象呢?
使⽤五⼤注解声明的bean,要想⽣效, 还需要配置扫描路径, 让Spring扫描到这些注解
也就是通过 @ComponentScan 来配置扫描路径.
那为什么前⾯没有配置 @ComponentScan注解也可以呢?
@ComponentScan 注解虽然没有显式配置,但是实际上已经包含在了启动类声明注解
@SpringBootApplication 中了
默认扫描的范围是SpringBoot启动类所在包及其⼦包
推荐作法
把启动类放在我们希望扫描的包的路径下, 这样我们定义的bean就都可以被扫描到

4. DI 详解

依赖注⼊是⼀个过程,是指IoC容器在创建Bean时, 去提供运⾏时所依赖的资源,⽽资源指的就是对象.,使⽤了 @Autowired 这个注解,完成了依赖注⼊的操作
关于依赖注⼊, Spring也给我们提供了三种⽅式:
1. 属性注⼊(Field Injection)
2. 构造⽅法注⼊(Constructor Injection)
3. Setter 注⼊(Setter Injection)

4.1 属性注⼊

将 Service 类注⼊到 Controller 类中.
Service 类的实现代码如下:
1 import org.springframework.stereotype.Service;
2
3 @Service
4 public class UserService {
5 public void sayHi() {
6 System.out.println("Hi,UserService");
7 }
8 }
Controller 类的实现代码如下:
1 @Controller
2 public class UserController {
3 //注⼊⽅法1: 属性注⼊
4 @Autowired
5 private UserService userService;
6
7 public void sayHi(){
8 System.out.println("hi,UserController...");
9 userService.sayHi();
10 }
11 }
获取 Controller 中的 sayHi⽅法:
1 @SpringBootApplication
2 public class SpringIocDemoApplication {
3
4 public static void main(String[] args) {
5 //获取Spring上下⽂对象
6 ApplicationContext context = SpringApplication.run(SpringIocDemoApplicatio
7 //从Spring上下⽂中获取对象
8 UserController userController = (UserController) context.getBean("userCont
9 //使⽤对象
10 userController.sayHi();
11 }
12 }

结果

4.2 构造⽅法注⼊

构造⽅法注⼊是在类的构造⽅法中实现注⼊,如下代码所⽰:
1 @Controller
2 public class UserController2 {
3 //注⼊⽅法2: 构造⽅法
4 private UserService userService;
5
6 @Autowired
7 public UserController2(UserService userService) {
8 this.userService = userService;
9 }
10
11 public void sayHi(){
12 System.out.println("hi,UserController2...");
13 userService.sayHi();
14 }
15 }
        注意事项:如果类只有⼀个构造⽅法,那么 @Autowired 注解可以省略;如果类中有多个构造⽅法, 那么需要添加上 @Autowired 来明确指定到底使⽤哪个构造⽅法

4.3 Setter 注⼊

Setter 注⼊和属性的 Setter ⽅法实现类似,只不过在设置 set ⽅法的时候需要加上 @Autowired 注
解 ,如下代码所⽰:
1 @Controller
2 public class UserController3 {
3 //注⼊⽅法3: Setter⽅法注⼊
4 private UserService userService;
5
6 @Autowired
7 public void setUserService(UserService userService) {
8 this.userService = userService;
9 }
10
11 public void sayHi(){
12 System.out.println("hi,UserController3...");
13 userService.sayHi();
14 }
15 }

4.4 三种注⼊优缺点分析

属性注⼊
优点: 简洁,使⽤⽅便;
缺点:
只能⽤于 IoC 容器,如果是⾮ IoC 容器不可⽤,并且只有在使⽤的时候才会出现 NPE(空指
针异常)
不能注⼊⼀个Final修饰的属性
构造函数注⼊(Spring 4.X推荐)
优点:
可以注⼊final修饰的属性
注⼊的对象不会被修改
依赖对象在使⽤前⼀定会被完全初始化,因为依赖是在类的构造⽅法中执⾏的,⽽构造⽅法
是在类加载阶段就会执⾏的⽅法.
通⽤性好, 构造⽅法是JDK⽀持的, 所以更换任何框架,他都是适⽤的
缺点:
注⼊多个对象时, 代码会⽐较繁琐
Setter注⼊(Spring 3.X推荐)
优点: ⽅便在类实例之后, 重新对该对象进⾏配置或者注⼊
缺点:
不能注⼊⼀个Final修饰的属性
注⼊对象可能会被改变, 因为setter⽅法可能会被多次调⽤, 就有被修改的⻛险

4.5 @Autowired存在问题

当同⼀类型存在多个bean时, 使⽤@Autowired会存在问题
1 @Component
2 public class BeanConfig {
3
4 @Bean("u1")
5 public User user1(){
6 User user = new User();
7 user.setName("zhangsan");
8 user.setAge(18);
9 return user;
10 }
11
12 @Bean
13 public User user2() {
14 User user = new User();
15 user.setName("lisi");
16 user.setAge(19);
17 return user;
18 }
19 }
1 @Controller
2 public class UserController {
3 
4 @Autowired
5 private UserService userService;
6 //注⼊user
7 @Autowired
8 private User user;
9
10 public void sayHi(){
11 System.out.println("hi,UserController...");
12 userService.sayHi();
13 System.out.println(user);
14 }
15 }

结果:

报错的原因是,⾮唯⼀的 Bean 对象(当容器中存在多个同一类型的 Bean 时,Spring 无法确定应该注入哪一个 Bean 到目标对象中)
如何解决上述问题呢?Spring提供了以下⼏种解决⽅案:
@Primary
@Qualifier
@Resource
使⽤@Primary注解:当存在多个相同类型的Bean注⼊时,加上@Primary注解,来确定默认的实现
1 @Component
2 public class BeanConfig {
3
4 @Primary //指定该bean为默认bean的实现
5 @Bean("u1")
6 public User user1(){
7 User user = new User();
8 user.setName("zhangsan");
9 user.setAge(18);
10 return user;
11 }
12
13 @Bean
14 public User user2() {
15 User user = new User();
16 user.setName("lisi");
17 user.setAge(19);
18 return user;
19 }
20 }
使⽤@Qualifier注解:指定当前要注⼊的bean对象。 在@Qualifier的value属性中,指定注⼊的bean 的名称。
@Qualifier注解不能单独使⽤,必须配合@Autowired使⽤
1 @Controller
2 public class UserController {
3 @Qualifier("user2") //指定bean名称
4 @Autowired
5 private User user;
6
7 public void sayHi(){
8 System.out.println("hi,UserController...");
9 System.out.println(user);
10 }
11 }
使⽤@Resource注解:是按照bean的名称进⾏注⼊。通过name属性指定要注⼊的bean的名称。
1 @Controller
2 public class UserController {
3 @Resource(name = "user2")
4 private User user;
5
6 public void sayHi(){
7 System.out.println("hi,UserController...");
8 System.out.println(user);
9 }
10 }

  • 12
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
完整全套资源下载地址:https://download.csdn.net/download/qq_27595745/70761177 【完整课程列表】 完整版Java web开发教程PPT课件 Java开发进阶教程 第01章 JavaScript简介以及基本语法(共15页).pptx 完整版Java web开发教程PPT课件 Java开发进阶教程 第02章 Dom模型,控制客户端元素(共15页).pptx 完整版Java web开发教程PPT课件 Java开发进阶教程 第03章 表单验证,常用函数(共15页).pptx 完整版Java web开发教程PPT课件 Java开发进阶教程 第04章 自定义web服务器(共14页).pptx 完整版Java web开发教程PPT课件 Java开发进阶教程 第06章 SERVLET(共15页).pptx 完整版Java web开发教程PPT课件 Java开发进阶教程 第07章 JSP语法及运行过程(共13页).pptx 完整版Java web开发教程PPT课件 Java开发进阶教程 第08章 JSP内置对象(共22页).pptx 完整版Java web开发教程PPT课件 Java开发进阶教程 第09章 jstl、el、java bean(共18页).pptx 完整版Java web开发教程PPT课件 Java开发进阶教程 第10章 过滤器、监听器、自定义标签(共19页).pptx 完整版Java web开发教程PPT课件 Java开发进阶教程 第11章 AJAX实现(共11页).pptx 完整版Java web开发教程PPT课件 Java开发进阶教程 第12章 自定义mvc框架(共11页).pptx 完整版Java web开发教程PPT课件 Java开发进阶教程 第13章 spring ioc aop(共18页).pptx 完整版Java web开发教程PPT课件 Java开发进阶教程 第14章 spring mvc介绍,原理以及搭建(共15页).pptx 完整版Java web开发教程PPT课件 Java开发进阶教程 第15章 spring mvc核心对象拦截器(共26页).pptx 完整版Java web开发教程PPT课件 Java开发进阶教程 第17章 自定义orm框架(共11页).pptx 完整版Java web开发教程PPT课件 Java开发进阶教程 第18章 mybatis框架的搭建以及应用(共13页).pptx 完整版Java web开发教程PPT课件 Java开发进阶教程 第19章 mybatis高级应用(共21页).pptx 完整版Java web开发教程PPT课件 Java开发进阶教程 第20章 数据库连接池,缓存(共15页).pptx 完整版Java web开发教程PPT课件 Java开发进阶教程 第22章 常用框架的介绍以及环境搭建(共16页).pptx JS课程案例ebookHTML\网上书店需求文档.doc

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值