spring基础02-IOC容器2-基于xml操作bean管理
2.3 IOC操作Bean管理(基于XML)
2.3.1 什么是Bean管理
- 
Bean管理指的是两个操作 - 
Spring创建对象 
- 
Spring注入 
 
- 
2.3.2 创建对象
- 
用maven创建的项目,xml配置文件放在了resources文件夹下,可以直接classpath定位到 
- 
<?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"> <!-- 配置User对象的创建--> <bean id="user" class="com.zhang.User"></bean> </beans>
- 
bean标签的属性: - id,唯一标识,
- class,要创建对象类的全路径,包+类
- name:和id差不多,属于早期不成熟的一个属性
 
- 
创建对象时,默认执行的是类的无参构造,所以类必须有无参构造函数 
2.3.3注入属性:(DI)
就是依赖注入( DI ) 别别人说DI别不知道是啥
- 
方法1,:使用set方法注入 
- 
<!-- set方法注入属性--> <bean id="book" class="com.zhang.Book"> <!--在bean标签中使用property完成属性注入 name :类里面的属性名称 value:向里面注入的值 --> <property name="bname" value="java从入门到放弃"></property> </bean>
- 
方法2:使用有参数构造进行注入 
- 
<!-- 3.有参构造创建带属性的对象--> <bean id="book1" class="com.zhang.Book"> <constructor-arg name="bname" value="php是最好的编程语言"></constructor-arg> </bean>
- 
方法3: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"> <!-- 4.是引用p命名空间注入--> <bean id="book2" class="com.zhang.Book" p:bname="Spring5冲刺50w"></bean> </beans>
- 
注意第4行声明p空间 
2.3.4 注入其他类型属性
a.字面量
 给类的属性设置固定值,就是字面量,
- 
null值 <!-- set方法注入属性--> <bean id="book" class="com.zhang.Book"> <!--在bean标签中使用property完成属性注入 name :类里面的属性名称 value:向里面注入的值 --> <property name="bname" value="java从入门到放弃"></property> <!--向属性中注入空值--> <property name="address"> <null/> </property> </bean>
- 
属性值包含特殊字符 <!--向属性中注入特殊符号--> <!-- <property name="author" value="<<张>>"></property>这个写法是错的,可能把字符串里面的<>识别为xml结构体 --> <property name="author" > <value> <![CDATA[<<张>>]]> </value> </property>-  俩中括号[ [ ] ] ,第一个中括号后面跟CDATA,第二个中括号里面写具体内容
 
