Spring最成功的是其提出的理念,而不是技术本身。它所依赖的两个核心理念,一个是控制反转(Inversion of Control,IoC),另一个是面向切面编程(Aspect Oriented Programming,AOP)
IoC是一种通过描述来生成或者获取对象(Bean)的技术,这个技术不是Spring甚至不是Java独有的。平时最熟悉的是使用new关键字来创建对象,而在Spring中则不是,它是通过描述来创建对象。Spingt Boot中建议使用注解描述生成对象而不是使用XML。
Spring中把每一个需要管理的对象称为Spring Bean(简称Bean),管理这些Bean的容器称为Spring IoC容器(或者简称IoC容器)。IoC容器具备两个基本的功能:通过描述管理Bean(包括发布和获取Bean)和通过描述完成Bean之间的依赖关系。
Spring IoC容器总,可以按类型(by type)或者按名称(by name)获取Bean,默认情况下Bean都是以单例存在的。
IoC装配Bean
使用@Bean注解装配Bean
@Configuration
public class BeanConfig {
@Bean(name = "user")
public User initUser() {
User user = new User();
user.setUsername("Jack");
user.setAge(18);
return user;
}
}
@Configuration 表示这是一个Java配置文件,Spring容器会根据它来生成IoC容器去装配Bean
@Bean 表示将initUser方法返回的POJO装配到IoC容器中,属性name定义Bean的名称,如果没有设置该属性,则默认使用方法名称initUser作为Bean的名称保存到Spring IoC容器中
通过扫描装配Bean
如果使用@Bean一个个的装配,将是一件很麻烦的事情,Spring也意识到了这点,允许使用扫描的方式进行装配,使用的注解是@Component和@ComponentScan,@Component标明哪个类被扫描进入Spring IoC容器,而@ComponentScan则是标明采用何种策略扫描装配Bean
package com.test.example.config;
@Component("user")
public class User {
@Value("Jack")
private String username;
@Value("18")
private int age;
}
@Component标明该类将被Spring IoC容器扫描装配,其中配置的user则是Bean的名称,如果不配置,则IoC容器默认会把类名第一个字母作为小写,其他不变作为Bean名称
@Value 指定具体的值,使得Spring IoC给予对应的属性注入对应的值
为了Spring IoC容器装配这个类,调整BeanConfig
package com.test.example.config;
@Configuration
@ComponentScan
public class BeanConfig {
}
@ComponentScan 标明会进行扫描,默认只是扫描BeanConfig所在的当前package和子package,可以观察到User也在该package下面,但是这样设置太不合理,为了更加合理,运行@ComponentScan扫描自定义的包
@ComponentScan(basePackages = {" com.test.example.pojo"})
包名可以采用正则表达式匹配,但是这个也有不合理的地方,比如不想加载某些Bean,比如定义一个UserService类,将它标记为@Service(该注解已经注入了@Component)服务类,则也会被Spring扫描装配到IoC容器中,如果不希望这些服务类被装配,则可以通过设置excludeFilters
@ComponentScan(basePackages = {" com.test.example.*", excludeFilters = {@Filter(classes = {Service.class})}})
由于加入excludeFilters设置,则使用@Service注解的服务类不会被扫描注入
自定义第三方Bean
实际项目中经常需要引入许多第三方的包,并且希望把第三方包的类对象放入到Spring IoC容器中,这时需要使用@Bean注解
定义一个数据源
@Bean(name = "dataSource")
public DataSource getDataSource() {
Properties props = new Properties();
props.setProperty("driver", "com.mysql.jdbc.Driver");
props.setProperty("url", "jdbc:mysql://localhost:3306/test");
props.setProperty("username", "root");
props.setProperty("password", "root");
DataSource dataSource = null;
try {
dataSource = BasicDataSourceFactory.createDataSource(props);
} catch (Exception e) {
e.printStackTrace();
}
return dataSource;
}
通过@Bean的name配置Bean名称为“dataSource”,如果不设置name属性,默认会使用方法名称作为Bean名称保存到IoC容器中。
上半部分主要讨论了Bean如何装载到IoC容器中,对于如何获取以及Bean之间的依赖,在Spring IoC概念中称为依赖注入(Dependency Injection,DI)
依赖注入DI
@Autowired
Spring中最常用注解之一,可以标注属性、方法、参数。
根据类型(by type)获取Bean,@Autowired是一个默认必须找到对应Bean的注解,如果不确定其标注的属性一定存在并且允许被标注的属性为Null,可以设置required属性为false
@Autowired(require = false)
消除歧义性 @Primary和@Qualifier
@Primary是一个修改优先权的注解,其目的当发现有多个同类型的Bean时,高速IoC容器优先使用该注解标记的Bean,但是它也可以被标注到多个Bean上,这时IoC容器还是无法区分要采用哪个Bean实例,此时需要使用@Qualifier的value来进行设置
@Qualifier和@Autowired组合在一起就是通过类型和名称一起找到Bean,Bean的名称在IoC容器中是唯一的,如
@Autowired
@Qualifier("dog")
private Animal animal = null;
带有参数的构造方法类装配
public ConstructorAnimal(@Autowired @Qualifier("dog") Animal animal) {
...
}
网友评论