SpringIOC第二课,@Bean用法,DI详解,常见面试题Autowired VS Resource

简介: SpringIOC第二课,@Bean用法,DI详解,常见面试题Autowired VS Resource

一、回顾

但是我们之前MVC时候,在页面上,为什只用Controller,不用其他的呢?

用其他的好使吗?(我们可以在这里看到,出现404的字样)


@Service
@ResponseBody
public class TestController {
    @RequestMapping("/test")
    public String test(){
        return "测试Controller和其他注解的区别";
    }
}

但是Controller就是好使的,事实上Spring对Controller有更屌的权限

二、@Bean用法

五大注解只能加在类上,并且只能加在自己的代码上

如果我引入一个第三方的jar包,也希望交给Spring管理,是没有办法加五大注解

第一个应用场景:可以使用@Bean, @Bean是方法注解

在这里,我们可以看到一个问题,就是两个引用指向的是一个对象(看后面的那几位,说明地址相同)

第二个应用场景:那么假如说要求是一个类,定义多个对象,比如说数据库操作,定义多个数据源使用@Bean

@Bean相当于是一个上交作业的过程,交完了作业,要告诉老师,交完作业了

所以也就是说@Bean要搭配五大注解来使用并且当一个类型存在多个bean中,采用多个Bean的时候,我们就不能使用类型来获取对象了。

我们上节课学的注释

