spring 自动装配
Beans 自动装配
Spring 容器可以在不使用 和 元素的情况下自动装配相互协作的 bean 之间的关系,这有助于减少编写一个大的基于 Spring 的应用程序的 XML 配置的数量。
自动装配模式
下列自动装配模式,它们可用于指示 Spring 容器为来使用自动装配进行依赖注入。你可以使用 元素的 autowire 属性为一个 bean 定义指定自动装配模式。
模式 | 描述 |
---|---|
no | 这是默认的设置,它意味着没有自动装配,你应该使用显式的bean引用来连线。你不用为了连线做特殊的事。在依赖注入章节你已经看到这个了。 |
byName | 由属性名自动装配。Spring 容器看到在 XML 配置文件中 bean 的自动装配的属性设置为 byName。然后尝试匹配,并且将它的属性与在配置文件中被定义为相同名称的 beans 的属性进行连接。 |
byType | 由属性数据类型自动装配。Spring 容器看到在 XML 配置文件中 bean 的自动装配的属性设置为 byType。然后如果它的类型匹配配置文件中的一个确切的 bean 名称,它将尝试匹配和连接属性的类型。如果存在不止一个这样的 bean,则一个致命的异常将会被抛出。 |
constructor | 类似于 byType,但该类型适用于构造函数参数类型。如果在容器中没有一个构造函数参数类型的 bean,则一个致命错误将会发生。 |
autodetect | Spring首先尝试通过 constructor 使用自动装配来连接,如果它不执行,Spring 尝试通过 byType 来自动装配。 |
可以使用 byType 或者 constructor 自动装配模式来连接数组和其他类型的集合。
自动装配的局限性
当自动装配始终在同一个项目中使用时,它的效果最好。如果通常不使用自动装配,它可能会使开发人员混淆的使用它来连接只有一个或两个 bean 定义。不过,自动装配可以显著减少需要指定的属性或构造器参数,但你应该在使用它们之前考虑到自动装配的局限性和缺点。
限制 | 描述 |
---|---|
重写的可能性 | 你可以使用总是重写自动装配的 <constructor-arg> 和 <property> 设置来指定依赖关系。 |
原始数据类型 | 你不能自动装配所谓的简单类型包括基本类型,字符串和类。 |
混乱的本质 | 自动装配不如显式装配精确,所以如果可能的话尽可能使用显式装配。 |
Spring 自动装配 ‘byName’
这种模式由属性名称指定自动装配。Spring 容器看作 beans,在 XML 配置文件中 beans 的 auto-wire 属性设置为 byName。然后,它尝试将它的属性与配置文件中定义为相同名称的 beans 进行匹配和连接。如果找到匹配项,它将注入这些 beans,否则,它将抛出异常。
例如,在配置文件中,如果一个 bean 定义设置为自动装配 byName,并且它包含 spellChecker 属性(即,它有一个 setSpellChecker(...) 方法),那么 Spring 就会查找定义名为 spellChecker 的 bean,并且用它来设置这个属性。你仍然可以使用 <property> 标签连接其余的属性。下面的例子将说明这个概念。
让我们在恰当的位置使用 Eclipse IDE,然后按照下面的步骤来创建一个 Spring 应用程序:
步骤 | 描述 |
---|---|
1 | 创建一个名称为 SpringExample 的项目,并且在已创建的项目的 src 文件夹中创建一个包 com.tutorialspoint。 |
2 | 使用 Add External JARs 选项,添加所需的 Spring 库,在 Spring Hello World Example 章节中已说明。 |
3 | 在 com.tutorialspoint 包中创建 Java 类 TextEditor,SpellChecker 和 MainApp。 |
4 | 在 src 文件夹中创建 Beans 的配置文件 Beans.xml。 |
5 | 最后一步是创建所有 Java 文件和 Bean 配置文件的内容,并运行该应用程序,正如下面解释的一样。 |
这里是 TextEditor.java 文件的内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | package com.tutorialspoint; public class TextEditor { private SpellChecker spellChecker; private String name; public void setSpellChecker( SpellChecker spellChecker ){ this .spellChecker = spellChecker; } public SpellChecker getSpellChecker() { return spellChecker; } public void setName(String name) { this .name = name; } public String getName() { return name; } public void spellCheck() { spellChecker.checkSpelling(); } } |
下面是另一个依赖类文件 SpellChecker.java 的内容:
1 2 3 4 5 6 7 8 9 | package com.tutorialspoint; public class SpellChecker { public SpellChecker() { System.out.println( "Inside SpellChecker constructor." ); } public void checkSpelling() { System.out.println( "Inside checkSpelling." ); } } |
下面是 MainApp.java 文件的内容:
1 2 3 4 5 6 7 8 9 10 11 | package com.tutorialspoint; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MainApp { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext( "Beans.xml" ); TextEditor te = (TextEditor) context.getBean( "textEditor" ); te.spellCheck(); } } |
下面是在正常情况下的配置文件 Beans.xml 文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <?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-3.0.xsd"> <!-- Definition for textEditor bean --> <bean id= "textEditor" class = "com.tutorialspoint.TextEditor" > <property name= "spellChecker" ref= "spellChecker" /> <property name= "name" value= "Generic Text Editor" /> </bean> <!-- Definition for spellChecker bean --> <bean id= "spellChecker" class = "com.tutorialspoint.SpellChecker" > </bean> </beans> |
但是,如果你要使用自动装配 “byName”,那么你的 XML 配置文件将成为如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <?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-3.0.xsd"> <!-- Definition for textEditor bean --> <bean id= "textEditor" class = "com.tutorialspoint.TextEditor" autowire= "byName" > <property name= "name" value= "Generic Text Editor" /> </bean> <!-- Definition for spellChecker bean --> <bean id= "spellChecker" class = "com.tutorialspoint.SpellChecker" > </bean> </beans> |
一旦你完成了创建源代码和 bean 的配置文件,我们就可以运行该应用程序。如果你的应用程序一切都正常,它将打印下面的消息:
Inside SpellChecker constructor. Inside checkSpelling.
Spring 自动装配 ‘byType’
这种模式由属性类型指定自动装配。Spring 容器看作 beans,在 XML 配置文件中 beans 的 autowire 属性设置为 byType。然后,如果它的 type 恰好与配置文件中 beans 名称中的一个相匹配,它将尝试匹配和连接它的属性。如果找到匹配项,它将注入这些 beans,否则,它将抛出异常。
例如,在配置文件中,如果一个 bean 定义设置为自动装配 byType,并且它包含 SpellChecker 类型的 spellChecker 属性,那么 Spring 就会查找定义名为 SpellChecker 的 bean,并且用它来设置这个属性。你仍然可以使用 <property> 标签连接其余属性。下面的例子将说明这个概念,你会发现和上面的例子没有什么区别,除了 XML 配置文件已经被改变。
让我们在恰当的位置使用 Eclipse IDE,然后按照下面的步骤来创建一个 Spring 应用程序:
步骤 | 描述 |
---|---|
1 | 创建一个名称为 SpringExample 的项目,并且在已创建的项目的 src 文件夹中创建一个包 com.tutorialspoint。 |
2 | 使用 Add External JARs 选项,添加所需的 Spring 库,在 Spring Hello World Example 章节中已说明。 |
3 | 在 com.tutorialspoint 包中创建 Java 类 TextEditor,SpellChecker 和 MainApp。 |
4 | 在 src 文件夹中创建 Beans 的配置文件 Beans.xml。 |
5 | 最后一步是创建所有 Java 文件和 Bean 配置文件的内容,并运行该应用程序,正如下面解释的一样。 |
但是,如果你要使用自动装配 “byType”,那么你的 XML 配置文件将成为如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <?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-3.0.xsd"> <!-- Definition for textEditor bean --> <bean id= "textEditor" class = "com.tutorialspoint.TextEditor" autowire= "byType" > <property name= "name" value= "Generic Text Editor" /> </bean> <!-- Definition for spellChecker bean --> <bean id= "SpellChecker" class = "com.tutorialspoint.SpellChecker" > </bean> </beans> |
一旦你完成了创建源代码和 bean 的配置文件,我们就可以运行该应用程序。如果你的应用程序一切都正常,它将打印下面的消息:
Inside SpellChecker constructor.
Inside checkSpelling.
Spring 由构造函数自动装配
这种模式与 byType 非常相似,但它应用于构造器参数。Spring 容器看作 beans,在 XML 配置文件中 beans 的 autowire 属性设置为 constructor。然后,它尝试把它的构造函数的参数与配置文件中 beans 名称中的一个进行匹配和连线。如果找到匹配项,它会注入这些 bean,否则,它会抛出异常。
例如,在配置文件中,如果一个 bean 定义设置为通过构造函数自动装配,而且它有一个带有 SpellChecker 类型的参数之一的构造函数,那么 Spring 就会查找定义名为 SpellChecker 的 bean,并用它来设置构造函数的参数。你仍然可以使用 <constructor-arg> 标签连接其余属性。下面的例子将说明这个概念。
让我们在恰当的位置使用 Eclipse IDE,然后按照下面的步骤来创建一个 Spring 应用程序:
步骤 | 描述 |
---|---|
1 | 创建一个名称为 SpringExample 的项目,并且在已创建的项目的 src 文件夹中创建一个包 com.tutorialspoint。 |
2 | 使用 Add External JARs 选项,添加所需的 Spring 库,在 Spring Hello World Example 章节中已说明。 |
3 | 在 com.tutorialspoint 包中创建 Java 类 TextEditor,SpellChecker 和 MainApp。 |
4 | 在 src 文件夹中创建 Beans 的配置文件 Beans.xml。 |
5 | 最后一步是创建所有 Java 文件和 Bean 配置文件的内容,并运行该应用程序,正如下面解释的一样。 |
这里是 TextEditor.java 文件的内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | package com.tutorialspoint; public class TextEditor { private SpellChecker spellChecker; private String name; public TextEditor( SpellChecker spellChecker, String name ) { this .spellChecker = spellChecker; this .name = name; } public SpellChecker getSpellChecker() { return spellChecker; } public String getName() { return name; } public void spellCheck() { spellChecker.checkSpelling(); } } |
下面是另一个依赖类文件 SpellChecker.java 的内容:
1 2 3 4 5 6 7 8 9 10 | package com.tutorialspoint; public class SpellChecker { public SpellChecker(){ System.out.println( "Inside SpellChecker constructor." ); } public void checkSpelling() { System.out.println( "Inside checkSpelling." ); } } |
下面是 MainApp.java 文件的内容:
1 2 3 4 5 6 7 8 9 10 11 | package com.tutorialspoint; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MainApp { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext( "Beans.xml" ); TextEditor te = (TextEditor) context.getBean( "textEditor" ); te.spellCheck(); } } |
下面是在正常情况下的配置文件 Beans.xml 文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <?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-3.0.xsd"> <!-- Definition for textEditor bean --> <bean id= "textEditor" class = "com.tutorialspoint.TextEditor" > <constructor-arg ref= "spellChecker" /> <constructor-arg value= "Generic Text Editor" /> </bean> <!-- Definition for spellChecker bean --> <bean id= "spellChecker" class = "com.tutorialspoint.SpellChecker" > </bean> </beans> |
但是,如果你要使用自动装配 “by constructor”,那么你的 XML 配置文件将成为如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <?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-3.0.xsd"> <!-- Definition for textEditor bean --> <bean id= "textEditor" class = "com.tutorialspoint.TextEditor" autowire= "constructor" > <constructor-arg value= "Generic Text Editor" /> </bean> <!-- Definition for spellChecker bean --> <bean id= "SpellChecker" class = "com.tutorialspoint.SpellChecker" > </bean> </beans> |
一旦你完成了创建源代码和 bean 的配置文件,我们就可以运行该应用程序。如果你的应用程序一切都正常,它将打印下面的消息:
Inside SpellChecker constructor. Inside checkSpelling.
基于注解的配置
从 Spring 2.5 开始就可以使用注解来配置依赖注入。而不是采用 XML 来描述一个 bean 连线,你可以使用相关类,方法或字段声明的注解,将 bean 配置移动到组件类本身。
在 XML 注入之前进行注解注入,因此后者的配置将通过两种方式的属性连线被前者重写。
注解连线在默认情况下在 Spring 容器中不打开。因此,在可以使用基于注解的连线之前,我们将需要在我们的 Spring 配置文件中启用它。所以如果你想在 Spring 应用程序中使用的任何注解,可以考虑到下面的配置文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <?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-3.0.xsd http: //www.springframework.org/schema/context http: //www.springframework.org/schema/context/spring-context-3.0.xsd"> <context:annotation-config/> <!-- bean definitions go here --> </beans> |
一旦 被配置后,你就可以开始注解你的代码,表明 Spring 应该自动连接值到属性,方法和构造函数。让我们来看看几个重要的注解,并且了解它们是如何工作的:
序号 | 注解 & 描述 |
---|---|
1 | @Required
@Required 注解应用于 bean 属性的 setter 方法。 |
2 | @Autowired
@Autowired 注解可以应用到 bean 属性的 setter 方法,非 setter 方法,构造函数和属性。 |
3 | @Qualifier
通过指定确切的将被连线的 bean,@Autowired 和 @Qualifier 注解可以用来删除混乱。 |
4 | JSR-250 Annotations
Spring 支持 JSR-250 的基础的注解,其中包括了 @Resource,@PostConstruct 和 @PreDestroy 注解。 |
注解装配
annotation注解,注解就是采用一个@加上字段进行声明,就像我们常见的@Test、@Override等等
采用注解进行装配之前,bean.xml文件要较之前有个改变:
1 2 3 4 5 6 7 8 9 10 11 | <?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:p= "http://www.springframework.org/schema/p" xmlns:context= "http://www.springframework.org/schema/context" xsi:schemaLocation="http: //www.springframework.org/schema/beans http: //www.springframework.org/schema/beans/spring-beans-3.1.xsd http: //www.springframework.org/schema/context http: //www.springframework.org/schema/context/spring-context-3.1.xsd"> <context:component-scan base- package = "com.eco" ></context:component-scan> </beans> |
红字是较之前手动装配/自动装配新增的声明字段,然后内部只有一个标签,这个标签告诉容器要解析哪个包下的bean。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | @Service public class Userservice { // 定义接口的引用 private UserDao userdao; // 定义setter方法,设置接口的引用指向哪个实现类的对象 @Autowired public void setUserdao(UserDao userdao) { this .userdao = userdao; } public void useradd(User newuser) { // 此时的userdao经过spring依赖注入之后已经实现指向特定的接口实现类对象 // 那么调用接口的方法,实际上是调用了特定实现类的方法的 userdao.adduser(newuser); } } @Repository public class Usertodo1 implements UserDao { // 接口实现类为方法添加方法体 public void adduser(User user) { // 利用Hibernate的工厂类获得Session对象和事务对象Transaction Session session = HibernateSessionFactory.getSession(); Transaction transaction = session.beginTransaction(); // 数据库添加用户操作 session.save(user); // 提交事务 transaction.commit(); // 关闭session对象 session.close(); System.out.println( "todo1 create the user" ); } } |
红字标注的三个注解意思就是:为@Service声明的Userservice类,内部的@Autowired声明的userdao变量,注入了
@Repository声明的Usertodo1实现类。
依赖注入有①接口注入②setter注入③构造方法注入,很明显上面的例子是setter注入,
接口注入就将注解写在定义的成员变量上;
setter注入就将注解写在setter方法上;
构造方法注入就将注解写在构造方法上(很明显上面没有定义构造方法)。
调用的时候方法还是和之前一样:
1 2 3 4 5 6 7 8 9 10 11 12 | public class Test1 { @Test public void add() { // Spring读取beans。xml文件 ApplicationContext ctx = new ClassPathXmlApplicationContext( "beans.xml" ); // 解析id为userservice的bean标签,内部实现UserDao userdao = new Usertodo1() Userservice service = (Userservice) ctx.getBean( "userservice" ); User newuser = new User( "桔子桑" , 31 ); // 此时调用的useradd()方法,就是接口实现类Usertodo1的useradd()方法 service.useradd(newuser); } } |
只是这个bean的名称,默认是采用@Service声明的类的名称首字母小写,其余不变作为bean的id/name;
我们也是可以自定义这个bean名称的,@Service("eco"),像这样在括号里就可以自定义名称了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具