Spring-框架之IOC
Spring框架
1.Spring简单介绍
在介绍IOC之前我们先介绍一下Spring框架:
简单来说:Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器(框架)
Spring:优点
- 轻量级:大小完整的spring框架可以在只有1M多点的AR文件发布,开销也是微不足道的。Spring是非侵入式的:Spring应用中的对象不依赖于Spring的特定类。
- 、Spring是一个开源免费的框架 , 容器 .
- 控制反转 IoC , 面向切面 Aop
- 对事物的支持 , 对框架的支持
1.IOC介绍
1.1.IOC的概念
- IOC的概念:IOC控制反转他是一种程序设计思想。Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。
- 反转的解释:反转则是由容器来帮忙创建及注入依赖对象:由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转,依赖对象的获取被反转了。
1.2.IOC的用处
Ioc的主要作用是:解耦
解耦即降低代码耦合度,也就是减少代码之间的依赖,就是A功能的代码不要写在B的功能代码中,这样修改一处的代码会影响其他很多的代码。
1.3.依赖注入Dl
di依赖注入,是IOC另一种说法,也就是对象由容器来管理,注入到我们需要依赖中。
2.IOC容器
2.1 IOC的容器的概念
包org.springframework.beans和org.springframework.context是Spring框架的IoC容器的基础。BeanFactory接口提供了一个先进的配置机制能够管理任何类型的对象。ApplicationContext是BeanFactory的一个子接口。它增加了与Spring AOP特征的更加简单的集成;消息资源处理(用于国际化中),事件发布和应用层特定的上下文例如用于Web应用中的 WebApplicationContext。
也就是说BeanFactory提供了配置框架和基本功能。ApplicationContext是BeanFactory的一个完备的超级并继承了BeanFactory,添加了更多的企业特定的功能,例如从一个属性文件中解析文本信息的能力,发布应用程序事件给感兴趣的事件监听器的能力。
ApplicationContext接口的主要实现:
- FileSystemXmlApplicationContext
基于文件系统中XML文件配置的应用程序上下文 - ClassPathXmlApplicationContext
基于ClassPath路径中XML文件配置的应用程序上下文 - AnnotationConfigApplicationConext
基于注解配置的应用程序上下文
Ioc的实现方式
配置版
1.导入依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.8.RELEASE</version>
2.编写代码
/** * CPU接口
*/
public interface Cpu {
void run();
}
//实现接口
public class AMDCpu implements Cpu {
public void run() {
System.out.println("AMD的CPU在运行。。。");
}
}
public class IntelCpu implements Cpu {
public void run() {
System.out.println("英特尔CPU在运行。。。");
}
}
/**内存 */
public interface Memory { void read(); void write();}
public class KingstonMemory implements Memory {
public void read() {
System.out.println("金士顿内存读取数据");
}
public void write() {
System.out.println("金士顿内存写入数据");
}
}
public class SumsungMemory implements Memory {
public void read() {
System.out.println("三星内存读取数据");
}
public void write() {
System.out.println("三星内存写入数据");
}
}
//编写电脑类/**
* 电脑
*/
public class Computer {
private String brand;
private Cpu cpu;
private Memory memory;
public Cpu getCpu() {
return cpu;
}
public void setCpu(Cpu cpu) {
this.cpu = cpu;
}
public Memory getMemory() {
return memory;
}
public void setMemory(Memory memory) {
this.memory = memory;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public void start(){
System.out.println(brand + "电脑启动了!");
cpu.run();
memory.read();
memory.write();
}
}
3.添加配置文件
<?xml version="1.0" encoding="UTF-8"?><beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="cpu" class="com.blb.ioc_demo.AMDCpu"></bean>
<bean id="memory" class="com.blb.ioc_demo.KingstonMemory"></bean>
<!-- Java对象配置-->
<bean id="computer" class="com.blb.ioc_demo.Computer">
<property name="brand" value="联想"></property>
<property name="cpu" ref="cpu">
</property>
<property name="memory" ref="memory"></property> </bean>
</beans>
注解配置版
1. 重要注解
-
- @Component 组件,被标记的类会被Spring扫描到,交给Spring容器进行管理
-
@ComponentScan 组件扫描,标记在配置类上,用于扫描某一个包下带@Component的类
-
@Configuration 配置类,标记在类上,该类作为配置类代替XML
-
@Value 注入值类型数据,配置属性或set方法上
-
@Autowried 自动装配,默认按类型进行注入
-
@Qualifier 标记名称,配置在类和注入属性上,用于区分类型相同的对象
-
@Resource 自动装配,类似Autowired,默认按名称注入,名称没有再按类型注入
-
@Repository 类似@Component,标记DAO实现类
-
@Service 类似@Component,标记Service实现类
-
@Controller 类似@Component,标记Controller类
修改上面的案例,给每个接口的一个实现类加上@Component注解
/**
-
配置类
*/
@ComponentScan(basePackages = “com.blb.ioc_demo”)
@Configuration
public class ComputerConfig {public static void main(String[] args) {
//创建注解应用程序上下文
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ComputerConfig.class);
//获得对象
Computer computer = context.getBean(Computer.class);
computer.start();
}
}
iOC的实现原理
通过自定义注解+反射机制实现的
代码如下所示:
public class ComputerFactory {
/**
* 创建电脑对象
* @param computerClass
* @return
*/
public Computer createComputer(Class computerClass) throws Exception {
//反射创建对象
Object computer = computerClass.newInstance();
//遍历所有的属性
Field[] fields = computerClass.getDeclaredFields();
for(Field field : fields){
String fName = field.getName();
//读取自定义注解
MyValue myValue = field.getDeclaredAnnotation(MyValue.class);
if(myValue != null){
//通过反射调用set方法注入值
String mName = "set" + fName.substring(0,1).toUpperCase() + fName.substring(1);
Method set = computerClass.getDeclaredMethod(mName, field.getType());
set.invoke(computer,myValue.value());
}
MyComponent myComponent = field.getDeclaredAnnotation(MyComponent.class);
if(myComponent != null){
//通过反射调用set方法注入对象
String mName = "set" + fName.substring(0,1).toUpperCase() + fName.substring(1);
Method set = computerClass.getDeclaredMethod(mName, field.getType());
//通过配置的类型创建对象
Object obj = myComponent.value().newInstance();
set.invoke(computer,obj);
}
}
return (Computer) computer;
}
}