IOC思想
概念
1.IOC(控制反转)
- inversion of control
- 控制:创建对象由原来的程序创建交给Spring容器创建
- 反转:程序本身不创建对象,而是被动的接收对象
2.DI(依赖注入)
- dependency injection
- Set将注入
- 依赖:对象的创建依赖于Spring容器
- 注入:对象的所以属性由容器注入
托管bean到Spring容器
1.测试
//容器只用创建一次
static ApplicationContext context;
@BeforeClass
public static void initClass() {
//AnnotationConfigApplicationContext:基于注解,创建管理容器IOC
context = new AnnotationConfigApplicationContext(AppConfig3.class);
}
@Test
public void testProcessor() {
//获取spring托管的bean
String[] beanName = context.getBeanDefinitionNames();
for (String bn : beanName) {
System.out.println(bn);
}
}
1.@Configuration+@Bean(1.10)
- 在配置类中集中创建第三方bean(被人写的)
- 配置类也被托管到spring容器中
@Configuration
public class AppConfig {
@Bean//表示创建hello的bean,并以h为id
public Hello h() {
return new Hello();
}
}
2.@Component+@ComponentScan(1.10.1)
- 托管注解 @Component
1.托管自己写的类
2.对应的id就是该类名的小写,也可以自己约定(value = "xxx")
3.具体语义mvc代替托管注解@Component,功能相同
DAO层:@Repository->将受检异常转成非受检异常,对业务层的影响最小
业务层:@Service->底层也是Component
控制层:@Controller->servlet
- 扫描托管注解 @ComponentScan
1.只要有注解@Component都被扫描到
2.参数
-->basePackages:指定扫描的类路径,默认全部扫描
-->beanId:指定托管类的id
-->useDefaultFilters:默认过滤器(是否自动检测XX注释) 取消默认检测后启动自定义检测
-->includeFilters:包含哪些过滤器
includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = {Component.class})}
类型是一个注解过滤器,过滤的内容是有@Component注解的类
-->excludeFilters:取消哪些过滤器
excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = {Service.class, Repository.class})})
- 实现
@Component(value = "h")
public class Hello {
public Hello() {
System.out.println("Hello构造方法");
}
public void sayHello() {
System.out.println("hello");
}
}
-----------------------------------------------
@Configuration
@ComponentScan(basePackages = {"com.yc.test1", "com.yc.test2"})
public class AppConfig { }
3.@Import(1.12.5)
- beanId没有手工指定,则为类的全路径名称
- 参数
1.反射实例数组
@Configuration
@Import({Hello.class})
public class AppConfig { }
2.ImportSelector接口:提供导入的规则,可以写逻辑判断
@Configuration
@Import({Hello.class,PearImportSelector.class})
//Pear托管,而不是PearImportSelector
public class AppConfig { }
-----------------------------------------------
public class PearImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
//importingClassMetadata:类的原信息
System.out.println("selectImport:" + importingClassMetadata.toString());
return new String[]{Pear.class.getName()};
}
}
3.参数:ImportBeanDefinitionRegistrar接口
@Configuration
@Import({Hello.class,PearImportSelector.class,FruitNameImportBeanDefinitionRegistrar.class})
public class AppConfig3 { }
-----------------------------------------------
//判断Hello是否托管,如果托管则将Grape托管,并修改beanid
public class FruitNameImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
//registerBeanDefinitions:注册bean的定义
//importingClassMetadata:注解原信息
//BeanDefinitionRegistry:bean的注册项
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//判断Grape是否托管
boolean bean = registry.containsBeanDefinition("com.yc.test1.Hello");
//改beanid
if (bean) {
//bean定义项
RootBeanDefinition d = new RootBeanDefinition(Grape.class);
registry.registerBeanDefinition("grape", d);
}
}
}
4.FactoryBean(1.8.3)
- 使用步骤
1.创建工厂Bean,实现FactoryBean接口
public class OrangeFactoryBean implements FactoryBean<Orange> {
@Override//获取实例
public Orange getObject() throws Exception {
return new Orange();
}
@Override//实例的类型
public Class<?> getObjectType() {
return Orange.class;
}
@Override//是否是单例
public boolean isSingleton() {
return true;
}
}
2.托管工厂Bean
@Configuration
public class AppConfig3 {
@Bean//托管工厂
public FactoryBean<Orange> orangeFactoryBean() {
return new OrangeFactoryBean();
}
}
3.区分
取产品:context.getBean("orangeFactoryBean");
取工厂:context.getBean("&orangeFactoryBean");
5.@Conditional(1.12.5)
- @Conditional(条件类,必须实现Condition接口,实现matches函数,返回true/false表示是否创建该类)
- 加载该类之前进行判断
@Conditional(SystemCondition.class)
@Component
public class Strawberry { }
-----------------------------------------------
public class SystemCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
//判断之前操作系统的类型
Environment env = context.getEnvironment();
String os = env.getProperty("os.name");
if (os.contains("Linux")) {
return true;
}
return false;
//-Dos.name=Linux(VM options) 测试
}
}
注入值到属性中
1.@Value(1.9.8)
- 普通值注入
@Value("oracle.jdbc.driver.OracleDriver")
private String driver;
- spEL注入值,T表示该类
@Value("#{T(java.lang.Runtime).getRuntime().availableProcessors()}")
private int minCons;
@Value("#{T(java.lang.Runtime).getRuntime().availableProcessors()*2}")
private int maxCons;
- 读取属性文件注入
@Value("${db.username}")
private String username;
@Value("${db.password}")//$占位符
private String password;
-----------------------------------------------
@Configuration
@ComponentScan(basePackages = {"com.yc.test4"})
@PropertySource({"classpath:db.properties"})
public class AppConfig4 { }
------------------db.properties----------------
db.username=root
db.password=a
2.@Autowired+@Qualifier/@Primary(1.9.2)
- @Autowired:装配该类的初始值(理解为将该类实例化)
- @Qualifier:明确注入的bean,即分清用哪个实现类,用在属性上
- @Primary:区分相同的bean,指定优先级,用在类上
1.@Autowired+@Qualifier
@Autowired
@Qualifier("custDaoOracleImpl")
private CustDao custDao;
//CustDao是接口,custDaoOracleImpl与custDaoMysqlImpl是其的两个实现类
2.@Autowired+@Primary
@Autowired
private CustDao custDao;
//CustDao是接口,custDaoOracleImpl与custDaoMysqlImpl是其的两个实现类
----------------------------------
@Primary
public class CustDaoOracleImpl implements CustDao {...}
3.@Inject+@Name(1.11.1)
- 注意:单独引入jsr330.jar
- @Inject:类似于@Autowired
- @Name:类似于@Qualifier
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
----------------------------------
@Inject
@Name("custDaoOracleImpl")
private CustDao custDao;
//CustDao是接口,custDaoOracleImpl与custDaoMysqlImpl是其的两个实现类
4.@Resource
- @Resource(name):相当于@Autowired+@Qualifier
@Resource(name = "custDaoOracleImpl")
private CustDao custDao;
5.@Required(安全机制)
- @Required:避免空指针异常,必须要注入,否则报错
private CustDao custDao;
@Required
public void setCustDao(CustDao custDao) {
this.custDao = custDao;
}