spring4-1-基础bean的配置

一.概念

1.轻量级开源框架;
2.简化企业级应用而生;
3.是一个IOC(DI)依赖注入和AOP(面向切面编程)容器框架;
4.在IOC和AOP基础上可以整合各种企业应用的开源框架和优秀的第三方类库

二.配置eclipse

以下是不同的eclipse对应的sts版本,请查看好自己的eclipse下载对应的版本

eclipse-kepler.4.3.1–>springsource-tool-suite-RELEASE-e4.3.1-updatesite.zip
eclipse-Mars.4.5.1–>springsource-tool-suite-3.7.2RELEASE-e4.5.1-updatesite.zip
eclipse-Mars.4.5.2–>springsource-tool-suite-3.7.3RELEASE-e4.5.2-updatesite.zip
eclipse-neno.4.6–>springsource-tool-suite-3.7.3RELEASE-e4.6-updatesite.zip

我的版本是eclipse-Mars.4.5.2安装完毕后,welcome页面显示Spring tool,但是在window->properties中却没有spring选项,而且安装完毕后在properties中连maven选项也不见了,这个问题整整折腾了我半天时间,卸了装,装了卸还是不行,最后问同事用的是eclipse-neno.4.6.3发行版,下载eclipse-neno.4.6.3

spring4-1-基础bean的配置_第1张图片
eclipse-1.jpg

下载后打开,提示JDK环境必须是JDK1.8以上,于是 从JDK1.7升级到JDK1.8,

安装步骤如下:我用的是(springsource-tool-suite-3.8.4.RELEASE-e4.6.3-updatesite.zip)下载地址:https://spring.io/tools/sts/all

spring4-1-基础bean的配置_第2张图片
Paste_Image.png

spring4-1-基础bean的配置_第3张图片
spring-2.jpg
spring-3.jpg

安装完毕后在window->Preperences中就可以看到spring选项了;


spring4-1-基础bean的配置_第4张图片
spring-5.jpg

到此为止eclipse中spring插件配置结束,这个汗....

三.第一个helloWorld

  • 下载spring最新稳定版本,下载方式请查看:
    http://www.cnblogs.com/yy3b2007com/p/6783699.html

  • 新建java下过目,spring-1

  • 加载jar包(以下橙色背景的四个核心jar包必须加载)


    spring4-1-基础bean的配置_第5张图片
    spring-6.jpg
  • 自己下载commons-logging.jar包并加载进去

  • 目录结构:


    spring4-1-基础bean的配置_第6张图片
    spring-7.jpg
  • HelloWorld内容:

package com.lxf.spring.bean;

public class HelloWorld {
    private String name;
    public void setName(String name)
    {
        System.out.println("setName:"+name);
        this.name = name;
    }
    public void hello()
    {
        System.out.println("hello: "+this.name);
    }
    public  HelloWorld()
    {
        System.out.println("init HelloWorld...");
    }
}
  • Spring Bean Configuration File内容:



     
    
        
    

  • Main.java内容
package com.lxf.spring.bean;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
    public static void main(String[] args)
    {
        /*
        HelloWorld helloworld = new HelloWorld();
        helloworld.setName("liangxifeng");
        */
        //1.创建spring的IOC容器对象
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        //2.从IOC容器中获取Bean实例
        //HelloWorld helloworld = (HelloWorld)ctx.getBean("helloWorld");
        //helloworld.setName("aaa");
        //3.调用hello方法
       // helloworld.hello();
    }
}

四.IOC(inversion of Control)和 DI(Dependency Injection)

  • IOC概念:
  • 思想是反转资源获取的方向
  • 传统的资源查找方式要求组件向容器发起请求查找资源.作为回应,容器实时的返回资源;
  • 应用了IOC之后,则是容器主动地就将资源推送给它所管理的组件
  • 组件所要做的只是选择一种合适的方式来接收资源;(也称查找的被动形式)
  • DI概念
  • IOC的另一种表达方式:即组件以一些预定义好的方式(例如:setter方法)接收来自容器的资源注入,相对IOC而言,这种表述更直接;
