首页IT科技Spring依赖注入的方式有哪些(Spring的配置、依赖注入、Bean的自动装配及注解开发)

Spring依赖注入的方式有哪些(Spring的配置、依赖注入、Bean的自动装配及注解开发)

时间2025-06-19 06:31:36分类IT科技浏览4831
导读:Spring配置...

Spring配置

1. 别名

alias 设置别名 , 为bean设置别名 , 可以设置多个别名

2. Bean的配置

<!--bean就是java对象,由Spring创建和管理--> <!-- id 是bean的标识符,要唯一,如果没有配置id,name就是默认标识符 如果配置id,又配置了name,那么name是别名 name可以设置多个别名,可以用逗号,分号,空格隔开 如果不配置id和name,可以根据applicationContext.getBean(.class)获取对象; class是bean的全限定名=包名+类名 --> <bean id="hello" name="hello2 h2,h3;h4" class="com.kuang.pojo.Hello"> <property name="name" value="Spring"/> </bean>

3. import

团队的合作通过import来实现 .

<import resource="{path}/beans.xml"/>

依赖注入(DI)

依赖注入(Dependency Injection,DI)            。 依赖 : 指Bean对象的创建依赖于容器 . Bean对象的依赖资源 . 注入 : 指Bean对象所依赖的资源 , 由容器来设置和装配 .

1 构造器注入

在上一篇博客已经详细讲过了

2 set注入 (重点)

要求被注入的属性 , 必须有set方法 , set方法的方法名由set + 属性首字母大写 , 如果属性是boolean类型 , 没有set方法 , 是 is .

测试pojo类 :

Address.java

public class Address {   private String address;   public String getAddress() {     return address;   }   public void setAddress(String address) {     this.address = address;   } }

Student.java

package com.hang.pojo; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; public class Student {   private String name;   private Address address;   private String[] books;   private List<String> hobbys;   private Map<String,String> card;   private Set<String> games;   private String wife;   private Properties info;   public void setName(String name) {     this.name = name;   }   public void setAddress(Address address) {     this.address = address;   }   public void setBooks(String[] books) {     this.books = books;   }   public void setHobbys(List<String> hobbys) {     this.hobbys = hobbys;   }   public void setCard(Map<String, String> card) {     this.card = card;   }   public void setGames(Set<String> games) {     this.games = games;   }   public void setWife(String wife) {     this.wife = wife;   }   public void setInfo(Properties info) {     this.info = info;   }   public void show(){     System.out.println("name="+ name       + ",address="+ address.getAddress()       + ",books="     );     for (String book:books){       System.out.print("<<"+book+">>\t");     }     System.out.println("\n爱好:"+hobbys);     System.out.println("card:"+card);     System.out.println("games:"+games);     System.out.println("wife:"+wife);     System.out.println("info:"+info);   } }

2            、1 常量注入

<bean id="student" class="com.kuang.pojo.Student"> <property name="name" value="小明"/> </bean>

测试:

@Test public void test01(){   ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");   Student student = (Student) context.getBean("student");   System.out.println(student.getName()); }

2                   、2 Bean注入

注意点:这里的值是一个引用             ,ref

<bean id="addr" class="com.kuang.pojo.Address">   <property name="address" value="重庆"/> </bean> <bean id="student" class="com.kuang.pojo.Student">   <property name="name" value="小明"/>   <property name="address" ref="addr"/> </bean>

2      、3 数组注入

<bean id="student" class="com.kuang.pojo.Student">   <property name="name" value="小明"/>   <property name="address" ref="addr"/>   <property name="books">     <array>       <value>西游记</value>       <value>红楼梦</value>       <value>水浒传</value>     </array>   </property> </bean>

2         、4 List注入

<property name="hobbys">   <list>     <value>听歌</value>     <value>看电影</value>     <value>爬山</value>   </list> </property>

2                   、5 Map注入

<property name="card">   <map>     <entry key="中国邮政" value="456456456465456"/>     <entry key="建设" value="1456682255511"/>   </map> </property>

2          、6 set注入

<property name="games">   <set>     <value>LOL</value>     <value>BOB</value>     <value>COC</value>   </set> </property>

2      、7 Null注入

<property name="wife"><null/></property>

2                  、8 Properties注入

<property name="info">   <props>     <prop key="学号">20190604</prop>     <prop key="性别"></prop>     <prop key="姓名">小明</prop>   </props> </property>

测试结果:

3 拓展注入实现

User.java : 【注意:这里没有有参构造器!】

public class User {   private String name;   private int age;   public void setName(String name) {     this.name = name;   }   public void setAge(int age) {     this.age = age;   }   @Override   public String toString() {     return "User{" +       "name=" + name + \ +       ", age=" + age +       };   } }

