什么是IOC?
控制反转,Inversion Of Controller;
是面向对象编程中的一种设计原则,可以减少计算机代码之间的耦合度;
控制反转的二要素
控制什么
反转什么
IOC实现的两种方式
依赖注入
依赖查找
什么是Spring IOC?
Spring根据IOC思想在Java语言中的一种实现;
一种容器,用来管理bean的创建与销毁,以及bean之间的依赖关系;
控制什么?
控制的是Bean的创建以及销毁,以及依赖关系
将设计好的对象交由容器控制,而不是传统的在对象内部直接控制
反转什么?
反转的是Bean的控制权(创建,销毁,依赖),
将控制权交给了容器;
什么是DI?
依赖注入,Dependency Injection;
就是A.class中有B.class的属性;
注入的四种方式:
接口注入(Interface Injection)
Spring早期版本使用
setter注入(setter Injection)
通过setter方法注入属性
构造注入(Constructor Injection)
通过构造方法注入属性
名称空间注入
Spring中的一种实现注入的方式,依赖于setter注入或者构造注入
依赖于setter注入的实现时P名称空间注入
依赖于构造注入的实现是C名称空间注入
Spring管理Bean的三种方式
XML
通xml配置文件管理Bean
注解
通XML配合使用,在xml配置文件中开启注解扫描
<context:component-scan package="com" /> //指定扫描的包,该配置自动开启注解,即可以省略配置<context:annotation-config/>
使用@Component,@Repository,@Service,@Controller等注解注册Bean
@Repository //注册Bean public class IndexDao { public void query(){ System.out.println("query"); } }
Java Configuration
与xml,注解配合使用
@Configuration //声名为配置类 @ComponentScan("com") //指定扫面的包 @ImportResource("classpath:spring.xml") //指定配置文件 public class AppConfig { }
Spring初始化容器的三种方式
根据类路径xml配置文件初始化容器
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("xml-path");
根据Java Configuration配置类初始化容器
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
根据外部xml配置文件初始化容器
FileSystemXmlApplicationContextcontext = new FileSystemXmlApplicationContext("xml-path");
Spring 自动装配
XML自动装配
配置全局自动装配,配置default-autowire属性
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd" default-autowire="byName"> </beans>
配置单个Bean自动装配,配置autowire属性
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="com.luban" name-generator="com.luban.config.MyNameGenerator"></context:component-scan> <bean id="dao" class="com.luban.dao.impl.IndexDaoImpl" autowire="byName"></bean> </beans>
autowire属性值
default : 不使用自动转配
no : 不使用自动装配
byType : 通过类型自动装配
byName : 通过名字自动装配
constructor : 通过构造方法参数类型自动装配
注解自动装配
@Autowire 按照类型自动装配
@Qualifier 与@Autowire配合使用,按照名称自动装配
@Resource
按照名称自动装配,没有匹配到时,按照类型进行装配
指定名称时,使用指定的名称装配,
没有指定名称时,看注解作用在属性上还是setter方法上
注解作用在属性上时,按照属性名称装配
注解作用在setter方法上时,按照set后的名称首字母小写进行装配
自动装配引发的问题
同一类型有两个实现类时,不知该装配那个实现类的问题?
解决办法
1.按照名称进行装配
2.在某一实现类上添加@Primary注解,优先装配该实现类
Spring中Bean名称的生成策略
默认的生成策略
使用xml注册Bean
有id时,Bean名称默认与id一致,
无id时,默认使用类名首字母小写作为Bean名称
使用注解注册Bean
显式的指定Bean名称
不指定时,默认采用类名首字母小写作为Bean名称
修改Bean名称的生成策略
自定义Bean名称生成策略类
两种实现方式
方式一:继承AnnotationBeanNameGenerator,重写buildDefaultBeanName(BeanDefinition definition)方法
public class MyNameGenerator extends AnnotationBeanNameGenerator { @Override protected String buildDefaultBeanName(BeanDefinition definition) { return definition.getBeanClassName(); } }
方式二:实现BeanNameGenerator实现generateBeanName(BeanDefinition var1, BeanDefinitionRegistry var2)方法
public class MyNameGenerator1 implements BeanNameGenerator { @Override public String generateBeanName(BeanDefinition beanDefinition, BeanDefinitionRegistry beanDefinitionRegistry) { return beanDefinition.getBeanClassName(); } }
使用自定义Bean名称生成策略类
xml方式:name-generator属性
<context:component-scan base-package="com.luban" name-generator="com.config.MyNameGenerator"></context:component-scan>
注解方式:@ComponentScan注解中的nameGenerator属性
@Configuration @ComponentScan(value = "com",nameGenerator=MyNameGenerator.class) public class SpringConfig { }
Spring中循环引用问题
bean的作用域都是Singleton,可以循环引用
bean的作用域都是Prototype,不可以循环引用,会抛出异常
循环引用会造成一直有引用保持者,导致不能被gc回收.新型gc算法产生
Spring Profile
主要解决生产环境与测试环境配置不一致时频繁修改配置文件的问题
切换配置文件类
在配件文件类上添加@Profile注解,并声明profileName
@Configuration @Profile("pro") @ComponentScan(value = "com",nameGenerator=MyNameGenerator.class) public class SpringConfig { }
切换不同的实现Bean
在Bean上使用注解@Profile
@Repository @Profile("pro") public class IndexDaoImpl implements IndexDao { @Override public void hello() { System.out.println("================================"); } }
初始化容器时指定Profile
public class App { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.getEnvironment().setActiveProfiles("pro"); //设置生效的profileName context.register(SpringConfig.class); //注册配置文件 context.refresh(); //刷新IOC容器,使设置生效 } }