b.注入属性-外部bean
- 
创建service类和dao类 
- 
Dao类 
- 
public interface dao { public void getUser(); }public class MyDao implements dao{ @Override public void getUser() { System.out.println("获取user"); } }
- 
Service类 
- 
public class MyServices { private MyDao myDao; public void setMyDao(MyDao myDao) { this.myDao = myDao; } public void add(){ System.out.println("service add"); myDao.getUser();//调用dao } }
- 
在service里面调用dao里面的方法 - 
配置文件: 
- 
<bean id="myServices" class="com.zhang.service.MyServices"> <!--注入属性 name:属性名字 ref:类类型的属性值--> <property name="myDao" ref="myDao"></property> </bean> <bean id="myDao" class="com.zhang.dao.MyDao"></bean>
 
- 
c.注入属性-内部bean和级联属性
- 
一对多关系:部门&员工 - 
部门类和员工类 
- 
public class Emp { private String ename;//员工姓名 private String gender;//性别 private Dept dept; public void setDept(Dept dept) {this.dept = dept;} public void setEname(String ename) { this.ename = ename;} public void setGender(String gender) {this.gender = gender;} }
- 
public class Dept { private String danme; public void setDanme(String danme) { this.danme = danme; } }
- 
配置文件: 
- 
<bean id="emp" class="com.zhang.bean.Emp"> <property name="ename" value="张大壮"></property> <property name="gender" value="汉子"></property> <!--设置对象类型属性--> <property name="dept"> <bean id="dept" class="com.zhang.bean.Dept"> <property name="danme" value="安保部门"></property> </bean> </property> </bean>
- 
测试类 
- 
@Test public void test1(){ ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml"); Emp emp = context.getBean("emp", Emp.class); System.out.println(emp.toString()); }
 
- 
- 
级联赋值:像有关联的类赋值 - 
配置文件: 
- 
<bean id="emp" class="com.zhang.bean.Emp"> <property name="ename" value="张大壮"></property> <property name="gender" value="汉子"></property> <property name="dept" ref="dept"></property> <property name="dept.dname" value="后勤部"></property> </bean> <bean id="dept" class="com.zhang.bean.Dept"></bean>
- 
其他,emp类中加了一个getDept的方法 
 
- 
2.3.5 xml注入集合属性
a.基本注入方式
- 
待操作类 
- 
public class Stu { private String[] courses;//课程 //测试List类型的属性 private List<String> list; //测试Map类型的属性 private Map<String,String > map; //测试set类型的属性 private Set<String> set; public void setSet(Set<String> set) {this.set = set;} public void setCourses(String[] courses) {this.courses = courses;} public void setList(List<String> list) {this.list = list;} public void setMap(Map<String, String> map) {this.map = map;} }
- 
配置文件 
- 
<bean id="stu" class="collection.Stu"> <!-- 数组类型属性注入 用list或者array都可以--> <property name="courses"> <array> <value>java课程</value> <value>操作系统</value> </array> </property> <!-- List类型属性 --> <property name="list"> <list> <value>工程实践</value> <value>la</value> </list> </property> <!--map类型--> <property name="map"> <map> <entry key="JAVA" value="java"></entry> </map> </property> <!--set类型--> <property name="set"> <set> <value>张张张</value> </set> </property> </bean>
b.集合里设置对象类型值
- 
配置文件 
- 
<beans> <bean id="stu" class="collection.Stu"> <!-- 注入list集合类型,值是对象--> <property name="courseList"> <list> <ref bean="java"></ref> <ref bean="database"></ref> </list> </property> </bean> <bean id="java" class="collection.Course"> <property name="cname" value="java"></property> </bean> <bean id="database" class="collection.Course"> <property name="cname" value="database"></property> </bean> </beans>
- 
Stu类和course类 
- 
public class Course { private String cname;//课程名称 public void setCname(String cname) { this.cname = cname;} }
- 
public class Stu { private List<Course> courseList; public void setCourseList(List<Course> courseList) { this.courseList = courseList;} }
c.把集合注入部分提取出公共部分
- 
在spring配置文件中引入名称空间 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">
- 
多加了一个xmlns:util 同之前p名称的改法,location里面多了两个连接,将原连接里的所有beans改成util 
- 
配置文件: 
- 
<!--提取list集合类型属性注入--> <util:list id="bookList"> <value>钢铁是怎样练成的</value> <value>降龙十八掌</value> </util:list> <!-- 使用--> <bean id="book" class="collection.Book"> <property name="list" ref="bookList"></property> </bean>
- 
Book类 
- 
public class Book { private List<String> list; public void setList(List<String> list) {this.list = list;} }
2.3.6 FactoryBean
- Spring 有两种类型的bean,一种普通的bean,另外一种就是工厂bean
- 普通bean:在配置文件中定义bean类型就是返回类型
- 工厂bean:可以不一样
- 创建类,让这个类作为工厂bean,实现接口FactoryBean
- 实现接口里面的方法,在实现方法中定义返回的bean类型
 
 
public class MyBean implements FactoryBean<Course> {
    //定义一下返回的bean的类型
    @Override
    public Course getObject() throws Exception {
        Course course = new Course();
        course.setCname("英语");
        return course;
    }
    @Override
    public Class<?> getObjectType() {
        return null;
    }
    @Override
    public boolean isSingleton() {
        return FactoryBean.super.isSingleton();
    }
}
测试类:
public void test2(){
    ApplicationContext context = new ClassPathXmlApplicationContext("bean-factorybean.xml");
    Course course = context.getBean("mybean", Course.class);
    System.out.println(course);
}
2.3.7 bean作用域
- 
在spring里,设置创建的bean实例是单实例还是多实例 
- 
在spring里面,默认情况下创建的bean是一个单实例情况 - 可以多次context.getbean() ,但是拿出来的对象hashcode都是一个
 
- 
设置: - 
spring配置文件的bean标签里可以设置scope属性 
- 
<bean id="book" class="collection.Book" scope="prototype"></bean><!--多实例--> bean id="book" class="collection.Book" scope="singleton"></bean><!--单实例:默认的-->
- 
设置成singleton时,加载spring配置文件时就会创建单实例对象 
- 
设置成prototype时,在调用getBean方法时才创建对象 
 
- 
2.3.8 bean声明周期
- 一个对象从创建到对象销毁的过程
- bean的声明周期
- 第一步:通过构造器创建bean实例(无参构造)
- 第二步:为bean的属性设置值和对其他bean引用(调用set方法)
- (后置处理器)把bean的实例传给bean后置处理器的方法postProcessBeforeInitialization
- 第三步:调用bean的初始化方法(需要进行配置)
- (后置处理器)把bean的实例传给bean后置处理器的方法postProcessAfterInitialization
- 第四步:bean可以使用了
- 第五步:当容器关闭的时候,调用bean的销毁的方法(需要进行配置销毁的方法)
 
bean类:
public class Order {
    private String oname;
    public void setOname(String oname) {
        this.oname = oname;
        System.out.println("第二步,set方法设置值");
    }
    public Order() {
        System.out.println("第一步,无参构造");
    }
    //创建执行初始化的方法
    public void initMethod(){
        System.out.println("第三部,初始化方法");
    }
    public void destroyMethod(){
        System.out.println("第五步,销毁bean");
    }
}
配置文件:注意配置了初始化方法和销毁方法
<bean id="orders" class="bean.Order" init-method="initMethod" destroy-method="destroyMethod">
    <property name="oname"  value="手机"></property>
</bean>
测试方法,调用了context的close方法
注意:ApplicationContext是个接口,没有close方法, 得强转成new 的ClassPathXmlApplicationContext类型,或者把context声明成这个类型
@Test
public void test3(){
    ApplicationContext context = new ClassPathXmlApplicationContext("bean-factorybean.xml");
    Order orders = context.getBean("orders", Order.class);
    System.out.println("第四步,获取创建bean实例对象");
    System.out.println(orders);
    ((ClassPathXmlApplicationContext)context).close();
}
- bean的后置处理器
- 创建类,实现BeanPostProcessor,创建后置处理器
 
public class PostProcess implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("执行后置处理方法1");
        return bean;
    }
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("执行后置处理方法2");
        return bean;
    }
}
配置文件:
他会为这个配置文件下的每一个bean实例都添加后置处理
<bean id="postprocess" class="bean.PostProcess"></bean>
测试方法:
测试的还是用上一个Order实例
@Test
public void test3(){
    ApplicationContext context = new ClassPathXmlApplicationContext("bean-factorybean.xml");
    Order orders = context.getBean("orders", Order.class);
    System.out.println("第四步,获取创建bean实例对象");
    System.out.println(orders);
    ((ClassPathXmlApplicationContext)context).close();
}

2.3.2.9 xml自动装配(一键白学)
- 
啥是手动装配 - 就是在配置文件里通过value和ref设置每个属性的值
 
- 
根据指定装配规则(属性名称或者属性类型)Spring自动将匹配的属性进行注入 - F---K,有这玩意前面十几节学他干毛
 
- 
根据名称byName - 
配置文件 
- 
![image]() 
- 
bean类 
- 
public class Emp { private Dept dept; public void setDept(Dept dept) {this.dept = dept;} @Override public String toString() {return "Emp{" +"dept=" + dept +'}';} }
- 
public class Dept { @Override public String toString() { return "Dept{}";} }
- 
测试类测试Emp的创建,略 
 
- 
- 
根据类型:byType - 就是去你的配置文件里面找到合适的类型的bean注入,但是注意,必须要保证唯一
- 比如上面例子要是声明了俩 class="Dept"的bean就不好使了,就必须使用byName了
 

2.3.10 外部属性文件
把一些常用的固定的值,放在一个外部文件中,然后导入xml配置文件
就好像把常量抽取出来组成一个常量类一样
- 方法1:直接配置数据库信息
- 配置德鲁伊连接池
- 引入依赖jar包
 
<!--    直接配置连接池-->
    <bean id="druid" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306"></property>
        <property name="username" value="root"></property>
        <property name="password" value="072432"></property>
    </bean>
- 
方法2:引入外部属性文件配置数据库连接池 - 
创建外部属性文件,jdbc.properties 
- 
prop.driverClassName=com.mysql.jdbc.Driver prop.url=jdbc:mysql://localhost:3306 prop.username=root prop.password=072432
- 
把外部properties属性文件引入到spring配置文件中 - 
引入名称空间context,方法同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:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
- 
在spring配置文件中使用标签引入外部属性文件 
- 
<context:property-placeholder location="jdbc.properties"/> 
- 
<!-- 使用外部属性文件--> <context:property-placeholder location="jdbc.properties"/> <bean id="druid" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="${prop.driverClassName}"></property> <property name="url" value="${prop.url}"></property> <property name="username" value="${prop.username}"></property> <property name="password" value="${prop.password}"></property> </bean>
 
- 
 
- 
本文来自博客园,作者:荧惑微光,转载请注明原文链接:https://www.cnblogs.com/yinghuoweiguang/p/16019002.html
 
                    
                
 

 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号