学习spring之前,先要了解什么是spring,简单理解就是,spring是一个分层的JavaSE框架。
WEB层 | SpringMVC |
---|---|
service层 | Spring的Bean管理,Spring声明式事务 |
DAO层 | spring的JDBC模板 |
IOC控制反转是一种设计理念,不是一种设计技术,是由代理人来创建和管理对象,消费者通过代理人来获取对象。IOC的目的就是降低对象之间的直接耦合。
控制反转:将对象的创建权反转给Spring
下图解释:
将苹果采购,创建的权力由最原始的消费者转嫁给了代理人。 顾客需要什么样的苹果,只需要找果商要就行。
IOC是一种设计理念,与语言无关。但是放在某一种语言下该如何实现IOC呢?这里就需要依赖注入(DI)。DI在Java中利用反射技术实现对象注入。
Spring官网:(国外网)
https://spring.io/
因为对象之间往往存在引用关系,而这些对象都是new出来的,程序难以扩展维护。
IOC容器是Spring生态的地基,用于统一创建与管理依赖。
将A的依赖B注入到A中,这里的注入主要是靠反射技术实现的。
在Java文件夹下创建两个实体类:apple 和Child
分别编写类的属性,并设置geter和seter;
为了方便对象实例化,为其书写带参的构造方法。
测试结果:
这样写存在的问题:
苹果的信息是固定的,属性变化后,就需要修改程序的源代码。如果有了新苹果,就需要new新的对象,这样的程序,健壮性是差的。
注入依赖
创建一个applicationContext.xml配置文件
这个操作就是让idea知道该工程是spring,并且idea为spring提供了一系列的优化。
其XML文件的内容头为schema约束。
<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
https://www.springframework.org/schema/beans/spring-beans.xsd">
在ioc容器启动时,自动由Spring实例化Apple对象,取名为sweetApple放入容器中
<bean id="sweetApple" class="com.imooc.spring.ioc.entity.Apple">
bean>
使用上述这种方式的优点就是,只需要更改配置文件的内容即可,源代码文件不需要做任何调整。
编写测试类:
学习到这里,大概就算入门Spring IOC啦(你可拉到吧!!!)
继承:
Class A{
}
Class B extends A{
}
- <bean id="lily" class="com.imooc.spring.ioc.entity.Child">
<property name="name" value="莉莉">property>
<property name="apple" ref="softApple">property>
bean>
创建ApplicationContext对象,该对象有很多实现类,其中最主要的是ClassPathXmlApplicationContext。
ClassPathXmlApplicationContext(“classpath:applicationContext.xml”)实现了从当前内路径读取指定XML文件,并解析加载。
工厂:隐藏创建类的细节,通过额外的工厂类来组织创建我们需要的对象。
bean id与name都是设置对象在ioc容器中的唯一标识。
两者在同一配置文件中都不允许出现重复。
两者允许在多个配置文件中出现重复,新对象覆盖旧对象。
如何在spring Ioc容器中注入对象的依赖关系。
上面已经学会使用IOC容器实现单个对象的实例化。
child对象要依赖于apple,方法就是由ioc容器先单独创建出Child和apple,来动态的进行依赖的注入。
这里的依赖注入就是将两个对象关联起来。
下面代码只能通过构造方法来进行赋值,没有书写set方法。
com.gx.spring.demo.Car
public class Car {
private String name;
private Double price;
public Car(String name, Double price) {
super();
this.name = name;
this.price = price;
}
@Override
public String toString() {
return "Car [name=" + name + ", price=" + price + "]";
}
}
构造方法的属性注入
constructor-arg 标签用于配置构造方法的属性注入
name :参数的名称
value:设置普通数据
ref:引用数据,一般是另一个bean id值
<!-- 构造方法的方式 -->
<bean id="car" class="com.gx.spring.demo.Car">
<constructor-arg name="name" value="玛莎拉蒂"/>
<constructor-arg name="price" value="800000"/>
</bean>
利用setter实现静态数据的注入
Set方法的普通属性注入
property 标签用于配置Set方法的属性注入
name :参数的名称
value:设置普通数据
ref:引用数据,一般是另一个bean id值
只需要下面这句话就能从xml配置文件中提取对象。
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
通过这段代码直接提取配置文件中sweetapple对应id的内容。
Apple sweetApple = context.getBean("sweetApple", Apple.class);
使用注解仍然要创建XML文件,原因是一些基础的配置仍然要在xml文件下写,但是这里的schema配置与之前的有一点不同(具体代码去官网找)
<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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
beans>
Spring的注解开发:组件扫描(不使用类上注解的时候可以不用组件扫描)
使用注解方式,需要开启组件扫描< context:component-scan base-package=直接包名或者包名.类名/>,当然开发中一般都是base-package=包名,毕竟这样可以扫描整个包,方便开发
Spring 的注解开发:组件扫描(类上注解: 可以直接使用属性注入的注解)
<context:component-scan base-package="com.imooc"/>
在创建的对象上面写上@Autowrite注解。测试发现set方法没有执行,也就是对象属性没有注入。
把@Autowired写在set方法上面。IOC容器会自动按类型进行注入,而把@Autowired放在属性上面则不会执行set方法。
为某一个属性设置静态属性