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​​​​​​​

猜你喜欢

转载自blog.csdn.net/weixin_72953218/article/details/134754199
今日推荐