1             、P命名空间注入 : 需要在头文件中假如约束文件

导入约束 : xmlns:p="http://www.springframework.org/schema/p" <!--P(属性: properties)命名空间 , 属性依然要设置set方法--> <bean id="user" class="com.kuang.pojo.User" p:name="腹白" p:age="18"/>

2   、c 命名空间注入 : 需要在头文件中假如约束文件

导入约束 : xmlns:c="http://www.springframework.org/schema/c" <!--C(构造: Constructor)命名空间 , 属性依然要设置set方法--> <bean id="user" class="com.kuang.pojo.User" c:name="腹白" c:age="18"/>

发现问题:爆红了                  ,刚才我们没有写有参构造!

解决:把有参构造器加上      ,这里也能知道          ,c 就是所谓的构造器注入!

测试代码:

@Test public void test02(){   ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");   User user = (User) context.getBean("user");   System.out.println(user); }

4 Bean的作用域

在Spring中                   ,那些组成应用程序的主体及由Spring IoC容器所管理的对象         ,被称之为bean                   。简单地讲      , bean就是由IoC容器初始化                  、装配及管理的对象 .

几种作用域中                   ,request                、session作用域仅在基于web的应用中使用(不必关心你所采用的是什么web 应用框架)            ,只能用在基于web的Spring ApplicationContext环境      。

4.1 Singleton

当一个bean的作用域为Singleton   ,那么Spring IoC容器中只会存在一个共享的bean实例                   ,并且所有对 bean的请求               ,只要id与该bean定义相匹配,则只会返回bean的同一实例         。Singleton是单例类型                ,就是 在创建起容器时就同时自动创建了一个bean的对象                  ,不管你是否使用   ,他都存在了             ,每次获取到的对象 都是同一个对象                   。注意                  ,Singleton作用域是Spring中的缺省作用域          。要在XML中将bean定义成 singleton      ,可以这样配置:

<bean id="ServiceImpl" class="cn.csdn.service.ServiceImpl" scope="singleton">

测试:

@Test public void test03(){   ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");   User user = (User) context.getBean("user");   User user2 = (User) context.getBean("user");   System.out.println(user==user2); }

4.2 Prototype

当一个bean的作用域为Prototype          ,表示一个bean定义对应多个对象实例      。Prototype作用域的bean会 导致在每次对该bean请求(将其注入到另一个bean中                   ,或者以程序的方式调用容器的getBean()方法) 时都会创建一个新的bean实例                  。Prototype是原型类型         ,它在我们创建容器的时候并没有实例化      ,而是 当我们获取bean的时候才会去创建一个对象                   ,而且我们每次获取到的对象都不是同一个对象             。根据经 验            ,对有状态的bean应该使用prototype作用域   ,而对无状态的bean则应该使用singleton作用域   。在 XML中将bean定义成prototype                   ,可以这样配置:

<bean id="account" class="com.foo.DefaultAccount" scope="prototype"/> 或者 <bean id="account" class="com.foo.DefaultAccount" singleton="false"/>

4.3 Request

当一个bean的作用域为Request               ,表示在一次HTTP请求中,一个bean定义对应一个实例;即每个HTTP 请求都会有各自的bean实例                ,它们依据某个bean定义创建而成                  。该作用域仅在基于web的Spring ApplicationContext情形下有效                。考虑下面bean定义:

<bean id="loginAction" class=cn.csdn.LoginAction" scope="request"/>

针对每次HTTP请求                  ,Spring容器会根据loginAction bean的定义创建一个全新的LoginAction bean实 例   ,且该loginAction bean实例仅在当前HTTP request内有效             ,因此可以根据需要放心的更改所建实例 的内部状态                  ,而其他请求中根据loginAction bean定义创建的实例      ,将不会看到这些特定于某个请求的 状态变化。当处理请求结束          ,request作用域的bean实例将被销毁               。

4.4 Session

当一个bean的作用域为Session                   ,表示在一个HTTP Session中         ,一个bean定义对应一个实例                   。该作用域 仅在基于web的Spring ApplicationContext情形下有效   。考虑下面bean定义:

<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>

针对某个HTTP Session      ,Spring容器会根据userPreferences bean定义创建一个全新的 userPreferences bean实例                   ,且该userPreferences bean仅在当前HTTP Session内有效            。与request作 用域一样            ,可以根据需要放心的更改所创建实例的内部状态   ,而别的HTTP Session中根据 userPreferences创建的实例                   ,将不会看到这些特定于某个HTTP Session的状态变化                   。当HTTP Session 最终被废弃的时候               ,在该HTTP Session作用域内的bean也会被废弃掉      。

Bean的自动装配

自动装配是使用spring满足bean依赖的一种方法 spring会在应用上下文中为某个bean寻找其依赖的bean         。

Spring中bean有三种装配机制,分别是:

在xml中显式配置; 在java中显式配置; 隐式的bean发现机制和自动装配                   。

这里我们主要讲第三种:自动化的装配bean          。

Spring的自动装配需要从两个角度来实现                ,或者说是两个操作:

组件扫描(component scanning):spring会自动发现应用上下文中所创建的bean; 自动装配(autowiring):spring自动满足bean之间的依赖                  ,也就是我们说的IoC/DI;

组件扫描和自动装配组合发挥巨大威力   ,使的显示的配置降低到最少      。

推荐不使用自动装配xml配置 , 而使用注解 .

1、测试环境搭建

1. 新建一个项目

2. 新建两个实体类             ,Cat Dog 都有一个叫的方法

public class Cat {   public void shout() {     System.out.println("miao~");   } }
public class Dog {   public void shout() {     System.out.println("wang~");   } }

3. 新建一个用户类 User

public class User {   private Cat cat;   private Dog dog;   private String str; }

4. 编写Spring配置文件

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     xsi:schemaLocation="http://www.springframework.org/schema/beans       http://www.springframework.org/schema/beans/spring-beans.xsd">   <bean id="dog" class="com.kuang.pojo.Dog"/>   <bean id="cat" class="com.kuang.pojo.Cat"/>   <bean id="user" class="com.kuang.pojo.User">     <property name="cat" ref="cat"/>     <property name="dog" ref="dog"/>     <property name="str" value="qinjiang"/>   </bean> </beans>

5. 测试

public class MyTest {   @Test   public void testMethodAutowire() {     ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");     User user = (User) context.getBean("user");     user.getCat().shout();     user.getDog().shout();   } }

结果正常输出                  ,环境OK

2               、byName

autowire byName (按名称自动装配)

由于在手动配置xml过程中      ,常常发生字母缺漏和大小写等错误          ,而无法对其进行检查                   ,使得开发效率 降低                  。

采用自动装配将避免这些错误         ,并且使配置简单化             。

测试:

1. 修改bean配置      ,增加一个属性 autowire="byName"

<bean id="user" class="com.kuang.pojo.User" autowire="byName"> <property name="str" value="qinjiang"/> </bean>

2. 再次测试                   ,结果依旧成功输出!

3. 我们将 cat 的bean id修改为 catXXX

4. 再次测试            , 执行时报空指针java.lang.NullPointerException   。因为按byName规则找不对应set方 法   ,真正的setCat就没执行                   ,对象就没有初始化               ,所以调用时就会报空指针错误                  。

小结:

当一个bean节点带有 autowire byName的属性时                。

将查找其类中所有的set方法名,例如setCat                ,获得将set去掉并且首字母小写的字符串                  ,即cat。 去spring容器中寻找是否有此字符串名称id的对象               。 如果有   ,就取出注入;如果没有             ,就报空指针异常                   。

3                   、byType

autowire byType (按类型自动装配)

使用autowire byType首先需要保证:同一类型的对象                  ,在spring容器中唯一   。如果不唯一      ,会报不唯一 的异常            。

NoUniqueBeanDefinitionException

测试:

1. 将user的bean配置修改一下 : autowire="byType"

2. 测试          ,正常输出

3. 在注册一个cat 的bean对象!

<bean id="dog" class="com.kuang.pojo.Dog"/> <bean id="cat" class="com.kuang.pojo.Cat"/> <bean id="cat2" class="com.kuang.pojo.Cat"/> <bean id="user" class="com.kuang.pojo.User" autowire="byType">   <property name="str" value="qinjiang"/> </bean>

4. 测试                   ,报错:NoUniqueBeanDefinitionException

5. 删掉cat2         ,将cat的bean名称改掉!测试!因为是按类型装配      ,所以并不会报异常                   ,也不影响最后 的结果                   。甚至将id属性去掉            ,也不影响结果      。

这就是按照类型自动装配!

4 使用注解

jdk1.5开始支持注解   ,spring2.5开始全面支持注解         。

准备工作: 利用注解的方式注入属性                   。

1. 在spring配置文件中引入context文件头

xmlns:context="http://www.springframework.org/schema/context" http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd

2. 开启属性注解支持!

<context:annotation-config/>

4.1   、@Autowired

@Autowired是按类型自动转配的                   ,不支持id匹配          。 需要导入 spring-aop的包!

测试:

1. 将User类中的set方法去掉               ,使用@Autowired注解

public class User {   @Autowired   private Cat cat;   @Autowired   private Dog dog;   private String str;   public Cat getCat() {     return cat;   }   public Dog getDog() {     return dog;   }   public String getStr() {     return str;   } }

2. 此时配置文件内容

<context:annotation-config/> <bean id="dog" class="com.kuang.pojo.Dog"/> <bean id="cat" class="com.kuang.pojo.Cat"/> <bean id="user" class="com.kuang.pojo.User"/>

3. 测试,成功输出结果!

【科普】

@Autowired(required=false) 说明: false                ,对象可以为null;true                  ,对象必须存对象   ,不能为null      。

//如果允许对象为null             ,设置required = false,默认为true @Autowired(required = false) private Cat cat;

4.2            、@Qualifier

@Autowired是根据类型自动装配的                  ,加上@Qualifier则可以根据byName的方式自动装配 @Qualifier不能单独使用                  。

测试实验步骤:

1. 配置文件修改内容      ,保证类型存在对象             。且名字不为类的默认名字!

<bean id="dog1" class="com.kuang.pojo.Dog"/> <bean id="dog2" class="com.kuang.pojo.Dog"/> <bean id="cat1" class="com.kuang.pojo.Cat"/> <bean id="cat2" class="com.kuang.pojo.Cat"/>

2. 没有加Qualifier测试          ,直接报错

3. 在属性上添加Qualifier注解

@Autowired @Qualifier(value = "cat2") private Cat cat; @Autowired @Qualifier(value = "dog2") private Dog dog;

4. 测试                   ,成功输出!

4.3                   、@Resource

@Resource如有指定的name属性         ,先按该属性进行byName方式查找装配; 其次再进行默认的byName方式进行装配; 如果以上都不成功      ,则按byType的方式自动装配   。 都不成功                   ,则报异常                  。

实体类:

public class User {   //如果允许对象为null            ,设置required = false,默认为true   @Resource(name = "cat2")   private Cat cat;   @Resource   private Dog dog;   private String str; }

beans.xml

<bean id="dog" class="com.hang.pojo.Dog"/> <bean id="cat1" class="com.hang.pojo.Cat"/> <bean id="cat2" class="com.hang.pojo.Cat"/> <bean id="user" class="com.hang.pojo.User"/>

测试:结果OK

配置文件2:beans.xml    , 删掉cat2

<bean id="dog" class="com.kuang.pojo.Dog"/> <bean id="cat1" class="com.kuang.pojo.Cat"/>

实体类上只保留注解

@Resource private Cat cat; @Resource private Dog dog;

结果:OK

结论:先进行byName查找                   ,失败;再进行byType查找               ,成功                。

5      、小结

@Autowired与@Resource异同:

@Autowired与@Resource都可以用来装配bean。都可以写在字段上,或写在setter方法上               。 @Autowired默认按类型装配(属于spring规范)                ,默认情况下必须要求依赖对象必须存在                  ,如果 要允许null 值   ,可以设置它的required属性为false             ,如:@Autowired(required=false)                   ,如果我 们想使用名称装配可以结合@Qualifier注解进行使用 @Resource(属于J2EE复返)      ,默认按照名称进行装配          ,名称可以通过name属性进行指定                   。如果 没有指定name属性                   ,当注解写在字段上时         ,默认取字段名进行按照名称查找      ,如果注解写在 setter方法上默认取属性名进行装配   。 当找不到与名称匹配的bean时才按照类型进行装配            。但是 需要注意的是                   ,如果name属性一旦指定            ,就只会按照名称进行装配                   。

它们的作用相同都是用注解方式注入对象   ,但执行顺序不同      。@Autowired先byType                   ,@Resource先 byName         。

使用注解开发

1         、说明

在spring4之后               ,想要使用注解形式,必须得要引入aop的包

在配置文件当中                ,还得要引入一个context约束

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     xmlns:context="http://www.springframework.org/schema/context"     xsi:schemaLocation="http://www.springframework.org/schema/beans       http://www.springframework.org/schema/beans/spring-beans.xsd       http://www.springframework.org/schema/context       http://www.springframework.org/schema/context/spring-context.xsd"> </beans>

2                   、Bean的实现

我们之前都是使用 bean 的标签进行bean注入                  ,但是实际开发中   ,我们一般都会使用注解!

1. 配置扫描哪些包下的注解

<!--指定注解扫描包--> <context:component-scan base-package="com.hang.pojo"/>

2. 在指定包下编写类             ,增加注解

@Component("user") // 相当于配置文件中 <bean id="user" class="当前注解的类"/> public class User {   public String name = "腹白"; }

3. 测试

@Test public void test(){   ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");   User user = (User) applicationContext.getBean("user");   System.out.println(user.name); }

3          、属性注入

使用注解注入属性

1. 可以不用提供set方法                  ,直接在直接名上添加@value("值")

@Component("user") // 相当于配置文件中 <bean id="user" class="当前注解的类"/> public class User {   @Value("秦疆")   // 相当于配置文件中 <property name="name" value="秦疆"/>   public String name; }

2. 如果提供了set方法      ,在set方法上添加@value("值");

@Component("user") public class User {   public String name;   @Value("秦疆")   public void setName(String name) {     this.name = name;   } }

4      、衍生注解

我们这些注解          ,就是替代了在配置文件当中配置步骤而已!更加的方便快捷!

@Component三个衍生注解

为了更好的进行分层                   ,Spring可以使用其它三个注解         ,功能一样      ,目前使用哪一个功能都一样                   。

@Controller:web层 @Service:service层 @Repository:dao层

写上这些注解                   ,就相当于将这个类交给Spring管理装配了!

5                  、自动装配注解

在Bean的自动装配已经讲过了            ,可以回顾!

6             、作用域

@scope

singleton:默认的   ,Spring会采用单例模式创建这个对象          。关闭工厂                    ,所有的对象都会销毁      。 prototype:多例模式                  。关闭工厂                ,所有的对象不会销毁             。内部的垃圾回收机制会回收
@Controller("user") @Scope("prototype") public class User {   @Value("秦疆")   public String name; }

7   、小结

XML与注解比较

XML可以适用任何场景 ,结构清晰                ,维护方便 注解不是自己提供的类使用不了                  ,开发简单方便

xml与注解整合开发 :推荐最佳实践

xml管理Bean 注解完成属性注入 使用过程中   , 可以不用扫描             ,扫描是为了类上的注解
<context:annotation-config/>

作用:

进行注解驱动注册                  ,从而使注解生效 用于激活那些已经在spring容器里注册过的bean上面的注解      ,也就是显示的向Spring注册 如果不扫描包          ,就需要手动配置bean 如果不加注解驱动                   ,则注入的值为null!

8                  、基于Java类进行配置

JavaConfig 原来是 Spring 的一个子项目         ,它通过 Java 类的方式提供 Bean 的定义信息      ,在 Spring4 的 版本                   , JavaConfig 已正式成为 Spring4 的核心功能    。

测试:

1. 编写一个实体类            ,Dog

@Component //将这个类标注为Spring的一个组件   ,放到容器中! public class Dog {   public String name = "dog"; }

2. 新建一个config配置包                   ,编写一个MyConfig配置类

@Configuration //代表这是一个配置类 public class MyConfig {   @Bean //通过方法注册一个bean               ,这里的返回值就Bean的类型,方法名就是bean的id!   public Dog dog(){     return new Dog();   } }

3. 测试

@Test public void test2(){   ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);   Dog dog = (Dog) applicationContext.getBean("dog");   System.out.println(dog.name); }

4. 成功输出结果!

导入其他配置如何做呢?

1. 我们再编写一个配置类!

@Configuration //代表这是一个配置类 public class MyConfig2 { }

2. 在之前的配置类中我们来选择导入这个配置类

@Configuration @Import(MyConfig2.class) //导入合并其他配置类                ,类似于配置文件中的 inculde 标签 public class MyConfig {   @Bean   public Dog dog(){     return new Dog();   } }

关于这种Java类的配置方式                  ,我们在之后的SpringBoot 和 SpringCloud中还会大量看到   ,我们需要知道 这些注解的作用即可!

声明:本站所有文章             ,如无特殊说明或标注                  ,均为本站原创发布                  。任何个人或组织      ,在未征得本站同意时          ,禁止复制                、盗用、采集               、发布本站内容到任何网站                   、书籍等各类媒体平台                。如若本站内容侵犯了原著者的合法权益                   ,可联系我们进行处理。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
rv1126 npu(RV1126_python人脸识别Retinaface+MobilefaceNet) python filter dict(python中filter()的多种筛选)