当前位置: 首页 > news >正文

Spring IOCDI————(2)

DI详解

我们之前讲了控制反转IOC,也就是bean的存,那么我们还需要Bean的取,就是DI了,DI翻译过来就是依赖注入,啥意思呢,就是我们通过IOC容器,把所有的对象交给Spring管理,我们指定哪个对象使用哪个类,就给他注入哪个类,这个类就能直接使用我们给他注入的类;

1,属性注入

第一种方法,使用@Autowired注解;

先创建一个功能类,交给Spring进行管理,


@Service
public class UserService {public void sayHello(){System.out.println("Hello,sayHello");}
}

再创建控制器,也交给Spring管理,把UserService注入到UserController中, 

@Controller
public class UserController {@Autowiredpublic UserService userService;public void SayHello(){System.out.println("Hello,UserController");userService.sayHello();}
}

 获取上下文对象,通过上下文获取UserController对象,我们直接调用UserController的SayHello方法,看看效果;

@SpringBootApplication
public class JavaTest2025521Application {public static void main(String[] args) {ApplicationContext context = SpringApplication.run(JavaTest2025521Application.class, args);UserController userController = context.getBean("userController", UserController.class);userController.SayHello();}
}

证明,UserService对象被Spring自动创建出来了;


2,构造方法注入

@Controller
public class UserController2 {private UserService userService;@Autowiredpublic UserController2(UserService userService){this.userService = userService;}public void SayHello(){System.out.println("Hello,Controller2");userService.sayHello();}
}

我们直接在构造方法上写上注解@Autoweired,就可以了,

        UserController2 userController2 = context.getBean("userController2", UserController2.class);userController2.SayHello();

也是可以的,那么如果有两个构造方法呢?

    @Autowiredpublic UserController2(UserService userService){this.userService = userService;}@Autowiredpublic UserController2(){}

 这段代码直接标红红嗷,我们想使用哪个构造方法,就得在哪个构造方法上标记@Autowired注解,

@Controller
public class UserController2 {private UserService userService;@Autowiredpublic UserController2(UserService userService){this.userService = userService;}public UserController2(){}public void SayHello(){System.out.println("Hello,Controller2");userService.sayHello();}
}

这样还是可以正常传参的,

那么如果有参数呢,Spring会找这个类型的Bean来给他赋值,比如参数需要String,它就会去找Bean下的类型Sting给他赋值,我们看我们这个代码:
 


@Controller
public class UserController3 {private UserService userService;@Autowiredpublic UserController3(UserService userService){this.userService = userService;}public void SayHello(){System.out.println("Hello,Controller3");userService.sayHello();System.out.println(userService.getName());}
}

现在有三个Spring管理的UserService对象,

@Configuration
public class UserSer {@Beanpublic UserService name1(){UserService userService = new UserService();userService.setName("zhangsan");return userService;}@Beanpublic UserService name2(){UserService userService1 = new UserService();userService1.setName("lisi");return userService1;}
}

@Service
@Data
public class UserService {private String name;public void sayHello(){System.out.println("Hello,sayHello");}
}

 那我们前面这个构造方法使用的是哪个对象呢,

        UserController3 userController3 = context.getBean("userController3", UserController3.class);userController3.SayHello();

我们这样直接指定的会就是通过Service注解生成的默认的, 

打印为null啊,我们试试修改getBean的名称

        UserController3 userController4 = context.getBean("name1", UserController3.class);userController4.SayHello();

 得到了,这就是我们之前讲Bean时使用的方法,我们说过还有别的办法就是@Qualifier注解,

@Controller
public class UserController3 {private UserService userService;@Autowiredpublic UserController3(@Qualifier("name2") UserService userService){this.userService = userService;}public void SayHello(){System.out.println("Hello,Controller3");userService.sayHello();System.out.println(userService.getName());}
}

类似参数绑定,用@Qualifier指定name2注解,这样getbean都不用指定String名字了;

        UserController3 userController5 = context.getBean(UserController3.class);userController5.SayHello();System.out.println();

另外啊,这只是获取UserController对象,如果获取的是UserService那么就又不对了,我们直接有三个类型,UserService,name1,name2,这可不是根据构造方法了,Spring想直接得到,那么我们需要加@primary注解才行,


3,Setter注入

这个跟属性的那个Set基本是一样的,

@Controller
public class UserController4 {private UserService userService;@Autowiredpublic void Set(UserService userService){this.userService = userService;}public void SayHello(){System.out.println("Hello,Controller4");userService.sayHello();}}
        UserController4 userController6 = context.getBean(UserController4.class);userController6.SayHello();

 setter方法还是很简单的,没有什么特别要说的;

(5-21忘了就过一遍代码)


4,三种注入优缺点分析

 

 


5,@Autowired存在问题

当同一个类型出现多个Bean就会出现问题,来上代码:
先来一个User类:
 

@Repository
@Data
public class User {private String name;private Integer age;
}

这里就自己创建了一个类,这个@Repository可以不加 

交给Spring管理,再来lombok,

@Configuration
public class UserConfig {@Beanpublic User get1(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;}@Beanpublic User get2(){User user = new User();user.setName("lisi");user.setAge(20);return user;}
}

在来一个类里面可以得到User类,并且有两个方法可以得到,两个Bean,


