Spring–bean实例化的三种方式:
- 构造器实例化
- 静态工厂实例化
- 实例工厂实例化
静态工厂实例化:
1、创建对应的静态实例工厂
public class StaticFactoryBean {
public static Student createStudent(){
Student student=new Student();
// 荣国数据库获取最新的数据 id name 再set值
// 假装
student.setStudentId(90);
student.setStudentName("练习");
return student;
}
}
2、去做对应的配置文件:
<?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="student" class="com.aaa.Factory.StaticFactoryBean" factory-method="createStudent"></bean>
其中,id为一个bean的唯一标识符,Sqring对bean的配置和管理都通过该属性来完成 ;
name :同样可以通过此属性对容器中的bean进行配置和管理。name属性可以为bean指定多个名称。每个名称之间用,或者;隔开。
class: 该属性指定了bean的具体实现类,他必须是一个完整的类名,使用类的全限定名。
scope:用来设定bean实例的作用域:其属性值有:singleton(单例)
</beans>
然后就可以对其进行测试:
public static void main(String[] args) {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("classpath:Factory/StaticFactory.xml");
Student student= (Student) applicationContext.getBean("student");
System.out.println("student = " + student);
}
实例工厂实例化
1、创建实例工厂
public class BeanFactory {
public BeanFactory(){
System.out.println("本实例工厂被实例化");
}
public Student createStudent(){
return new Student(98,"实例工厂");
}
}
2、去做对应的配置文件:
实例工厂,字如其名,必须要有实例才可以进行获取bean
<?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="factoryBean" class="com.aaa.Factory.BeanFactory"> </bean>
<!--调用实例工厂-->
<!-- 当初始化bean 时数据如果时动态的,选哟通过网络或者数据获取,可以通过静态工厂,实例工厂 创建对象
目的能够让容器更加灵活的的创建bean
factory-bean="normalFactory" 指向实例工厂
factory-method="createStudent" 执行创建bean的方法
-->
<bean id="studentBean" factory-bean="factoryBean" factory-method="createStudent" ></bean>
</beans>
bean的作用域:
- singleton
singleton是Spring容器默认的作用域,当Bean的作用域为singleton时,Spring容器就只会存在一个共享的Bean实例。singleton作用域对于无会话状态的Bean(如Dao 组件、Service组件)来说,是最理想的选择。
- xml的配置:其实也没啥配置的,就是一个关键字而已:scope关键字
当这个关键字为prototype的时候就是原型,当为sington的时候就是单例
<bean id="student" name="xiaowei,xiaoweiwei" class="com.aaa.Entity.Student" scope="prototype">
<property name="studentId" value="001"></property>
<property name="studentName" value="小薇"></property>
</bean>
bean的生命周期
Spring容器可以管理Bean部分作用域的生命周期。有关说明具体如下
- singleton
Spring容器可以管理singleton作用域的Bean的生命周期,在此作用域下,Spring能够精确的知道该Bean何时被创建,何时初始化完成,以及何时被销毁。
- prototype
prototype作用域的Bean,Spring只负责创建,当容器创建了Bean实例后,Bean的实例就交给客户端代码来管理,Spring容器将不再跟踪其生命周期。交给jvm销毁和管理
示例:
首先你想要知道一个bean什么时候被创建和销毁你一定要重写init和destroy方法。
- 在实体类中增加:
public void init(){
System.out.println("student被创建了");
}
public void destroy(){
System.out.println("student被销毁了");
}
在xml的对应bean中配置对应的方法:
<bean id="student" class="com.aaa.Entity.Student" scope="prototype" init-method="init" destroy-method="destroy">
</bean>
<bean id="student1" class="com.aaa.Entity.Student" scope="singleton" init-method="init" destroy-method="destroy">
</bean>
然后测试:需要注意的是:ApplicationContext接口没有destory方法,ClassPathXmlApplicationContext有destory方法。
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:life/bean1.xml");
// 调用容器的销毁方法 触发bean 的销毁
// 原型模式: 容器只负责创建(什么时候获取什么时候创建),不负责管理和销毁(交给jvm 销毁)
// 单利模式: 容器负责创建(当容器加载完毕就会创建,获取时时是从 容器的 singletonObject Map()) ,还负责管理和销毁
applicationContext.destroy();
bean的装配:
基于xml的装配
- 看一下实体的属性:
public class Student {
private int studentId;
private List crouseList;
private String studentName;
}
- 设值注入
使用的是setter方法注入,必备的条件就是:bean类必须有一个无参构造方法,bean类必须为属性提供setter方法
<bean id="student" class="com.aaa.Entity.Student" >
<property name="studentName" value="xml自动装配"/>
<property name="studentId" value="23"/>
<property name="crouseList">
<list>
<value>34</value>
<value>"listxml装配"</value>
</list>
</property>
</bean>
- 构造方法注入
xml书写如下:
<bean id="student2" class="com.aaa.Entity.Student">
<constructor-arg index="0" value="89" ></constructor-arg>
<constructor-arg index="1" >
<list>
<value>34</value>
<value>"xml构造方法装配"</value>
</list>
</constructor-arg>
<constructor-arg index="2" value="构造方法装配" ></constructor-arg>
</bean>
基于Annotation(注解)的装配
上述的xml注入有一个严重的问题就是太过于臃肿。所以spring提供了基于注解的装配方式
注解类型有三种:
@Autowired: 用于对Bean 的属性变量、属性的setter方法及构造方法进行标注,配合对应的注解处理器完成Bean的自动配置工作。
@Qualifier:与@Autowired注解配合使用,会将默认的按Bean类型装配修改为按Bean的实例名称装配。Bean的实例名称由@Qualifier注解的参数指定。
@Resource: 其作用和AutoWired一样,它中有两个重要的属性:name和type。Spring将name属性解析为Bean实例名称type属性解析为Bean实例类型。
半自动装配 annotation-config
需要在xml文件内创建实体,但是可以不用配置依赖注入的关系。依赖注入关系在对应的调用实体里边用注解的方式声明:
看xml:用自动注入注解的话一定要带上激活注解的标签才可以生效
<!-- 激活 自动注入的注解 @Autowired @Qualifier @Resources -->
<context:annotation-config></context:annotation-config>
<!-- 声明一个 studnetDao 接口对应的实现类的实例-->
<bean id="StudentDaoImpl1" class="com.aaa.Dao.impl.StudentDaoImpl"></bean>
<bean id="StudentDaoImpl2" class="com.aaa.Dao.impl.StudentDaoImpl"></bean>
<!-- 依赖注入 容器会自动给你创建对应的实例并且进行组装-->
<!-- 声明一个StudnetSerImpl实现类 并且通过 <property name="studentDao3" ref= 根据id获取已经声明的bean -->
<bean id="StudentSerImpl2" class="com.aaa.Service.Impl.StudentSerImpl">
</bean>
调用实体内的注解配置:
//需要容器注入一个studentdao类型的bean
/* @Autowired //按照类型将容器中的studentdao的bean注入,如果找到多个报错,需要Qualifer进行区别
@Qualifier("StudentDaoImpl2") // @Autowired 和 @Qualifier相互配合,根据id获取注入bean*/
/*
@Resource 默认情况 // 首先按照注解的变量名作为id去找容器对应的bean,找不到再按照类型去匹配
*/
@Resource(name = "StudentDaoImpl2") // 按照配置的name对应的id去查找;
StudentDao studentDao;
自动 注解装配 context:component-scan
扫描 当前包下面的注解@Component @Controller @Service @Repository,生成实例,并装配 @Autowired @Resource
只要配置就会生成对应的实例。其实自动注解装配和半自动注解装配最大的区别就是,自动注解你需要给各个层级的类配置类的注解,这样,开启全自动注解之后,你就可以不在xml文件里边书写bean标签来自己配置bean,而是由全自动注解自动去扫苗你配置的page下边所有带由CCSR注解的类,并且自动生成对应的bean,但是他们之间的依赖注入关系还是需要你自己用@Autowired @Resource来自己实现。
xml配置:
<!--开启全自动配置的注解 扫面base-package 下边所有 注解 @Component @Controller @Service @Repository,
生成实例,并装配 @Autowired @Qualifier @Resource -->
<context:component-scan base-package="com.aaa"/>
去对应的实体类里边配置注解:
依赖注解:
@Resource(name = "studentDao") // 按照配置的name对应的id去查找;
StudentDao studentDao;
基于xml的自动装配
所谓自动装配,就是将一个Bean自动的注入到到其他Bean的Property中。 Spring的元素中包含一个autowire属性,我们可以通过设置autowire的属性值来自动装配Bean。autowire属性有5个值,其值及说明下表所示:是用来进行依赖注入的。
<bean id="studentDao" class="com.aaa.Dao.impl.StudentDaoImpl" ></bean>
<!--
bytype:利用类型自动匹配 ,如果有多个同等类型的bean,则会报错
byName:按照id(实体类中需要注入的变量名)自动匹配,
constructor:必须有构造函数
-->
<bean id="StudentSerImpl2" autowire="byName" class="com.aaa.Service.Impl.StudentSerImpl">
</bean>
总结
控制反转:具体的意思就是将对象的创建过程交给spring的容器来完成,开发者不参与对象。
依赖注入:将各个类之间的依赖关系通过xml或者注解的方式来完成,而不用开发者手动书写。
所谓实例工厂和静态工厂就是是否需要一个实体bean来进行调用方法;
bean的作用域常用的有singlton(单例)和prototype(原型)模式,
如果是前者的话,呢么一直引用的就是一个bean,这个bean由容器创建,并且掌管他的生命周期。随着容器的消失而销毁。
bean的装配
bean的装配方式有很多。首先我们看看值的注入,由xml的值装配,xml的构造方法注入。
然后就是依赖的注入方式:
1、根据 @Autowired @Qualifier @Resource进行声明注入。(这个要在具体的实现类的变量里边。
2、在xml里边用auto-wire进行注入;
还有就是自动装配:
1、使用一个标签,然后可以自己不去书写bean,使用@Controller和@Service等进行声明实体。