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"?>
    
    
        
    
    
  • bean标签的属性:

    • id,唯一标识,
    • class,要创建对象类的全路径,包+类
    • name:和id差不多,属于早期不成熟的一个属性
  • 创建对象时,默认执行的是类的无参构造,所以类必须有无参构造函数

2.3.3注入属性:(DI)

就是依赖注入( DI ) 别别人说DI别不知道是啥

  • 方法1,:使用set方法注入

  • 
    
    	
    	
    
    
  • 方法2:使用有参数构造进行注入

  • 
        
            
        
    
    
  • 方法3:p名称空间注入(不常用)

  • <?xml version="1.0" encoding="UTF-8"?>
    
    
    
        
    
    
  • 注意第4行声明p空间

2.3.4 注入其他类型属性

a.字面量

? 给类的属性设置固定值,就是字面量,

  • null值

    
        
            
            
            
            
                
            
        
    
  • 属性值包含特殊字符

    
    
    
    	
    		>]]>
    	
    
    
    • ? 俩中括号[ [ ] ] ,第一个中括号后面跟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里面的方法

    • 配置文件:

    • 
          
          
      
      
      
      
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;
          }
      }
      
    • 配置文件:

    • 
          
          
      
          
          
              
                  
              
          
      
      
    • 测试类

    • @Test
      public void test1(){
          ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
          Emp emp = context.getBean("emp", Emp.class);
          System.out.println(emp.toString());
      }
      
  • 级联赋值:像有关联的类赋值

    • 配置文件:

    • 
          
          
          
          
      
      
      
    • 其他,emp类中加了一个getDept的方法

2.3.5 xml注入集合属性

a.基本注入方式
  • 待操作类

  • public class Stu {
        private String[] courses;//课程
        //测试List类型的属性
        private List list;
        //测试Map类型的属性
        private Map map;
        //测试set类型的属性
        private Set set;
    
        public void setSet(Set set) {this.set = set;}
        public void setCourses(String[] courses) {this.courses = courses;}
        public void setList(List list) {this.list = list;}
        public void setMap(Map map) {this.map = map;}
    }
    
  • 配置文件

  • 
        
        
            
                java课程
                操作系统
            
        
        
        
            
                工程实践
                la
            
        
    
        
        
            
                
            
        
        
        
            
                张张张
            
        
    
    
b.集合里设置对象类型值
  • 配置文件

  • 
        
    		
            
                
                    
                    
                
            
        
    
        
            
        
        
            
        
    
    
  • Stu类和course类

  • public class Course {
        private String cname;//课程名称
        
        public void setCname(String cname) { this.cname = cname;}
    }
    
  • public class Stu {
        private List courseList;
    
        public void setCourseList(List courseList) { this.courseList = courseList;}
    }
    
c.把集合注入部分提取出公共部分
  • 在spring配置文件中引入名称空间 util

  • <?xml version="1.0" encoding="UTF-8"?>
    
    
  • 多加了一个xmlns:util 同之前p名称的改法,location里面多了两个连接,将原连接里的所有beans改成util

  • 配置文件:

  • 
        
            钢铁是怎样练成的
            降龙十八掌
        
    
    
        
            
        
    
  • Book类

  • public class Book {
        private List list;
        public void setList(List list) {this.list = list;}
    }
    

2.3.6 FactoryBean

  • Spring 有两种类型的bean,一种普通的bean,另外一种就是工厂bean
    • 普通bean:在配置文件中定义bean类型就是返回类型
    • 工厂bean:可以不一样
      1. 创建类,让这个类作为工厂bean,实现接口FactoryBean
      2. 实现接口里面的方法,在实现方法中定义返回的bean类型
public class MyBean implements FactoryBean {
    //定义一下返回的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="singleton">
      
    • 设置成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");
    }
}

配置文件:注意配置了初始化方法和销毁方法


    

测试方法,调用了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实例都添加后置处理


测试方法:

测试的还是用上一个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

    • 配置文件

    • 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包

    
        
        
        
        
    
  • 方法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"?>
        
        
      • 在spring配置文件中使用标签引入外部属性文件

      •