spring4-1-基础bean的配置_第7张图片
Paste_Image.png

五.IOC的前生

spring4-1-基础bean的配置_第8张图片
ioc-1.jpg

ReprotService要想生成报表需要依赖三个类, 耦合度很高

spring4-1-基础bean的配置_第9张图片
ioc-2.jpg

使用工厂模式ReprotService要想生成报表需要依赖两个类, 耦合度降低

spring4-1-基础bean的配置_第10张图片
ioc-3.jpg

使用反转控制ReprotService要想生成报表需要依赖一个类, 耦合度最低

六.spring容器

  • 在Spring IOC容器读取Bean配置之前,自身要先实例化;

  • Spring提供了两种类型的IOC容器实现;
    (1). BeanFactory:IOC容器的基本实现(BeanFactory是spring框架的基础设施,面向Spring本身)
    (2). ApplicationContext 是BeanFactory的子接口,提供了更丰富的功能;(ApplicationContext 面向Spring框架的开发者,几乎所有应用场合都直接使用ApplicationContext而非底层的BeanFactory)

  • ApplicationContext有两个实现类


    spring4-1-基础bean的配置_第11张图片
    Paste_Image.png
  • 属性的注入方式一(setter方法)

     
    
        
    
    private String name;
    public void setName(String name)
    {
        System.out.println("setName:"+name);
        this.name = name;
    }
  • 属性的注入方式二(构造方法注入)
  • 通过构造方法注入Bean的属性值或依赖的对象,它保证了Bean实例在实例化后就可以使用
  • 构造器注入在元素里声明属性,中没有name属性;
  • 使用构造器注入属性值可以指定参数的位置和参数类型,以区分重载构造器
    
    
        
        
    
        
    
        
        
    

以上两个bean,根据参数类型区分实例化的时候调用哪个构造器
Bean类Car

package com.lxf.spring.bean;
public class Car {
    private String cName;
    private double price;
    private int speed;  
    /**
     * 构造器,为汽车名字和汽车价格属性初始化值
     * @param cName
     * @param price
     */
    public Car(String cName, double price) {
        super();
        this.cName = cName;
        this.price = price;
    }

    /**
     * 重载构造器,为汽车名字和汽车速度初始化值
     * @param cName
     * @param speed
     */
    public Car(String cName, int speed) {
        super();
        this.cName = cName;
        this.speed = speed;
    }
    @Override
    public String toString() {
        return "Car [cName=" + cName + ", price=" + price + ", speed=" + speed + "]";
    }
}

测试:

        Car car = (Car) ctx.getBean("car1");
        System.out.println(car);
        Car car = (Car) ctx.getBean("car2");
        System.out.println(car);

输出:

Car [cName=汽车1, price=150000.0, speed=0]
Car [cName=汽车2, price=0.0, speed=120]
  • 属性值也可以使用value子结点进行那个配置(字面值)
    
     
        
            ]]>
        
        
    
        Car car3 = (Car) ctx.getBean("car1-1");
        System.out.println(car3);

输出:

Car [cName=<汽车1-1*>, price=150000.0, speed=0]
  • bean之间的相关互引用

person类

package com.lxf.spring.bean;

public class Person {
    //姓名
    private String name;
    //年龄
    private int age;
    //该人所拥有的汽车
    private Car car;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public Car getCar() {
        return car;
    }
    public void setCar(Car car) {
        this.car = car;
    }
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + ", car=" + car + "]";
    }
}

配置bean文件:

    
        
        
    
    
        
        
        
        
        
        
    
        
        
            
                
                
            
        

七.级联属性赋值

    
        
        
    
    
    
        
        
        
        
        
             
    

八.集合属性赋值

(1)List类型配置
Person类中有属性

    //该人所拥有的汽车集合
    private List cars;
    public List getCars() {
        return cars;
    }
    public void setCars(List cars) {
        this.cars = cars;
    }