是getBean+方法名(小驼峰形式,特殊情况(两个首字母都是大写,那么她就会变成小写)

@Bean需要加的是方法名(方法名不遵守小驼峰形式)

如何进行相应的传递参数

那么我们在应用中,一般不会让写死

假如对Bean的方法中的内容进行传参数,则定义一个这种方法,当然现在这个也是死的,但是以后可以用这种方法变成“活的”

@Configuration
public class BeanConfig {
    @Bean
    public String name(){
        return "zhangsan";
    }
    @Bean
    public UserInfo UserInfo(String string){
        UserInfo userInfo=new UserInfo();
 
        userInfo.setName(string);
        return  userInfo;
    }

Spring的扫描文件约定

SpringBoot是属于我们的开发框架(其实叫做开发框架,更感觉像是打开idea,后呈现的这个结构)

SpringBoot特点:约定大于配置,约定到,放到哪里就扫描当前文件夹里面的所有文件,但是假如说你硬是想在一个小的目录里面去执行(也有方法,加路径)(约定的体现之一扫描路径,默认的扫描路径是:启动类所在的目录及其子孙目录)

解决方式就是

//默认扫描当前类的目录及子目录

在前面加上这个注解(路径自己填)@ComponentScan("com.example")

@ComponentScan("com.example")
@SpringBootApplication
public class IoCtryApplication {
 
    public static void main(String[] args) {
        //启动类是帮助我们启动spring,这个命令可以返回一个spring

DI详解

DI依赖注入,属性装配“依赖装配”,

只要加上这些依赖注入(就跟我们导包一样,没导包不能用)

1.属性注入 @Autowired

(相当于导游,带着去找这个东西)和上面那个匹配的一致,和那个@Bean传递参数一样。

@Controller
public class UserController {
//⚠️假如没有下面的这个Autowired注释,那么就会报空指针异常
@Autowired
private UserService userService;
 
public void prin(){
    userService.doService();
    System.out.println("春节快乐");
}
}
UserController userController=context.getBean(UserController.class);
        userController.prin();

2.构造方法注入

如下图

 
@Controller
public class UserController {
//@Autowired
private UserService userService;
    private UserInfo userInfo;
//⚠️注意此时加完构造函数之后,还要把无参数的也写一遍,因为无参数的构造函数,有很多东西在用,所以一旦经过修改,就会让使用无参数的报错。
 
public UserController(){
}
@Autowired
public  UserController(UserService userService){
    this.userService=userService;
}
 
    public  UserController(UserInfo userInfo,UserService userService){
        this.userService=userService;
        this.userInfo=userInfo;
    }
public void prin(){
    userService.doService();
    System.out.println("春节快乐");
}

3.Setter方法注入

三种注入的优缺点

1.属性注入:

优点:简洁方便

缺点:只能用于IOC容器,如果非IOC容器无法使用,并且只有在使用的时候才会出现NPE(空指针异常),并且不能修饰Final。

2.构造函数注入:

优点:

(1).可以注入final属性(通过构造方法的形式)。

(2).注入的对象不会被修改(因为除非你再new,不然构造方法不能被再次调用),依赖对象使用之前一定会被初始化,因为依赖在类的构造方法中执行的,构造方法是类加载阶段就会执行的方法

(3).通用型好:构造方法是JDK支持的

缺点:

代码会比较繁琐

Setter注入

优点:方便类实例化之后,重新对该对象进行配置或者注入

缺点:不能修饰Final,注入的对象肯会被改变,因为setter方法可能会被多次调用,就有被修改的风险。

当程序同一个类型,多个对象时候,使用@AutoWired会报错

这里说的情况是这样的一个代码

package com.example.IOCtry;
 
import com.example.IOCtry.config.UserInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
 
@Controller
public class UserController {
@Autowired                //⚠️
private UserService userService;
@Autowired                //⚠️
private UserInfo userInfo;
//注意此时加完构造函数之后,还要把无参数的也写一遍,因为无参数的构造函数,有很多东西在用,所以一旦经过修改,就会让使用无参数的报错。
 
//public UserController(){
//}
//
//public  UserController(UserService userService){
//    this.userService=userService;
//}
//
//    public  UserController(UserInfo userInfo,UserService userService){
//        this.userService=userService;
//        this.userInfo=userInfo;
//    }
//   @Autowired
//    public  void setUserController(UserService userService){
//        this.userService=userService;
//    }
public void prin(){
    userService.doService();
    System.out.println(userInfo);
    System.out.println("春节快乐");
}
}

改法一需要改属性名字:让属性名和方法名字一致

package com.example.IOCtry;
 
import com.example.IOCtry.config.UserInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
 
@Controller
public class UserController {
@Autowired
private UserService userService;
@Autowired
private UserInfo UserInfo1;       //⚠️这个名字改成和方法名字一摸一样
//注意此时加完构造函数之后,还要把无参数的也写一遍,因为无参数的构造函数,有很多东西在用,所以一旦经过修改,就会让使用无参数的报错。
 
//public UserController(){
//}
//
//public  UserController(UserService userService){
//    this.userService=userService;
//}
//
//    public  UserController(UserInfo userInfo,UserService userService){
//        this.userService=userService;
//        this.userInfo=userInfo;
//    }
//   @Autowired
//    public  void setUserController(UserService userService){
//        this.userService=userService;
//    }
public void prin(){
    userService.doService();
    System.out.println(UserInfo1);
    System.out.println("春节快乐");
}
}

不想改名的第二种方法:加上@Primary

//这个是在另一个类中搞的方法
package com.example.IOCtry.config;
 
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
 
@Configuration
public class BeanConfig {
    @Bean
    public String name(){
        return "zhangsan";
    }
    @Bean
    public String name2(){
        return "wangwu";
    }
 
   // ⚠️@Primary这个只有加上,程序才会不发生错误,会执行这个Setter方法
    @Bean
    public UserInfo UserInfo1(String name2){
        UserInfo userInfo=new UserInfo();
        userInfo.setName(name2);
        return  userInfo;
    }
    @Bean
    public UserInfo userInfo2(){
        UserInfo userInfo=new UserInfo();
        userInfo.setId(2);
        userInfo.setAge(22);
        userInfo.setName("lclyr");
        return  userInfo;
    }
 
}

改法3(优先):使用@Qualifier

package com.example.IOCtry;
 
import com.example.IOCtry.config.UserInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
 
@Controller
public class UserController {
@Autowired
private UserService userService;
@Qualifier("userInfo2")            //⚠️
@Autowired
private UserInfo userInfo;
//注意此时加完构造函数之后,还要把无参数的也写一遍,因为无参数的构造函数,有很多东西在用,所以一旦经过修改,就会让使用无参数的报错。
 
//public UserController(){
//}
//
//public  UserController(UserService userService){
//    this.userService=userService;
//}
//
//    public  UserController(UserInfo userInfo,UserService userService){
//        this.userService=userService;
//        this.userInfo=userInfo;
//    }
//   @Autowired
//    public  void setUserController(UserService userService){
//        this.userService=userService;
//    }
public void prin(){
    userService.doService();
    System.out.println(userInfo);
    System.out.println("春节快乐");
}
}

改法4(优先):使用@Resource(name="userInfo2")

package com.example.IOCtry;
 
import com.example.IOCtry.config.UserInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
 
import javax.annotation.Resource;
 
@Controller
public class UserController {
@Autowired
private UserService userService;
//@Qualifier("userInfo2")
    @Resource(name="userInfo2")
@Autowired
private UserInfo userInfo;
//注意此时加完构造函数之后,还要把无参数的也写一遍,因为无参数的构造函数,有很多东西在用,所以一旦经过修改,就会让使用无参数的报错。
 
//public UserController(){
//}
//
//public  UserController(UserService userService){
//    this.userService=userService;
//}
//
//    public  UserController(UserInfo userInfo,UserService userService){
//        this.userService=userService;
//        this.userInfo=userInfo;
//    }
//   @Autowired
//    public  void setUserController(UserService userService){
//        this.userService=userService;
//    }
public void prin(){
    userService.doService();
    System.out.println(userInfo);
    System.out.println("春节快乐");
}
}

三、常见面试题Autowired VS  Resource

@Autowired:是Spring开发的框架,@Resource是JDK提供的框架

@Autowired:默认是按照类型来去注入,假如说同一个类型存在多个对象,那么就按名称匹配,假如名称匹配不上,那么就会报错,相对于Autowired来说,@Resource支持更多的参数设置,如name设置,根据名称获取Bean


相关文章
|
存储 缓存 Java
每日一道面试题之LinkedList VS ArrayList~
每日一道面试题之LinkedList VS ArrayList~
|
3月前
|
Java 编译器 开发工具
JDK vs JRE:面试大揭秘,一文让你彻底解锁Java开发和运行的秘密!
【8月更文挑战第24天】JDK(Java Development Kit)与JRE(Java Runtime Environment)是Java环境中两个核心概念。JDK作为开发工具包,不仅包含JRE,还提供编译器等开发工具,支持Java程序的开发与编译;而JRE仅包含运行Java程序所需的组件如JVM和核心类库。一个简单的"Hello, World!"示例展示了两者用途:需借助JDK编译程序,再利用JRE或JDK中的运行环境执行。因此,开发者应基于实际需求选择安装JDK或JRE。
55 0
|
3月前
|
前端开发 应用服务中间件 API
"揭秘!面试官必问:你是如何巧妙绕过跨域难题的?前端代理VS服务器端CORS,哪个才是你的秘密武器?"
【8月更文挑战第21天】在软件开发中,尤其前后端分离架构下,跨域资源共享(CORS)是常见的挑战。主要解决方案有两种:一是服务器端配置CORS策略,通过设置响应头控制跨域访问权限,无需改动前端代码,增强安全性;二是前端代理转发,如使用Nginx或Webpack DevServer在开发环境中转发请求绕过同源策略,简化开发流程但不适用于生产环境。生产环境下应采用服务器端CORS策略以确保安全稳定。
50 0
|
6月前
|
存储 算法 关系型数据库
【面试普通人VS高手系列】b树和b+树的理解
【面试普通人VS高手系列】b树和b+树的理解
|
Cloud Native 程序员 Go
硬技能VS软技能:面试中哪个更重要?
硬技能VS软技能:面试中哪个更重要?
139 0
|
开发框架 Java Spring
【Java面试】Spring中Autowired和Resource关键字的区别
【Java面试】Spring中Autowired和Resource关键字的区别
110 0
面试基础篇——ArrayList VS LinkedList
面试基础篇——ArrayList VS LinkedList
84 0
面试基础篇——ArrayList VS LinkedList
|
C++
程序人生 - 平时的你 VS 面试的你
程序人生 - 平时的你 VS 面试的你
80 0
程序人生 - 平时的你 VS 面试的你
|
JavaScript C++
【面试题】debounce vs throttle
debounce 和 throttle 是面试时经常会被问到的一道 JS 题。我自己在第一次找工作的时候,就被问过。当时被问得半天说不出两者的区别,说着说着就把自己带入坑了。 今天就跟大家分享一下这两者的区别吧。
【面试题】debounce vs throttle
|
存储 消息中间件 NoSQL
面试必问的 Redis:Memcached VS Redis
老态龙钟的Memcached 似乎已经无力阻挡 Redis 一统江湖了,但是在面试中,关于两者的比较还是频频出现,因此有必要了解下两者的区别。
172 0