3.3、SpringBean的注入方式
3.3.1、创建对象和set方法注入属性
1. 什么是Bean管理
使用spring创建对象
使用spring注入属性
2. Bean的管理有两种方式
1. 基于XML方式配置
基于XML方式创建对象
<bean id="userEntity" class="com.mayikt.entity.UserEntity"></bean>
在spring的配置文件中,会配置一个bean标签,注入bean的信息 创建bean对象
Id:获取bean对象 唯一bean对象的名称; bean的名称不允许重复
Class属性: 类的完整路径地址(类名称+包名称)
默认底层使用反射技术执行无参数构造函数
2. 基于xml方式注入属性
DI 依赖注入: 对象的属性注入值; (spring实现)
1. 第一种实现方式:基于对象属性set方法实现
<bean id="bookEntity" class="com.mayikt.entity.BookEntity">
<property name="bookName" value="蚂蚁课堂面试宝典"></property>
<property name="bookPrice" value="108.00"></property>
</bean>
在Bean标签下 在定义一个属性<property>标签
Name:类中的属性名称
Value:需要注入属性值
3.3.2、有参构造函数注入属性
实例类
public class OrderEntity {
private String orderId;
private String orderName;
public OrderEntity(String orderId, String orderName) {
this.orderId = orderId;
this.orderName = orderName;
}
@Override
public String toString() {
return "OrderEntity{" +
"orderId='" + orderId + '\'' +
", orderName='" + orderName + '\'' +
'}';
}
}
Xml配置文件
<bean id="orderEntity" class="com.mayikt.entity.OrderEntity">
<!--
<constructor-arg name="orderId" value="123456"></constructor-arg>
<constructor-arg name="orderName" value="来龙虎山学习啦"></constructor-arg>
-->
<constructor-arg index="0" value="123456"></constructor-arg>
<constructor-arg index="1" value="来龙虎山学习啦"></constructor-arg>
</bean>
<constructor-arg name 指定参数列表名称
<constructor-arg index 指定参数列表索引
3.3.3、p名称空间注入
1. Xml头部引入P标签
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"></bean>
2. 使用p标签注入属性:
<bean id="bookEntity" class="com.mayikt.entity.BookEntity" p:bookName="mayikt" p:bookPrice="66">
</bean>
使用p标签为属性注入值:调用set方法注入值
3.3.4、注入空值和特殊符号
注入空值属性
<bean id="bookEntity2" class="com.mayikt.entity.BookEntity">
<property name="bookName" value="mayikt">
</property>
<property name="bookPrice" >
<null></null>
</property>
注入特殊符号
转移注入方式
<< 转移为:<<
>>转移为:>>
<bean id="bookEntity3" class="com.mayikt.entity.BookEntity">
<!-- <property name="bookName" value="<<武汉>>"></property> -->
<property name="bookName" value="<<武汉>>"></property>
<property name="bookPrice">
<null></null>
</property>
</bean>
Cdata注入方式
<![CDATA[<<>>]]>
<bean id="bookEntity4" class="com.mayikt.entity.BookEntity">
<!-- <property name="bookName" value="<<武汉>>"></property> -->
<property name="bookName">
<value><![CDATA[<<武汉>>]]></value>
</property>
<property name="bookPrice">
<null></null>
</property>
</bean>
3.3.5、注入属性外部bean
Com.mayikt.controller—控制层
Com.mayikt.service—-业务逻辑层
MemberService ##new MemberDao().
Com.mayikt.dao—-数据库访问层
MemberDao—-
Com.mayikt.service
调用:memberService
Com.mayikt.dao
MemberDaoImpl
public interface MemberDao {
void addMember();
}
public class MemberDaoImpl implements MemberDao {
public void addMember() {
System.out.println("dao member");
}
}
import com.mayikt.dao.MemberDao;
import com.mayikt.dao.MemberDaoImpl;
public class MemberService {
private MemberDao memberDao;
public MemberDao getMemberDao() {
return memberDao;
}
public void setMemberDao(MemberDao memberDao) {
this.memberDao = memberDao;
}
public void addMember() {
System.out.println("<<<Service Service>>");
// 原始的方式
// MemberDao memberDao = new MemberDaoImpl();
// memberDao.addMember();
memberDao.addMember();
}
}
<?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">
<!--
注入useService
-->
<bean id="memberService" class="com.mayikt.service.MemberService">
<!-- 注入userDao
name 属性值: 类中属性的名称;
ref 创建MemberDaoImpl类的 bean的id
-->
<property name="memberDao" ref="memberDao"></property>
</bean>
<bean id="memberDao" class="com.mayikt.dao.MemberDaoImpl"></bean>
</beans>
3.3.6、注入内部bean
1. 数据库表一对多或者一对一的关系
2. 部门–n多个员工 一对多
3. 站在员工角度考虑员工属于那个部门
4. 站在部门的角度考虑部门下n多个员工
1. 在数据库中表中有一对一一对多的关系;
2. 一对多关系;部门与员工 一个部门会有多个员工 一个员工属于一个部门;
3. 实体类之间表示一对多的关系;
实体类员工对象
public class EmpEntity {
private String name;
private Integer age;
/**
* 员工属于那个部门
*/
private DeptEntity deptEntity;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public void setDeptEntity(DeptEntity deptEntity) {
this.deptEntity = deptEntity;
}
@Override
public String toString() {
return "EmpEntity{" +
"name='" + name + '\'' +
", age=" + age +
", deptEntity=" + deptEntity +
'}';
}
}
部门对象
public class DeptEntity {
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "DeptEntity{" +
"name='" + name + '\'' +
'}';
}
}
Xml相关配置
<!--内部bean -->
<bean id="empEntity" class="com.mayikt.entity.EmpEntity">
<!--设置属性name/age -->
<property name="name" value="mayikt"></property>
<property name="age" value="21"></property>
<!-- 嵌入部门bean-->
<property name="deptEntity">
<bean id="deptEntity" class="com.mayikt.entity.DeptEntity">
<property name="name" value="教育部门"></property>
</bean>
</property>
</bean>
3.3.7、注入级联赋值
写法1
<bean id="empEntity" class="com.mayikt.entity.EmpEntity">
<!--两个属性-->
<property name="name" value="mayikt"></property>
<property name="addres" value="湖北省武汉市"></property>
<!--级联赋值-->
<property name="deptEntity" ref="deptEntity"></property>
</bean>
<bean id="deptEntity" class="com.mayikt.entity.DeptEntity">
<property name="name" value="教育部门"></property>
</bean>
写法2
<bean id="empEntity" class="com.mayikt.entity.EmpEntity">
<!--两个属性-->
<property name="name" value="mayikt"></property>
<property name="addres" value="湖北省武汉市"></property>
<!--级联赋值-->
<property name="deptEntity" ref="deptEntity"></property>
<property name="deptEntity.name" value="教育部门"></property>
</bean>
<bean id="deptEntity" class="com.mayikt.entity.DeptEntity">
</bean>
注意:需要在员工实体类新增:deptEntity get方法。
3.3.8、注入集合类型属性
1. 注入数组类型
2. 注入list集合类型
3. 注入Map集合类型属性
4. 注入set集合属性
实体类
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class StuEntity {
//1.数组属性
private String[] arrays;
//2.list集合属性
private List<String> list;
//3.Map
private Map<String,String> map;
//4.Set
private Set<String> set;
public void setArrays(String[] arrays) {
this.arrays = arrays;
}
public void setList(List<String> list) {
this.list = list;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public void setSet(Set<String> set) {
this.set = set;
}
@Override
public String toString() {
return "StuEntity{" +
"arrays=" + Arrays.toString(arrays) +
", list=" + list +
", map=" + map +
", set=" + set +
'}';
}
}
配置文件
<bean id="stuEntity" class="com.mayikt.entity.StuEntity">
<!--数组类型注入-->
<property name="arrays">
<array>
<value>mayikt01</value>
<value>mayikt02</value>
</array>
</property>
<!--list-->
<property name="list">
<list>
<value>语文</value>
<value>数学</value>
</list>
</property>
<!--Map-->
<property name="map">
<map>
<entry key="张三丰" value="23"></entry>
<entry key="小薇" value="25"></entry>
</map>
</property>
<!--Set-->
<property name="Set">
<set>
<value>01</value>
<value>02</value>
</set>
</property>
</bean>
集合类型为对象
private List<CourseEntity> courses;
public void setCourses(List<CourseEntity> courses) {
this.courses = courses;
}
public class CourseEntity {
private String name;
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "CourseEntity{" +
"name='" + name + '\'' +
'}';
}
}
<?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="stuEntity" class="com.mayikt.entity.StuEntity">
<!--对我们的list属性赋值-->
<property name="list">
<list>
<value>list01</value>
<value>list02</value>
</list>
</property>
<!--对我们的arrays属性赋值-->
<property name="arrays">
<array>
<value>mayikt01</value>
<value>mayikt02</value>
</array>
</property>
<!--对我们的map属性赋值-->
<property name="map">
<map>
<entry key="mayikt" value="张三丰"></entry>
<entry key="xiaowei" value="小薇"></entry>
</map>
</property>
<!--对我们的set属性赋值-->
<property name="set">
<set>
<value>list01</value>
<value>list02</value>
</set>
</property>
<property name="courses" >
<list>
<ref bean="courseEntity1"></ref>
集合注入部分提取公共
1. 需要先引入一个util名称空间
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
2. 使用util标签 注入
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
<!-- 提取公共部分-->
<util:list id="list">
<value>mayikt01</value>
<value>mayikt02</value>
</util:list>
<bean id="stuEntity" class="com.mayikt.entity.StuEntity">
<property name="list" ref="list"></property>
</bean>
</beans>
3.3.9、IOC操作Bean的管理
1. Spring中两种类型bean,一种是为普通的bean,另外一种是工厂bean
FactoryBean
2. 普通Bean:在配置文件中定义什么类型与返回的类型需一致;
3. 工厂Bean:在配置文件中定义Bean类型与返回类型可以不一致;
创建一个类,这个类是为工厂Bean,实现FactoryBean接口
import com.mayikt.entity.UserEntity;
import org.springframework.beans.factory.FactoryBean;
public class MayiktBean implements FactoryBean<UserEntity> {
/**
* 定义返回bean
*
* @return
* @throws Exception
*/
public UserEntity getObject() throws Exception {
return new UserEntity();
}
public Class<?> getObjectType() {
return null;
}
}
public static void main(String[] args) {
ClassPathXmlApplicationContext app =
new ClassPathXmlApplicationContext("spring_08.xml");
UserEntity mayiktBean = (UserEntity) app.getBean("mayiktBean");
System.out.println(mayiktBean);
}
3.4、Spring的工厂Bean
3.4.1、SpringBean的作用域
什么是作用域?
设定bean作用域是为单例还是多例
作用域单例与多例有什么区别呢?
1. 单例的作用域:每次在调用getbean方法获取对象都是为同一个对象;
2. 多例的作用域:每次在调用getbean方法获取对象都是一个
新的对象。
注意:在spring默认的情况下,bean的作用域就是为单例 节约服务器内存。
单例:
在同一个jvm中,该bean对象只会创建一次。
多例:
在同一个jvm中,该bean对象可以被创建多次。
设定对象单例还是多例
在spring的默认的情况下,springbean的作用域为单例。
1.单例就是每次获取bean都是同一个对象;
2.多例就是每次获取bean都是新的一个对象;
单例:在同一个jvm中该bean只能存在一个实例;
多例子:在同一个jvm中该bean存在多个实例;
证明:如果是为单例,则两个对象地址都是一样的,
多例子对象则两个对象地址不一样。
单例配置:
<bean id="userEntity" class="com.mayikt.entity.UserEntity" scope="singleton"></bean>
默认就是为单例子;
多例配置:
<bean id="userEntity" class="com.mayikt.entity.UserEntity" scope="prototype"></bean>
3.4.2、SpringBean的生命周期
简单分为:实例化→属性赋值→初始化→销毁
生命周期概念:
1. 对象的创建与销毁的过程,类似之前学习servlet生命的周期过程。
生命周期的原理:
1. 通过构造函数创建bean对象(默认执行无参构造函数 底层基于反射实现)
2. 为bean的属性设置 (使用反射调用set方法)
3. 调用bean的初始化的方法(需要单独在类中配置初始化的方法)
4. 正常使用bean对象
5. Spring容器关闭,调用该类的销毁回调的方法(需要单独在类中配置销毁的方法)
public class MemberEntity {
private String name;
public MemberEntity(){
System.out.println("[第一步]-无参构造函数被执行---反射机制调用");
}
public void setName(String name) {
System.out.println("[第二步]-set方法初始化属性---反射机制调用");
this.name = name;
}
/**
* 回调调用init初始化方法
*/
public void initMethod(){
System.out.println("[第三步]-回调调用init初始化方法");
}
/**
* destroyMethod
*/
public void destroyMethod(){
System.out.println("[第五步]-回调调用destroyMethod方法");
}
}
<bean id="memberEntity" class="com.mayikt.entity.MemberEntity" init-method="initMethod" destroy-method="destroyMethod">
<property name="name" value="mayikt"></property>
</bean>
<bean id="mayiktBeanPost" class="com.mayikt.bean.MayiktBeanPost"></bean>
import com.mayikt.entity.MemberEntity;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test07 {
public static void main(String[] args) {
ClassPathXmlApplicationContext app =
new ClassPathXmlApplicationContext("spring_07.xml");
MemberEntity memberEntity= app.getBean("memberEntity",MemberEntity.class);
System.out.println("[第四步]-获取使用到的memberEntity");
System.out.println(memberEntity);
// 手动让bean容器销毁
app.close();
}
}
Bean的后置处理器 作用提供更多的扩展功能 BeanPostProcessor
相关演示代码
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class MayiktBeanPost implements BeanPostProcessor {
/**
* 调用初始化方法之前执行
* @param bean
* @param beanName
* @return
* @throws BeansException
*/
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("在bean 初始化方法之前执行");
return bean;
}
/**
* 调用初始化方法之后执行
* @param bean
* @param beanName
* @return
* @throws BeansException
*/
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("在bean 初始化方法之后执行");
return bean;
}
}
<bean id="mayiktBeanPost" class="com.mayikt.bean.MayiktBeanPost"></bean>
1.通过构造函数创建bean对象(默认执行无参构造函数 底层基于反射实现)
2.为bean的属性设置 (使用反射调用set方法)
3.将bean传递给后置处理器 调用初始化方法之前执行
4.调用bean的初始化的方法(需要单独在类中配置初始化的方法)
5.将bean传递给后置处理器 调用初始化方法之后执行
6.正常使用bean对象
7.Spring容器关闭,调用该类的销毁回调的方法(需要单独在类中配置销毁的方法)
后置处理器底层原理
配置多个BeanPostProcessor
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.Ordered;
public class MayiktBeanPost implements BeanPostProcessor, Ordered {
/**
* 调用初始化方法之前执行
* @param bean
* @param beanName
* @return
* @throws BeansException
*/
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("调用该bean的 init方法之前");
return bean;
}
/**
* 调用初始化方法之后执行
* @param bean
* @param beanName
* @return
* @throws BeansException
*/
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("调用该bean的 init方法之后");
return bean;
}
public int getOrder() {
return 1;
}
}
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.Ordered;
public class MayiktBeanPost02 implements BeanPostProcessor, Ordered {
/**
* 调用初始化方法之前执行
* @param bean
* @param beanName
* @return
* @throws BeansException
*/
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("[MayiktBeanPost02:]调用该bean的 init方法之前");
return bean;
}
/**
* 调用初始化方法之后执行
* @param bean
* @param beanName
* @return
* @throws BeansException
*/
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("[MayiktBeanPost02:]调用该bean的 init方法之后");
return bean;
}
public int getOrder() {
return 0;
}
}
<!-- 后置处理器-->
<bean id="mayiktBeanPost" class="com.mayikt.bean.MayiktBeanPost"></bean>
<bean id="mayiktBeanPost02" class="com.mayikt.bean.MayiktBeanPost02"></bean>
实现Ordered接口 getOrder 值越小越优先加载
3.4.3、SpringBean的自动装配
什么是自动装配呢
根据装配的规则(属性的名称或者属性的类型)
Spring根据装配的规则自动为属性注入值。
1. 什么是自动装配
A. 根据指定装配规则(属性名称或者属性的类型),spring自动将匹配属性的值注入。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
<!-- spring ioc <bean id="empEntity" class="com.mayikt.entity.EmpEntity">
<property name="deptEntity" ref="deptEntity"></property>
</bean> -->
<!-- bean 标签中有一个属性autowire
1.根据属性的名称注入 bean的id名称与属性的名称一致
2.根据属性的类型注入 bean的类型与属性类型一致
-->
<bean id="empEntity" class="com.mayikt.entity.EmpEntity" autowire="byType">
</bean>
<bean id="deptEntity" class="com.mayikt.entity.DeptEntity">
<property name="name" value="教育部门"></property>
</bean>
</beans>
3.4.4、SpringBean的外部属性文件
3.5、SpringBean的注解形式
3.5.1、Spring的注解启动方式
Bean的管理操作方式
1. 基于XML方式实现
2. 基于注解方式实现
什么是注解:注解是JDK5中推出的新特性,代码的特殊标记,
格式注解名称“属性名称=属性值,属性名称=属性值”。
我们在后期学习springboot开发基本上都是使用注解,很少在使用
Xml配置的方式。
注解可以使用在类、方法、属性、上面。
使用注解的目的,简化xml的配置方式。
Spring提供的常用注解
1. @Component 将对象注入Spring容器中
2. @Service 注入业务逻辑对象
3. @Controller 控制器类
4. @Repository 注入dao对象
5. 以上该四个注解底层都是基于@Component注解封装的,只是区分用于
在不同的场景下。
注解的使用方式
AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext();
app.register(BeanConfig.class);
app.refresh();
MemberEntity memberEntity = (MemberEntity) app.getBean("memberEntity");
System.out.println(memberEntity);
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/111825.html