spring配置bean

    
    
        
        
    
        
    
        
        
    
    
    
                
                
                
                
                    
                        
                        
                    
                
    

(2)Map类型属性赋值
Person类中的属性

    //map类型的汽车
    private Map mapCars;
  public Map getMapCars() {
        return mapCars;
    }
    public void setMapCars(Map mapCars) {
        this.mapCars = mapCars;
    }

Spring配置

    
    
                
                
                
                
                    
                    
                        
                        
                    
                
    

(3)Properites属性赋值
DataSource实体类

package com.lxf.spring.bean;

import java.util.Properties;

public class DataSource {
    private Properties properties;

    public Properties getProperties() {
        return properties;
    }

    public void setProperties(Properties properties) {
        this.properties = properties;
    }

    @Override
    public String toString() {
        return "DataSource [properties=" + properties + "]";
    }
}

(4)使用Utility scheme定义集合
使用Utility schema里的集合标签定义独立的集合Bean,必须在Bean根元素里面定义;
这样定义的集合就可以被其他Bean共享
注意:需要导入util命名空间

spring4-1-基础bean的配置_第12张图片
col-5.jpg

Person实体类属性

    //该人所拥有的汽车集合
    private List cars;
    public List getCars() {
        return cars;
    }
    public void setCars(List cars) {
        this.cars = cars;
    }

Spring配置

    
    
        
        
    
    
               
                
                
                
    

从Spring2.5起可以使用P命名空间为bean属性赋值

