声明Bean首先第一步要声明Bean,这样Bean才能被Spring的IoC容器管理 。声明Bean有很多种方式,在一开始,Spring是使用XML的方式来声明一个Bean:
<bean id="myVehicle" class="test.spring.bean.Bus" /><bean id="worker" class="test.spring.bean.Worker"><property name="vehicle"><ref bean="myVehicle" /></property></bean>复制代码这样以后如果要依赖的Bean变了,只需要修改XML文件就行了 。
后来由于XML文件难以阅读和维护,Spring开始支持用注解的方式定义Bean 。我们在定义具体实现类的时候,可以在class上面加上@Component注解,然后配置好Spring的自动扫描路径,这样Spring就能够自己去扫描相应的类,纳入IoC容器中进行管理了 。
@Componentpublic class A {}复制代码@Component的语义其实不是很明确,因为“万物皆可为组件” 。它其实是一个元注解,也就是说,可以注解其它注解 。Spring提供了@Controller、@Service、@Repository、@Aspect等注解来供特定功能的Bean上面使用 。
我们自己也可以声明一些类似的注解,如果我们使用DDD,也可以用@Component声明一些诸如@ApplicationService、@DomainService之类的注解 。
SpringBoot默认的扫描路径是启动类当前的包和子包 。我们可以通过@ComponentScan和@ComponentScans来配置包的扫描路径 。
另一种方式是通过在方法上声明@Bean注解来声明一个Bean 。这个时候一般是会与@Configuration一起来配合使用的 。
@Configurationpublic class MyConfig {@Beanpublic B getB() {return new B();}}复制代码
一般只有在对框架提供的Bean有一些特殊配置的时候,才会使用@Bean注解 。比如数据库配置等 。使用Bean使用Bean也有很多种方式 。XML就不说了,上面例子也展示了如何在XML里配置Bean的注入 。
Spring比较推荐的是使用构造器注入,因为构造器注入能够在启动的时候就检查要依赖的对象是否存在,如果不存在,会启动失败并且抛出以下异常:
Parameter 0 of constructor in com.example.springbase.bean.A required a bean of type 'com.example.springbase.config.B' that could not be found.The following candidates were found but could not be injected:- User-defined bean method 'getB' in 'MyConfig' ignored as the bean value is nullAction:Consider revisiting the entries above or defining a bean of type 'com.example.springbase.config.B' in your configuration.复制代码这样我们就可以更早地发现依赖问题,而不用在运行时才发现要依赖的对象没有被注入进来,发生一些空指针异常 。另一种方式是注解注入,注解注入的好处是代码简洁,不用专门写构造器 。Spring支持三个注解:
- Resource - JSR250定义
- Inject - JSR330定义
- Autowired - Spring提供
【关于Spring IoC的那些事】@Resource是先通过名称匹配,找不到再通过类型匹配,找不到再通过结合@Qualifier来匹配 。
而@Inject是先通过类型匹配,找不到再通过Qualifier来匹配,找不到再通过名称匹配 。如果要使用@Inject,需要引入额外的包:
<dependency><groupId>javax.inject</groupId><artifactId>javax.inject</artifactId><version>1</version></dependency> 复制代码@Autowired和@Inject的用法一致,唯一区别就是@Autowired属于Spring框架提供的注解 。其实最推荐的是使用JSR-330的规范,这样可以做到与框架无关 。但是笔者发现大多数项目还是使用@Autowired居多,而且很难真正做到与Spring框架无关,因为@Component就是Spring提供的注解 。我们平时经常使用的@Controller、@Service、@Repository、@Aspect等注解也都是Spring提供的 。
所以如果要说推荐一个注解的话,笔者更推荐Spring的@Autowired 。
还有一种方式,可以从Spring的上下文中直接拿Bean 。这种方式一般用于:从一个不受Spring管理的对象中获取一个Bean 。比如说二方包里面的代码,就有可能会有这种情况 。
// 定义一个aware,持有一个static的context对象@Componentpublic class MySpringContextAware implements ApplicationContextAware {public static ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {MySpringContextAware.applicationContext = applicationContext;}}// A是不受Spring管理的public class A {// B是受Spring管理的private B b;public A() {System.out.println("a init");// 这样就可以在不受Spring管理的对象里面,获取到Bean了this.b = (B) MySpringContextAware.applicationContext.getBean(B.class);;System.out.println(b.hashCode());}}复制代码
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 饮食|关于维生素是否能帮助你减肥,这些真相你知道吗?
- spring框架之AOP面向切面编程
- 关于下一代智能手机的谈论 人工智能和云赋予手机完全个性化
- 看电视的利与弊
- 中国关于美人鱼的传说
- 韩信关于他与刘邦之间不同点的描述
- 交换机配置指南半分钟即可掌握关于SSL配置的内容
- 曹丕把曹彰杀了吗
- 关于人性的恶经典名句有哪些?
- 一文让你读懂JAVA.IO、字符编码、URL和Spring.Resource
