Spring目前来说最主要的作用:
降低组件与组件之间的关联,便于系统的维护和拓展
系统----忽然要添加新的功能模块 /修改
MVC
大堤---防洪水----蚂蚁---啃了一口---大堤毁坏
Spring的核心思想便是IoC和AOP
IOC全程Inverse of Control ---控制反转
我们在程序过程中经常遇到的一个场景是类与类之间的创建使用,我们可以称之为控制权
例如类A与类B 在A中调用B,这个时候理所当然的要在类A中需要创建类B。这就是我们所说的耦合
因为修改类B类A也要进行修改。
DAO userDao--jdbc/myBatis
Service 调用userDao
那我们怎么解决这个问题呢?Spring采用了IoC使代码对Spring的依赖减少
在Spring框架中,这个控制权由Spring容器来控制,要在一个类中使用另外一个类,我们不去手动创建类了,只需要
由Spring容器配置文件进行注入就可以了
AOP---Aspect Oriented Programming大名鼎鼎的面向切面编程
目的是通过预编译方式和运行期动态代理,在不修改源代码的情况下给程序添加功能
案例01演示:
我们采用jdbc编写的代码需要使用mybatis来替换了,这时候怎么办呢?改代码
高级版本-采用接口让jdbc和MyBatis分别实现,在用接口。
最终版本,采用spring来实现它
案例1结束
回顾刚才我们的代码,在最后我们需要使用的时候,首先通过Spring容器来实例化我们的类这时候用了一句话
ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
其实在我们容器在实例化的时候,我们有两种方式来加载Spring配置对象
ApplicationContext 和BeanFactory
使用BeanFactory的方法
Resource resource=new ClassPathResource("applicationContext.xml");
BeanFactory factory=new XmlBeanFactory(resource);
在激活Spting应用中,应用组件是在spring内激活的。容器可以创建组件,装配和配置组件以及管理它的生命周期。
spring框架的核心是容器。spring提供了多种容器实现,并分为两大类:
1Bean工厂是最简单的容器,提供了基础的依赖注入支持。org.springframework.beans.factory.BeanFactory接口定义
应用上下文ApplicationContext org.springframework.context.ApplictionContext提供。它建立在Bean工厂基础之上。拥有比bean工厂更强大的功能
AbstractApplicationContext
---补充-------------------------------------------------------------------------------------------------------------------------------------
生命周期问题
Bean对象一般是随着容器的启动而产生的---(想一下啥时候容器启动的)
1:Spring实例化bean
2:Spring注入bean的属性
3:Spring设置bean的名字
4:初始化
6:预处理
7:bean准备完毕可以使用
8:销毁bean
这里有个属性lazy-init="true"---这种方式呢,就可以让我们的bean对象,在真正需要使用的时候采取产生
那我们的bean是以什么模式来创建的呢?
UserService service=(UserService) context.getBean("UserService");
UserService service2=(UserService) context.getBean("UserService");
System.out.println(service==service2);//这是的值
默认情况下,是单例创建--singleton (比较好一点。全局只有一个),但是在某些情况下,我们不需要单例创建对象,那怎么办?
我们只需要指定bean的scope范围是prototype就可以每次都获取到一个新的bean了
还有几个属性不过与web相关
bean常用属性还有两个
init-method和destroy-method
最后当我们的容器关闭的时候,bean对象销毁
IOC--控制反转 刚才我们注入值 依赖注入
基础部分结束
--------------------------------------------------
关于bean配置
我们刚才的案例通过属性传递了参数
<property name="" ref=""></property>---这个方式
<constructor-arg name="dao" ref="MyBatisDao"></constructor-arg>----这种方式来传递参数
其实刚才我们在配置文件中将一个类注入到另外一个类的方式就是我们的DI-也可以称呼为依赖注入
它采取的就是我们刚才采用的两种方式setter属性注入和constructor构造函数注入
IOC和DI密不可分 spring---IOC---DI
实验1:如果不给set属性,我们刚才的实验还能正常使用吗?
实验2采取构造器的方式
----------------------------思考,什么时候使用set什么时候使用构造器模式呢?
问题?如果需要传递多个参数怎么搞?
在构造函数中我们可以使用下标的方式
<constructor-arg index="0" ref="MyBatisDao"></constructor-arg>
<constructor-arg index="1" value="zhangsan"></constructor-arg>
如果是set的方式我们就可以配置多个property来做这个事情
当然我们的spring还可以支持注入更多的东西
1:list--最常用的
<property name="要注入集和的名字">
<list>
<value>zhangsan</value>
<value>李四</value>
</list>
</property>
2:set
<property name="names">
<set>
<value>zhangsan</value>
<value>李四</value>
</set>
</property>
3:Map
<property name="maps">
<map>
<entry key="cd" value="成都"></entry>
<entry key="bj" value="北京"></entry>
</map>
</property>
4:配置文件
<property name="properties">
<props>
<prop key="userName">root</prop>
<prop key="userPwd">admin</prop>
</props>
</property>
关于自动装配:
四种类型自动装配
byName byType constructor autodetect
案例01
<bean id="empDao" class="com.wode.test.EmpDao"></bean>
<bean id="empService" class="com.wode.test.EmpService" autowire="byName">-----在程序中private empDao---会自动去找bean中的empDao
</bean>
案例02byType类似于name但是他是根据属性类型来自动寻找相关的bean
代码和上边一样,但是如果有多个类是这个类型的实现类,属性都一样,这就报错了
案例03
constructor 当设置为他的时候,我们需要提供构造器,当多个bean自动匹配,spring就不去猜测哪个bean能自动装配
案例04autodetect
这个很厉害,spring先从构造函数一直往下猜测到底谁能装配进去
自动装配---少用
关于抽象
案例:新建动物类,和两个子类dog和cat
<bean id="animal" class="com.wode.test.Animal" abstract="true">
<property name="name" value="动物"></property>
<property name="age" value="1"></property>
</bean>
<bean id="dog" class="com.wode.test.Dog" parent="animal"></bean>---这里的parent就指派了它的父类
<bean id="cat" class="com.wode.test.Cat" parent="animal"></bean>
怎么复写属性呢?
直接给bean dog中写入属性就可以了
福利:
注解的使用方式
支持注解的主要jar是我们的context这个jar包
<context:component-scan base-package="com.wode">
</context:component-scan>
使用:
@Repository代表用于dao层的组件
@Service代表用于service层的组件
@Controller代表Action层的组件
@Component代表表示其他的组件
当我们需要的时候,我们采用@Resource获取
注意,如果不加任何参数,则id于当前的类名保持一致
实验1测试(注意点,自动生成id名字的时候,类名的变换)
实验2:自己修改id名字
-----------------------------------------------------------------------------------------------------------------------------------
@Resource--先按照类型,再按照名字来匹配---演示错误
在获取的时候,我们还可以通过别的方式获取
@Autowired---这种方式是自动去找想匹配的,找到了自动注入进来
同样存在上边的问题,使用@Qualifier("idName")来解决
@Scope
@PostConstruct--init
@PreDestroy--Destroy
@PostConstruct
public void init(){
}