Spring配置(注意:需导入 p 命名空间,导入方式类似util命名空间

  
    

九.bean的自动装配

使用autowire属性指定自动装配的方式,
(1) byName根据其他bean的id值和当前bean的setter风格属性名进行自动装配,如果没有匹配的bean则不装配
(2)byType根据其他bean的类型和当前bean属性的类型进行自动装配,若IOC容器中有一个以上的类型匹配的bean,则抛异常

    
    
    
    
    

自动装配缺点:
(1)如果使用autowire属性自动装配,那么只要使用autowire的bean中引用其他bean属性的值都自动装载,不能指定某一个或几个属性使用自动装载;
(2)自动装载byType方式,如果一个Spring配置文件中有多个引用类型,则该方式会不知道装载哪个,会抛出异常;
所以在平时开发中尽量使用手动配置,整合其他框架的时候才使用自动装载

十.Bean之间的关系继承

  • Spring允许继承Bean的配置,称为父Bean和子Bean;
  • 子Bean从父Bean中继承配置,包括Bean的属性配置;
  • 子Bean也可以覆盖父Bean继承来的配置;
  • 父Bean可以作为配置模板,也可以作为Bean实例,可以设置的abstract属性为true,这样Spring将不会实例化这个Bean;
  • 并不是Bean元素里面的所有属性都会被继承,比如:autowire abstract等不会被继承
  • 也可以忽略父Bean的class属性,让子Bean指定自己的类,而共享相同属性配置,但此时abstract必须设为true



    
    
    
    

十一.Bean之间的关系依赖

  • 使用depends-on属性设定Bean前置依赖的Bean,前置依赖的Bean会在本Bean实例化之前创建好;
  • 如果前置依赖多个Bean,则可以通过逗号,空格或的方式配置Bean的名称;
    
    
    

十二.Bean的作用域

  • 默认单例: bean属性scope=singleton(默认值),IOC容器初始化的时创建bean实例,在整个容器的生命周期内只创建一个bean,单例的; 比如:
    Car类有无参构造器:
public class Car {
    private String brand;
    private double price;
    public Car()
    {
        System.out.println("Car is Constract...");
    }
}

Spring配置

    
    

main方法测试:

        //创建spring的IOC容器对象
        ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-scope.xml");   

输出:

Car is Constract...

证明容器在初始化的时候创建单例bean;
main方法测试:

        ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-scope.xml");   
        Car car1 = (Car)ctx.getBean("car");
        Car car2 = (Car)ctx.getBean("car");
        System.out.println(car1==car2);//输出true

以上car1=car2,证明每次调用bean的使用都是

  • 多例: bean属性scope=prototype(原型的),IOC容器初始化时不创建bean实例,而在每次请求时都创建一个新的Bean实例,并返回,比如:
    修改上面的Spring配置
    
    

main方法测试:

        //创建spring的IOC容器对象
        ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-scope.xml"); //不创建bean实例  
        Car car1 = (Car)ctx.getBean("car"); //创建一个bean实例
        Car car2 = (Car)ctx.getBean("car");//再次创建一个bean实例
        System.out.println(car1==car2);//返回false

十三.配置bean中使用外部属性文件

spring4-1-基础bean的配置_第13张图片
Paste_Image.png
  • 首先在Spring配置文件中打开context命名空间;
  • src下新建db.properties属性配置文件
userName=root
pass=123456
driverClass=com.mysql.jdbc.Driver
jdbcUrl=jdbc:mysql:///test
  • 在Spring配置文件(beans-properties.xml)中引用该配置文件中的属性变量
    
     
    
        
        
        
        
        
    
  • main方法测试:
        //1.创建spring的IOC容器对象
        ApplicationContext ctx = new ClassPathXmlApplicationContext("beans-properties.xml");   
        //获取数据源
        DataSource dataSource = (DataSource)ctx.getBean("dataSource");
        //打印数据库连接
        System.out.println(dataSource.getConnection());

输出结果:

com.mchange.v2.c3p0.impl.NewProxyConnection@ee3d0a5
  • 以上测试需要加入:c3p0-0.9.1.2.jar 和 jdbc jar包,其中C3P0是一个开源的JDBC连接池

十四.Spring的spel表达式


    
    



    
    
    
    



    
    
    
    
    
    
    

十五.IOC容器中Bean的生命周期

spring4-1-基础bean的配置_第14张图片
Paste_Image.png

举例如下:
(1)Car实体类:

package com.lxf.spring.cycle;
/**
 * 汽车实体类
 * @author lxf
 */
public class Car {
    private String brand;
    private double price;
    //轮胎周长
    private double tyrePerimeter;
    /**
     * 无参数构造器
     */
    public Car()
    {
        System.out.println("Car is Constract...");
    }
    public String getBrand() {
        return brand;
    }
    public void setBrand(String brand) {
        System.out.println("setBrand为品牌属性赋值");
        this.brand = brand;
    }
    public double getPrice() {
        return price;
    }
    public void setPrice(double price) {
        this.price = price;
    }
    public double getTyrePerimeter() {
        return tyrePerimeter;
    }
    public void setTyrePerimeter(double tyrePerimeter) {
        this.tyrePerimeter = tyrePerimeter;
    }
    @Override
    public String toString() {
        return "Car [brand=" + brand + ", price=" + price + ", tyrePerimeter=" + tyrePerimeter + "]";
    }
    
    /**
     * Bean初始化方法,在IOC容器启动的时候调用
     */
    public void myInit()
    {
        System.out.println("创建了IOC容器:调用Bean的初始化方法");
    }
    /**
     * Bean销毁方法,在IOC容器关闭的时候调用
     */
    public void myDestroy()
    {
        System.out.println("调用Bean的销毁方法,IOC容器关闭了");
    }
}

(2)Spring配置文件(beans-cycle.xml)

    
    
        
    

(3)main方法测试

        //创建spring的IOC容器对象
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans-cycle.xml");   
        Car car1 = (Car)ctx.getBean("car");
        System.out.println("使用Bean: "+car1);
        //关闭IOC容器
        ctx.close();

输出结果如下:

Car is Constract...
setBrand为品牌属性赋值
创建了IOC容器:调用Bean的初始化方法
使用Bean: Car [brand=Audi, price=0.0, tyrePerimeter=0.0]
...
调用Bean的销毁方法,IOC容器关闭了

spring4-1-基础bean的配置_第15张图片
Paste_Image.png

spring4-1-基础bean的配置_第16张图片
Paste_Image.png

修改以上代码加入后置处理器bean的生命周期:
(1)新建后置处理器MyBeanPostProcessor

package com.lxf.spring.cycle;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

public class MyBeanPostProcessor implements BeanPostProcessor {

    /**
     *  bean的init-method方法之后调用
     *  参数:
     *  bean: IOC传递进来的bean实例
     *  beanName:bean的id
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        // TODO Auto-generated method stub
        if("car".equals(beanName))
        {
            System.out.println("bean的init-method方法之后调用:"+bean);
        }      
        return bean;
    }
    /*
     * bean的init-method方法之前调用
     *  参数:
     *  bean: IOC传递进来的bean实例
     *  beanName:bean的id
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        // TODO Auto-generated method stub
        if("car".equals(beanName))
        {
            System.out.println("bean的init-method方法之前调用:"+bean);
            Car car = new Car();
            car.setBrand("大众");
            //对bean重新赋值
            bean = car;
        }       
        return bean;
    }
}

(2)Spring配置文件beans-cycle.xml修改

    
    
        
    
    
    
       
    

(3)main方法测试:

        //创建spring的IOC容器对象
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans-cycle.xml");   
        Car car1 = (Car)ctx.getBean("car");
        System.out.println("使用Bean: "+car1);
        //关闭IOC容器
        ctx.close();

输出结果:

Car is Constract...
setBrand为品牌属性赋值
bean的init-method方法之前调用:Car [brand=Audi, price=0.0, tyrePerimeter=0.0]
Car is Constract...
setBrand为品牌属性赋值
创建了IOC容器:调用Bean的初始化方法
bean的init-method方法之后调用:Car [brand=大众, price=0.0, tyrePerimeter=0.0]
使用Bean: Car [brand=大众, price=0.0, tyrePerimeter=0.0]
调用Bean的销毁方法,IOC容器关闭了

十六.使用工厂方法创建Bean

spring4-1-基础bean的配置_第17张图片
Paste_Image.png

举例:
(1)新建静态工厂方法类:StaticFactory

package com.lxf.spring.factory;

import java.util.HashMap;
import java.util.Map;

/**
 * 静态工厂方法:直接调用某一个类的静态方法可以返回Bean实例
 * @author lxf
 *
 */
public class StaticFactory {
    private static Map cars = new HashMap();
    static{
        cars.put("audi", new Car("audi"));
        cars.put("ford", new Car("ford"));
    }
    /**
     * 静态工厂方法返回对应Bean实例
     * @param name
     * @return
     */
    public static Car getCar(String name)
    {
        return cars.get(name);
    }
}

(2)Spring配置文件beans-factory.xml

    
    
    
        

(3)man方法测试:

        //创建spring的IOC容器对象
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans-factory.xml");   
        Car car1 = (Car)ctx.getBean("car1");
        System.out.println("使用Bean: "+car1);

输出:

使用Bean: Car [brand=audi, price=0.0, tyrePerimeter=0.0]
spring4-1-基础bean的配置_第18张图片
Paste_Image.png

举例:
(1)新建实例工厂方法类:InstanceFactory

package com.lxf.spring.factory;
import java.util.HashMap;
import java.util.Map;
/**
 * 实例工厂方法:实例工厂的方法,即先需要创建工厂本身实例,
 *                             再调用工厂的实例方法来返回bean的实例.
 * @author lxf
 */
public class InstanceFactory {
    private Map cars = null;
    public InstanceFactory()
    {
        cars = new HashMap();
        cars.put("audi", new Car("audi"));
        cars.put("ford", new Car("ford"));
    }
    public Car getCar(String name)
    {
        return cars.get(name);
    }
}

(2)Spring配置文件(beans-factory.xml)

     
     
     
     
         
     
        
     

(3)mani方法测试:

        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans-factory.xml");           
        Car car2 = (Car)ctx.getBean("car2");
        System.out.println("使用Bean: "+car2);

输出:

使用Bean: Car [brand=ford, price=0.0, tyrePerimeter=0.0]

使用FactoryBean的方式配置Bean

  • 其实就是自己定义一个类,实现Spring的FactoryBean接口,实现该接口的三个方法即可;(其中有一个方法返回Bean实例)
package com.lxf.spring.factorybean;
import org.springframework.beans.factory.FactoryBean;
/**
 * 通过FactoryBean的方式配置Bean,需要实现FactoryBean接口
 * @author lxf
 * @param 
 */
public class CarFactoryBean implements FactoryBean {
    private String brand;
    public void setBrand(String brand) {
        this.brand = brand;
    }
    @Override
    /**
     * 返回bean对象
     */
    public T getObject() throws Exception {
        // TODO Auto-generated method stub
        return (T) new Car(brand,5000000);
    }
    @Override
    /**
     * 返回Bean类型
     */
    public Class getObjectType() {
        // TODO Auto-generated method stub
        return Car.class;
    }
    @Override
    /**
     * 是否是单例
     */
    public boolean isSingleton() {
        // TODO Auto-generated method stub
        return true;
    }
}
  • 在Spring配置文件中beans-facotrybean.xml中配置自己定义的类
    
    
        
    
  • main方法测试:
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans-factorybean.xml");   
        Car car1 = (Car)ctx.getBean("car");
        System.out.println("使用Bean: "+car1);

输出:

使用Bean: Car [brand=BMW, price=5000000.0, tyrePerimeter=0.0]

使用注解的方式配置bean

注意:需要引入spring-aop-4.3.9.RELEASE.jar

spring4-1-基础bean的配置_第19张图片
Paste_Image.png

spring4-1-基础bean的配置_第20张图片
Paste_Image.png
spring4-1-基础bean的配置_第21张图片
Paste_Image.png

Spring配置文件beans-annotation.xml配置

        
        
        
         
        
         
         
         
        
       
                
         

以上目录结构:

src
 |__com.spring.beans.annotation
 |   |__Main.java
 |   |__TestObject.java
 |   |__service
 |       |__UserService.java
 |   |__respository
 |       |__UserRespository.java
 |   |__controller
 |       |__UserController.java
 |__beans.annotation.xml

UserService.java类带有@Service注解

package com.spring.beans.annotation.service;
import org.springframework.stereotype.Service;
@Service
public class UserService {
    public void add()
    {
        System.out.println("UserService add...");
    }
}

其他User*.java分别带有如下注解

@Repository("userRepository")
@Controller
@Repository("userRepository"

Bean之间属性互相依赖的解决方案:

spring4-1-基础bean的配置_第22张图片
Paste_Image.png
spring4-1-基础bean的配置_第23张图片
Paste_Image.png
package com.spring.beans.annotation.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import com.spring.beans.annotation.TestObject;
import com.spring.beans.annotation.repository.UserRepository;
import com.spring.beans.annotation.service.UserService;

@Controller
public class UserController {
    @Autowired
    private UserService userService;
    
    @Autowired
    //如果IOC容器中存在多个UserRepository接口的实现类,
    //可以指定具体装在哪个实现类,注意首字母小写(spring规定)
    @Qualifier("jdbcRespository")
    private UserRepository userRepository;
    
   //如果IOC容器中没有testObj这个bean,则使用@Autowired(required=false,否则异常
    @Autowired(required=false)    
    private TestObject testObj;
    public void execute()
    {
        System.out.println("UserControler execute...");
        userService.add();
    }
}

十七.Spring4.* 泛型的依赖注入

在实际开发中,往往我们可以将一些结构职能相似的类抽象出一定的泛型超类。这样相应结构中的类之间的依赖关系我们可以通过泛型超类来建立,而其他的子类只要继承了它们,就能够建立相应的依赖关系:

参考链接:https://my.oschina.net/happyBKs/blog/482508

代码演示点击

你可能感兴趣的:(spring4-1-基础bean的配置)