spring IoC(控制反转)
在Spring中把每一个需要管理的对象称为Spring Bean (简称Bean ),而Spring 管理这些Bean 的容器,被我们称为Spring
IoC 容器(或者简称IoC 容器) 。IoC 容器需要具备两个基本的功能:
通过描述管理Bean , 包括发布和获取Bean;
通过描述完成Bean 之间的依赖关系。
Spring IoC 容器是一个管理Bean 的容器,在Spring 的定义中,它要求所有的IoC 容器都需要实现接口BeanFactory ,它是一个顶级容器接口。由于BeanFactory 的功能还不够强大,因此Spring 在BeanFactory 的基础上, 还设计了一个更为高级的接口ApplicationContext 。它是BeanFactory 的子接口之一, 在Spring 的体系中BeanFactory 和ApplicationContext 是最为重要的接口设计,在现实中我们使用的大部分Spring IoC 容器是Appl icationContext 接口的实现类。
下面来看一个最为简单的例子。首先定义一个Java 简单对象( P lain Ordinary Java Object, POJO )文件User.java
package com.springboot.chapter3.pojo;
public class User{
private Long id;
private String userName;
private String note;
}
然后再定义一个Java 配置文件AppConfig.java
package com.springboot.chapter3.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration ;
import com.springboot.chapter3.pojo.User ;
@Configuration
public class AppConfig{
@Bean(name="user")
public User initUser(){
User user = new User();
user.setId(1L);
user.setUserName("username");
user.setNote("note");
return user;
}
}
@ Configuration 代表这是一个Java 配置文件, Spring的容器会根据
它来生成IoC 容器去装配Bean; @Bean 代表将initUser方法返回的POJO 装配到IoC 容器中,而其
属性name 定义这个Bean 的名称,如果没有配置它,则将方法名称“ initUser ”作为Bean 的名称保
存到Spring IoC 容器中。
做好了这些,就可以使用AnnotationConfigApplicationContext 来构建自己的IoC 容器
package com.springboot.chapter3.config ;
import org.apache.log4j.Logger ;
import org.springframework.context.ApplicationContext ;
import org.springframework.context annotation.AnnotationConfigApplicationContext;
import com.springboot.chapter3.pojo.User;
public class IocTest{
private static Logger log = Logger.getLogger(IocTest.class);
public static void main(String[] args){
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
User user = ctx.getBean(User.class);
log.info(user.getId);
}
}
代码中将Java 配置文件AppConfig 传递给AnnotationConfigApplicationContext 的构造方法,这
样它就能够读取配置了。然后将配置里面的Bean 装配到IoC 容器中,于是可以使用getBean 方法获
取对应的POJO
通过扫描装配你的Bean
如果一个个的Bean 使用注解@Bean 注入Spring loC 容器中,那将是一件很麻烦的事情。好在
Spring 还允许我们进行扫描装配Bean 到loC 容器中,对于扫描装配而言使用的注解是@Component
和@ComponentScan 。@Component 是标明l哪个类被扫描进入Spring IoC 容器,而@ComponentScan
则是标明采用何种策略去扫描装配Bean
package com.springboot.chapter3.config ;
@Component (”user")
public class User {
@Value (” 1 ”)
private Long id;
@Value (”user name 1”}
private String userName ;
@Value (”note 1”)
private String note;
/**setter and getter **/
}
这里的注解@Component 表明这个类将被Spring IoC 容器扫描装配,其中配置的“ user "则是作为
Bean 的名称,当然你也可以不配置这个字符串,那么IoC 容器就会把类名第一个字母作为小写,其他
不变作为Bean 名称放入到IoC 容器中;注解@Value 则是指定具体的值,使得Spring IoC 给予对应的
属性注入对应的值。为了让Spring IoC 容器装配这个类, 需要改造类AppConfig ,
package com.springboot.chapter3.config ;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotationConfiguration;
@Configuration
@ComponentScan
public class AppConfig {
}
这里加入了@ComponentScan ,意味着它会进行扫描,但是它只会扫描类AppConfig 所在的当前
包和其子包。
为了更加合理,@ ComponentScan 还允许我们自定义扫描的包.
@ComponentScan (”com.springboot.chapter3.* ” )
或
@ComponentScan(basePackages = {”com.springboot.chapter3.pojo” })
或
ComponentScan(basePackageClasses = {User.class} )
无论采用何种方式都能够使得IoC 容器去扫描User 类,而包名可以采用正则式去匹配。但是有
时候我们的需求是想扫描一些包,将一些Bean 装配到Spring IoC 容器中,而不是想加载这个包里面
的某些Bean 。
ComponentScan(basePackages = "com.springboot.chapter3.*”,
excludeFilters = {@Filter(classes = {Service.class})})
这样,由于加入了excludeFilters 的配置,使标注了@Service 的类将不被IoC 容器扫描注入,这
样就可以把UserService 类排除到Spring IoC 容器中了
现实的Java 的应用往往需要引入许多来自第三方的包, 并且很有可能希望把第三方包的类对象
也放入到Spring IoC 容器中,这时@Bean 注解就可以发挥作用了。
例如, 要引入一个DBCP 数据源,我们先在pom.xml 上加入项目所需要DBCP 包和数据库MySQL
驱动程序的依赖
这样DBCP 和数据库驱动就被加入到了项目中,接着将使用它提供的机制来生成数据源。
@Bean(name = "dataSource")
public DataSource getDataSource () {
Properties props= new Properties();
props.setProperty(”driver ”,”com.mysql . jdbc.Driver ");
props.setProperty("url”,”jdbc:mysql://localhost:3306/chapter3”);
props.setProperty(”username”,”root") ;
props.setProperty(”password ”,”123456”) ;
DataSource dataSource = null ;
try {
dataSource = BasicDataSourceFactory.createDataSource(props);
} catch ( Exception e) {
e. printStackTrace ();
return dataSource;
}
这里通过@Bean 定义了其配置项name 为“ dataSource 飞那么Spring 就会把它返回的对象用名
称“ dataSource ” 保存在loC 容器中。当然, 你也可以不填写这个名称,那么它就会用你的方法名称
作为Bean 名称保存到roe 容器中。通过这样,就可以将第三方包的类装配到Spr ing IoC 容器中了。