一、概述
我们知道,使用类的方法和属性,通常需要将类进行实例化后,才能具象化去使用这些方法和属性。
然而类的实例随着方法运行的结束结束,。这不仅增加了开发的代价,还需要大量的甚至重复的实例化代码,而且增加了GC回收的压力。那么是否可以通过一个容器来进行统一管理,在spring进行统一管理得这些对象就是bean。
二、bean的含义
Spring Bean是被实例的,组装的及被Spring容器管理的Java对象。
Spring容器会自动完成@bean对象的实例化。
通俗理解为类的代理或代言人(实际上确实是通过反射、代理来实现的),这样它就能代表类拥有该拥有的东西了。比如我们都在微博上@过某某,对方会优先看到这条信息,并给你反馈,那么在Spring中,你标识一个@符号,那么Spring就会来看看,并且从这里拿到一个Bean或者给出一个Bean。
三、bean的三种配置方案
1、在XML中进行显示配置
2、使用Java代码进行显示配置
3、隐式的bean发现机制和自动装配
推荐方式: 3> 2> 1
四、bean的装配之自动化装配bean
1.组件扫描(组件扫描):Spring会自动发现应用程序。
组件注解作用:
表明该类会作为组件类。
不过,组件扫描默认是不开启用的,我们还需要显示配置下Spring,从而命令它去寻找带有@Component注解的类,并创建Bean。
bean配置好了需要收集这些bean,那么如何将这些bean收集起来呢? 此时,就需要bean的收集器,有两种方式,包括java和XML
Java代码执行bean收集:
其中,如果CompoentScan后面没有参数的话,则会扫描与配置类相同的包。
@Configuration
@ComponentScan
public class JavaConfig {
}
XML方式执行bean收集:
<!-- 自动扫描该包 -->
<context:component-scan base-package="com.**" />
当这些bean收集起来之后,当我们想要在某个测试类使用@Autowired注解来引入这些收集起来的bean时,只需要给这个测试类添加@ContextConfiguration注解来标注我们想要导入这个测试类的某些bean。
4.2、为组件扫描的bean命名
默认情况加,Spring应用上下文种所有的bean都会给定一个ID。在前面的例子中,尽管我们没有明确地为MailSender bean设置ID,但是Spring会默认为MailSender设置ID为mailSender,也就是将类名的第一个字母变成小写。
如果想为这个bean设置不同的ID,那就将期望的值传递给@Component注解
@Component("mailMessageSender")
public class MailSenderimplements IMessageSender {
@Override
public void send() {
System.out.println("this is mailsender!");
}
}
4.3、设置组件扫描的基础包
前面再给MessageConfig类设置@ComponentScan,我们并没有设置任何属性,这个时候默认扫描默认包是:MessageConfig类所在包及其包的子包。
MessageConfig所在的包与@ComponentScan的扫描的包不在同一个包下,就需要设置扫描的包,否则不能进行依赖注入。
@Configuration
@ComponentScan(basePackages ="com.***")
public class MessageConfig {
}
}
4.4、通过为bean添加注解实现自动装配
如果所有的对象都是独立的,彼此之间没有任何依赖,那么使用组件扫描就能自动化装配bean。
但是实际工作中,很多对象会依赖其他对象完成任务。这时候就需要能够将组件扫描得到的bean和他们依赖装配在一起。这就是自动装配(autowiring)
使用Spring的Autowired
@Component
public class AppOptimize implements IOptimizePerformance {
private IMessageSendermessageSender;
@Autowired
public AppOptimize(IMessageSender messageSender) {
this.messageSender = messageSender;
}
@Override
public void optimize() {
System.out.println("app 优化之异步消息发送");
messageSender.send();
}
}
AppOptimize类的构造器上添加了@Autowired注解,表明当Spring创建AppOptimize bean的时候,会通过这个构造器来进行实例化。
Autowired的多种方式
1、构造器注解(constructor)
2、属性setter注解
3、field注解
不管使用上面3中的哪个方法,Spring都会满足声明的依赖。假如有且只有一个bean匹配依赖的话,那么这个bean将会被装配进来。
如果使用2,3方式注解,有多个bean的话,则用Qualifier指定。
比如:优化包含后端优化的实现和前端优化实现。
@Autowired
//@Qualifier("appOptimize")
private IOptimizePerformance appOptimize; //指定具体的实现
@Autowired
@Qualifier("appOptimize") //使用Qualifier指定具体使用到哪个bean
private IOptimizePerformance optimize;
如果没有匹配的bean,那么在应用上下文创建的时候,Spring会抛出一个异常。为了避免异常的出现,可以使用
@Autowired(required = false)
private IOptimizePerformance appOptimize;
required=false表示如果没有匹配的话,Spring会让bean处于未装配的样子。使用未装配的属性,会出现NullPointerException
总结:
所以在使用开发的时候一般建议使用Resource(package javax.annotation)进行注解。但是Resource不支持构造器注解
五、bean的装配之Java代码装配Bean
尽管在很多场景下通过组件扫描和自动装配实现Spring的自动化更为推荐,但是有时候行不通。比如引用第三方组件,没办法在它的类上添加@Component及@Autowired。
所以就需要JavaConfig或者XML配置
在进行显示配置的时候,JavaConfig是更好的解决方案。
JavaConfig与其他的Java代码又有所区别,在概念上它与应用程序中的业务逻辑和领域代码又有所不同。JavaConfig是配置相关代码,不包含任何逻辑代码。通常将JavaConfig放到单独的包中。
@Configuration
public class RedisConfig {
}
使用@Configuration表明RedisConfig是一个配置类
1、用 配置 代替 扫描。
之前:
@Configuration
@ComponentScan(basePackages ="com.nrsc.springstudy.bean_di")
public class MessageConfig {
}
}
如果去掉@ComponentScan(basePackages ="com.nrsc.springstudy.bean_di") 就会出现BeanCreationException异常。
现在解决方案:
声明简单的bean
在MessageConfig中声明bean,需要编写一个方法,该方法会创建所需类型的实例,然后这个方法添加 @Bean注解
@Bean
public IMessageSender setMessageSender(){
return new MailSender();
}
@Bean注解会告诉Spring这个方法会返回一个对象,该对象要注册为Spring应用上下文中的bean。
默认情况下,bean的ID与带有 @Bean注解的方法名是一样的,在上面的例子中,bean的ID将会是setMessageSender。如果想设置不同的ID,那么可以重命名该方法,也可以通过name属性指定一个不同的名字:
@Bean("messageSender")
public IMessageSender setMessageSender(){
return new MailSender();
}
借助JavaConfig实现注入
前面声明的IMessageSender很简单,因为没有其他依赖。但现在,我们需要声明IOptimizePerformance bean,它依赖于IMessageSender。
在javaConfig中装配bean的最简单方式就是引用创建bean的方法。
@Bean
public IOptimizePerformance frontOptimize() {
return new FrontOptimize(setMessageSender());
}
六、bean的装配之通过XML装配Bean
该装配不进行详解,使用较少。
附:
重要注解及其作用
@RunWith(SpringJUnit4ClassRunner.class),让测试运行于Spring测试环境
@ContextConfiguration 作用:加载配置文件。Spring整合JUnit4测试时,使用注解引入多个配置文件
单个文件
@ContextConfiguration(Locations="classpath:applicationContext.xml")
@ContextConfiguration(classes = SimpleConfiguration.class)
多个文件时,可用{}
@ContextConfiguration(locations = { "classpath:spring1.xml", "classpath:spring2.xml" })
@Component :当一个类添加了注解@Component,那么他就自动变成了一个bean,就不需要再Spring配置文件中显示的配置了。
@Qualifier(""):多个bean实现同一个接口的话,指定具体使用哪一个bean。
@Autowired(required = false) :
网友评论