@Controller
public class UserControl {@Autowiredprivate User user;public void sayHello(User user){System.out.println(user.getAge()+"    "+user.getName());}
}

来控制器类,现在我不说了,现在有几个重复的Bean呢,

User user = context.getBean(User.class);System.out.println(user);

运行试试:

有三个 ,我们怎么解决这个问题呢,我们有三种办法

1,@Primary

使用该注解直接标注到Bean上面:

    @Primary@Beanpublic User get1(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;}
        User user = context.getBean(User.class);System.out.println(user);

 

    @Primary@Beanpublic User get2(){User user = new User();user.setName("lisi");user.setAge(20);return user;}

 

2,@Qualifier

必须搭配合@Autowired使用,指定要注入的对象是哪个:

这里指的是指定注入哪个,然后在被注入的对象中用被注入的对象,而刚才那个@primary,是直接指定这个类型就用这个被指定的了

我们来看代码:


@Configuration
public class UserConfig2 {@Beanpublic User get1(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;}@Beanpublic User get2(){User user = new User();user.setName("lisi");user.setAge(20);return user;}
}
@Controller
public class UserControl2 {@Qualifier("get1")@Autowiredprivate User user;public void sayHello(){System.out.println(user.getAge()+"    "+user.getName());}
}
        UserControl2 userControl2 = context.getBean(UserControl2.class);userControl2.sayHello();System.out.println();

 

来个总结嗷,怕大家混了:

我们刚开始创建一个对象,比如刚才的User我们交给Spring就代表了有一个User类了,Spring已经自己创建一个了;

1,属性注入就是我们在写一个A类的时候如果想用User类,就直接使用 @Autowired注解,我们在获取上下文对象的时候可以获取A类,调用A类的方法,如果有User相关的,就能调用到;但是如果接收的是User对象的话就不行了,即使A类注入了,如果成功了的话就是因为User交给Spring管理了,就是

@Repository
@Data
public class User {private String name;private Integer age;
}

如果属性注入同一类型出现了多个Bean呢,我们就可以使用@Primary来标记Bean,表示这写类型的Bean就使用标记的这个就行,可以直接获取到,或者包含它的类获取到,

@Configuration
public class UserConfig {@Beanpublic User get1(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;}@Primary@Beanpublic User get2(){User user = new User();user.setName("lisi");user.setAge(20);return user;}
}
;
@Controller
public class UserControl {@Autowiredprivate User user;public void sayHello(){System.out.println(user.getAge()+"    "+user.getName());}
}
User user = context.getBean(User.class);
System.out.println(user);
UserControl userControl = context.getBean(UserControl.class);
userControl.sayHello();

这个就可以用User接收,也可以使用注入过的User的类来调用,都是可以的,

还有就是刚才的@Autowired,是指定被注入的类,去使用Spring中的哪个User类的,

@Qualifier("get1")
@Autowired
private User user;

直接接收User类是做不到的,只能让被注入的那个类调用;

还有就是构造方法注入要注意,有多个构造方法要用@Autowired来制定,参数有多个类型也要使用@Qualifier()来绑定;

3,@Resource

按照Bean的名称注入@Resource(name = "user2")通过那么来指定要注入的;

@Configuration
public class UserConfig3 {@Beanpublic User get1(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;}@Beanpublic User get2(){User user = new User();user.setName("lisi");user.setAge(20);return user;}
}
@Controller
public class UserControl3 {@Resource(name = "get1")@Autowiredprivate User user;public void sayHello(){System.out.println(user.getAge()+"    "+user.getName());}
}
        User user = context.getBean(User.class);System.out.println(user);

 直接获取还是不行的,

 

        UserControl3 userControl3 = context.getBean(UserControl3.class);userControl3.sayHello();

 


@Autowired和Resource的区别

1,@Autowired是spring框架提供的注解,⽽@Resource是JDK提供的注解

2,@Autowired默认是按照类型注⼊,⽽@Resource是按照名称注⼊.相⽐于@Autowired 来说, @Resource ⽀持更多的参数设置,例如name设置,根据名称获取Bean

相关文章:

  • 如何提灯验车
  • Android13 wifi设置国家码详解
  • 全球机电气缸市场深度洞察:技术驱动与产业升级下的增长机遇(2025-2031)
  • 面试相关的知识点
  • mmaction2——tools文件夹下
  • 从零基础到最佳实践:Vue.js 系列(4/10):《Vue Router 路由管理:深入探索与实战应用》
  • 深入浅出理解时间复杂度和空间复杂度
  • 学习黑客了解密码学
  • UML 活动图 (Activity Diagram) 使用案例
  • 【Java高阶面经:微服务篇】8.高可用全链路治理:第三方接口不稳定的全场景解决方案
  • 【C++】模板下(泛型编程)
  • java面试每日一背 day1
  • 深入解析应用程序分层及 BaseDao 的封装策略
  • 操作系统 第四章 -2
  • 2025上半年软考准考证打印入口已开放!
  • 黑色矩形大于6识别
  • 编程技能:字符串函数09,strncmp
  • Base64加密解密
  • C++:array容器
  • 十七、面向对象底层逻辑-MessageSource接口设计
  • 砀山网站建设/二级域名查询入口
  • 东莞保安公司有哪些/优化设计三年级上册答案
  • java做网站的权限管理/网站流量排行
  • 营销型网站设计文章/seo课程培训机构