IOC/DI

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;
}

IOC/DI源码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值