初识Spring--工厂模式、IOC、Bean的生命周期、依赖注入
Spring
Spring是分层的 Java SE/EE应用 full-stack 轻量级开源框架,以 IoC(Inverse Of Control:反转控制)和 AOP(Aspect Oriented Programming:面向切面编程)为内核。
Spring的优势
-
方便解耦,简化开发(IOC)
Spring就是一个大工厂,可以将所有的对象的创建和依赖关系进行维护。
-
AOP编程支持
spring提供面向切面编程,主要方便进行权限拦截,和事务管理,进行监控行为。
-
声明式事务管理
只需要写简单的配置完成事务管理,不需要写代码
-
方便程序测试
Spring对Junit4的支持,可以通过注解完成Spring程序的测试
-
方便集成各个优秀的框架
SSM整合(Spring+SpringMVC+MyBatis)
-
降低JAVAEE API的难度
JDBC模板
Spring体系架构
IOC
spring IOC底层原理: 工厂模式、配置文件、反射
1、导入 Spring 开发的jar包
今天主要用到了Beans、Core、Context、 SpEL所需要的核心容器jar包和ogging依赖。
2、创建 applicationContext.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="studentBean" class="com.yunhe.JavaBean.Student">
<property name="name" value="wang"></property>
<property name="age" value="18"></property>
<!--依赖注入-->
<property name="teacher" ref="teacherBean"></property>
</bean>
<bean id="teacherBean" class="com.yunhe.JavaBean.Teacher">
<property name="name" value="zhang"></property>
<property name="tid" value="99"></property>
</bean>
<!--通过静态工厂获取实例对象-->
<bean id="studentFactory" class="com.yunhe.factory.StudentFactory" factory-method="getStudent">
</bean>
<!--通过实例工厂获取实例对象-->
<bean id="studentFactory2" class="com.yunhe.factory.StudentFactory2"></bean>
<bean id="studentStand" factory-bean="studentFactory2" factory-method="getStudent"></bean>
<!--通过标准工厂获取实例对象-->
<!--配置标准工厂类 Spring会自动执行标准工厂类的getObject()方法-->
<bean id="studentFactoryStand" class="com.yunhe.factory.StudentFactoryStand"></bean>
</beans>
3、创建实体类
4、创建工厂类
静态工厂类
public class StudentFactory {
public static Student getStudent(){
Student student = new Student();
student.setName("静态工厂");
student.setAge(20);
return student;
}
}
标准工厂类
实现FactoryBean<?>接口,重写方法,标准统一工厂接口,如getObject()方法
//实现FactoryBean<?>接口,重写方法,标准统一工厂接口,如getObject()方法
public class StudentFactoryStand implements FactoryBean<Student> {
@Override
public Student getObject() throws Exception {
Student student = new Student();
student.setName("标准工厂");
student.setAge(20);
return student;
}
@Override
public Class<?> getObjectType() {
return null;
}
@Override
public boolean isSingleton() {
return false;
}
}
5、使用 Spring 的 API 获得 Bean 实例
public class Main {
public static void main(String[] args) {
//使用spring对指定类进行管理后获取指定对象
//通过配置 将对象设置的名字与全路径名进行配置
//使用相应工具类进行加载配置文件获取交由spring管理的所有类的信息
//通过getBean 传入要获取对象的对应的id获取指定对象
//强转为需要使用的对象 调用相应方法
//加载配置文件
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//Bean实例化三种方式
//使用无参构造方法实例化
Student s = (User) ac.getBean(Student.class);//通过xml文件中的class进行匹配
Student s = (Student) ac.getBean("studentBean"); //通过xml文件中的唯一标识符id进行匹配
//通过静态工厂获取实例对象
Student s = (Student) ac.getBean("studentFactory");
//通过实例工厂获取实例对象
Student s = (Student) ac.getBean("studentStand");
//通过标准工厂获取实例对象
Student s = (Student) ac.getBean("studentFactoryStand");
System.out.println(s);
}
}
实现原理:
1. 加载配置文件,解析文件
2. 读取bean节点的id和class
3. 获取到当前id对应class,可以使用反射机制(Class.forName(“类名”).newInstance()–>得到实例对象(默认调用无参数构造方法))
4. 读取property节点,读取name值,获取value值;(反射(invoke)调用setName(setAge())进行赋值)
5. 提供一个getBean方法()
Spring IOC/DI
IOC控制反转Inversion of Control
把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是松散耦合,这样也方便测试,利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。
DI依赖注入Dependency Injection
在程序运行期间由容器动态的将某个依赖关系注入到组件之中
简单可以理解为:
ioc负责对象在容器的创建销毁初始化,di负责存值
Bean
Bean的作用范围
作用域 | 描述 |
---|---|
singleton | 在spring IOC容器中仅存在一个Bean实例,Bean以单例方式存在,默认值 |
prototype | 每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时,相当于执行new Bean() |
request | 每次HTTP请求都会创建一个新的Bean,该作用域仅适用于WebApplicationContext环境 |
session | 同一个HTTP Session共享一个Bean,不同Session使用不同的Bean,该作用域仅适用于WebApplicationContext环境 |
global-session | 一般用于Portlet应用环境,该作用域仅适用于WebApplicationContext环境 |
scope="prototype"
Bean的生命周期
在指定的Bean类中书写对应的初始化和销毁方法
public void init(){
System.out.println("Student实例对象初始化");
}
public void destory(){
System.out.println("Student实例对象销毁");
}
在bean标签中配置指定类初始化方法与销毁方法,Spring会在Bean的生命周期中自动调用
init-method="init"
destroy-method="destory"
单例模式创建的bean会随着spring的关闭自动调用销毁方法
applicationContext.close();
<bean id="studentBean" class="com.yunhe.JavaBean.Student" scope="prototype" init-method="init" destroy-method="destory">
<property name="name" value="wang"></property>
<property name="age" value="18"></property>
<property name="teacher" ref="teacherBean"></property>
</bean>
后处理器Bean
package com.yh;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
/*
bnena生命周期---后处理器Bean
作用:将当前spring容器中的所有其他bean的初始化前后监控。(对象初始化前后做功能增强)
*/
public class MyBeanPostProcessor implements BeanPostProcessor {
//初始化之前方法
@Override
public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
System.out.println("初始化之前"+o+" "+s);
//o为初始化对象 s是Bean的id
return o;
}
//初始化之后方法
@Override
public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
System.out.println("初始化之后"+o+" "+s);
return o;
}
}
配置
<!--不需要配置id,因为这个bean我们不需要,spring容器需要-->
<bean class="com.yh.MyBeanPostProcessor"></bean>
Bean的依赖注入
有参的构造方法方式
<!--依赖注入:有参的构造方法-->
<bean id="studentYL" class="com.yunhe.JavaBean.Student">
<!--
index 为构造方法参数的序号
或者可以通过属性名name=“"name",name=”“"age"
-->
<constructor-arg index="0" value="依赖注入"></constructor-arg>
<constructor-arg index="1" value="18" ></constructor-arg>
<constructor-arg index="2" ref="teacherBean"></constructor-arg>
</bean>
P命名空间依赖注入
<!--p命名空间配置信息-->
xmlns:p="http://www.springframework.org/schema/p"
配置Bean
<!--依赖注入:P命名空间-->
<bean id="studentP" class="com.yunhe.JavaBean.Student" p:name="P命名空间" p:age="18">
</bean>
测试
Student s = (Student) ac.getBean("studentP");//P命名空间依赖注入
System.out.println(s);
集合数据的注入
public class Person {
private List<String> names;
private Set<Teacher> teacherSet;
private HashMap<String,Integer> map;
private Properties ps;
<bean id="p1" class="com.yh.Person">
<property name="names">
<list>
<value>jack</value>
<value>rose</value>
</list>
</property>
<property name="teacherSet">
<set>
<ref bean="teahcer1"></ref>
</set>
</property>
<property name="map">
<map>
<entry key="张三" value="13">
</entry>
<entry key="里斯" value="35">
</entry>
</map>
</property>
<property name="ps">
<props>
<prop key="rul">www.baidu.com</prop>
<prop key="user">root</prop>
</props>
</property>
</bean>