Spring基础
重要概念:
- IOC(Inversion of control):控制反转,控制的是对象的创建,把对象的创建方式进行了反转。
- DI(Dependency Injection):依赖注入,即组件之间的依赖关系由容器在运行期决定,由容器动态地将某种依赖关系注入到组件当中,对对象的属性进行注入。
- 没有IOC就没有DI。
- AOP(Aspect Oriented Programming):面向切面
一.Spring介绍
类图
注:ClassPathApplicationContext:他只能加载类路径下的配置文件。
FileSystemXmlApplicationContext:它可以加载磁盘任意位置的配置文件。
二.Spring的优点
- 方便解耦,简化开发
Srping是一个大工厂(容器),可以将所有对象的创建和依赖维护关系交给Spring管理。 - AOP编程的支持
Spring提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能。 - 声明式事务的支持
只需要配置就可以完成对事务的管理,而无须手动编程。 - 方便程序的测试
Spring对Junit4支持,可以通过注解方便的测试Spring程序。 - 方便集成各种优秀框架
Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts、Hibernate、MyBatis、Quartz等)的直接支持。 - 降低JavaEE API的使用难度
Spring 对JavaEE开发中非常难用的一些API(JDBC、JavaMail、远程调用等),都提供了封装,使这些API应用难度大大降低。
(mysql事务,隔离级别,传播行为
三.Spring入门实例
1、 创建Java项目。
2、 导入所需Jar包。
3.、在项目新建applicationContext.xml配置文件,放在src的lib下面。
Spring/spring-framework-4.2.4.RELEASE/docs/spring-framework-reference/html/xsd-configuration.html
applicationContext.xml配置文件注意:
bean标签中的Id(也可用name,尽量用id,否则在同一个文件中会出错)为操作接口名,class为实际操作类的完整路径名(包名+类名)。
4、在此处有实例。
5、我自己实现的实例。
注意:此处getBean得到的为Object对象,需要强转为操作接口的对象。ClassPathXmlApplicatipnContext。
6、configurableApplicationContext:让AllicationContext具有刷新(refresh())和关闭(close())功能,是AllicationContext的扩展。
7、使用Spring的IOC进行有参构造方法的对象的实例化
(1)在使用带参数的构造器创建对象时,在中添加且该标签中的name属性必须与对应的实体类中的属性名相同。
(2)引用对象
(3)引用了List集合,name属性要与对象的属性的变量名相同。
四.关于Bean
- Bean的生命周期
(1)Spring对Bean进行实例化
(2)Spring将值和Bean的引用注入Bean对应的属性中。
(3)如果Bean实现了BeanNameAware接口,Spring将Bean的ID传递给setBeanName()接口方法。
(4)如果Bean实现了BeanFactoryAware接口,Spring将调用setBeanFactory()接口方法,将BeanFactory容器实例传入。
(5)如果Bean实现了ApplicationContextAware接口,Spring将调用setApplicationContext接口方法,将应用上下文的引用传入。
(6) 如果Bean实现了BeanPostProcessor接口,Spring将调用它们的postProcessBeforeInitialization()接口方法。
(7) 如果Bean实现了InitializingBean接口,Spring将调用它们的afterPropertiesSet()接口方法。类似地,如果Bean使用init-method声明了初始化方法,该方法也会被调用。
(8) 如果Bean实现了BeanPostProcessor接口,Spring将调用它们的post-PoressAfterInitialization()方法。
(9) 此时此刻,Bean已经准备就绪,可以被应用程序使用了,它们将一直驻留在应用上下文中,直到应用上下文被销毁。
(10) 如果Bean实现了DisposableBean接口,Spring将调用它的destory()接口方法。同样,如果Bean使用destory-method声明了销毁方法,该方法也会被调用。 - Bean创建的两种规则以及三种方式以及Bean的作用范围
(1)Bean创建的两种规则
所需jar包:
BeanFactory:提供的是一种延迟加载思想来创建Bean对象,Bean对象什么时候用什么时候创建。代码如下:
@Test
public void test(){
ClassPathResource resource = new ClassPathResource("beans.xml");
BeanFactory factory = new XmlBeanFactory(resource);
ICustomerService customerService = (ICustomerService) factory.getBean("ICustomerServiceImp");
customerService.saveCustomer();
}
执行结果:
ApplcationContext:提供的时一种立即加载思想创建Bean对象。只要一解析完配置文件,就立马创建Bean对象。代码如下:
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
ICustomerService customerService = (ICustomerService) context.getBean("InstanceCustomerService");
customerService.saveCustomer();
}
执行结果:
xml配置文件如下:
<?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="ICustomerServiceImp" class="com.renjing.service.imp.ICustomerServiceImp">
</bean>
</beans>
ICustomerServiceImp类如下:
//客户的业务层实现类
public class ICustomerServiceImp implements ICustomerService {
public ICustomerServiceImp() {
System.out.println("bean对象被创建了");
}
@Override
public void saveCustomer() {
System.out.println("业务层调用持久层");
}
}
(2)Bean的三种创建方式
① 调用默认无参构造函数创建(用的最多)。
默认情况下,如果类中没有默认无参数构造函数,则创建失败,会报异常。
② 调用静态工厂中的方法创建对象。
需要使用Bean标签的factory-method属性,指定静态工厂中创建对象的方法。
代码如下:
<!--使用静态工厂创建对象-->
<bean id="staticCustomerService" class="com.renjing.factory.StaticFactory" factory-method="getCustomerService"></bean>
③ 使用实例工厂的方法创建。
<!--使用实例工厂创建对象-->
<bean id="InstanceFactory" class="com.renjing.factory.InstanceFactory"></bean>
<bean id="InstanceCustomerService" factory-bean="InstanceFactory" class="com.renjing.factory.InstanceFactory" factory-method="getCustomerService"></bean>
(3)Bean的作用范围
① 他是可以通过配置的方式来调整作用范围。
② 配置的属性:Bean标签的Scope属性。
③ 属性的取值:
Singleton:单例的(默认值)。
xml文件中默认为单例:
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
ICustomerService customerService = (ICustomerService) context.getBean("ICustomerServiceImp");
ICustomerService customerService2 = (ICustomerService) context.getBean("ICustomerServiceImp");
customerService.saveCustomer();
System.out.println(customerService==customerService2);
}
执行结果:
Prototype:多例的(当我们让Spring接管struts的action创建时,action必须配置此值)。
将Bean对象中的scope属性设置为“Prototype”后,
<bean id="ICustomerServiceImp" class="com.renjing.service.imp.ICustomerServiceImp" scope="prototype">
执行结果:
Request:作用范围是一次请求和当前请求的转发。
Session:作用范围时一次会话。
Globalsession:作用范围是一次全局会话。
(4)Bean的生命周期
ICustomeRService的实现类ICustomeRServiceImp:
//客户的业务层实现类
public class ICustomerServiceImp implements ICustomerService {
public ICustomerServiceImp() {
System.out.println("bean对象被创建了");
}
public void init(){
System.out.println("对象创建");
}
public void destory(){
System.out.println("对象销毁");
}
@Override
public void saveCustomer() {
System.out.println("业务层调用持久层");
}
}
xml配置文件:
<!--使用无参构造创建对象,并设置初始化和销毁的方法-->
<bean id="ICustomerServiceImp" class="com.renjing.service.imp.ICustomerServiceImp" scope="singleton" init-method="init" destroy-method="destory">
mian函数:
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
ICustomerService customerService = (ICustomerService) context.getBean("ICustomerServiceImp");
customerService.saveCustomer();
}
执行结果:
此时,我们只能看到对象的创建,原因在于:线程运行的时候,先将Main函数压栈,等到其他函数弹栈完毕后,Main函数才会弹栈,然后线程上所占用的内存才会被全部释放。还没有调用销毁方法,内存已经全部被释放,故而看不到对象的销毁。
修改代码如下:
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
ICustomerService customerService = (ICustomerService) context.getBean("ICustomerServiceImp");
customerService.saveCustomer();
context.close();
}
执行结果:
① 涉及Bean标签的两个属性:
Init-method
Destory-method
② 单例:
出生:容器创建,对象出生。
活着:只要容器在,对象就一直在。
死亡:容器销毁,对象消亡。
③ 多例:
出生:每次使用时,创建对象。
活着:只要对象在使用中,就一直活着。
死亡:当对象长时间不使用,并且也没有别的对象引用时,由java的垃圾回收器回收。