1. 程式人生 > >spring IOC快速入門,屬性註入,註解開發

spring IOC快速入門,屬性註入,註解開發

復雜 void erl main http val rri prop turn

我們使用spring框架也會使用到配置文件,我們需要在src下創建一個關於spring的配置文件,
一般情況名稱叫applicationContext.xml

基本約束:

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"
        "http://www.springframework.org/dtd/spring-beans-2.0.dtd">

IOC快速入門

  inversion of Controller 控制反轉

原來由我們自己實例化的對象交給spring容器來實始化。這時對象的實始化的權利就會反轉

創建一個類

public class
Bean1 { public void show() { System.out.println("bean1......"); } }

在src下的applicationContext.xml中配置

<bean name="bean1" class="com.learn.bean.Bean1" scope="singleton"></bean>

在測試類中測試

[email protected]
    public void test1() {
        ApplicationContext context 
= new ClassPathXmlApplicationContext("ApplicationContext.xml"); UserServiceImpl us = (UserServiceImpl) context.getBean("UserService"); us.sayHello(); }

ApplicationContext它是BeanFactory的一個子接口,我們在使用時使用的是AppliCationContext的實現類ClassPathXmlApplicationContext
ApplicationContext它是擴展BeanFactory接口。BeanFactory它采取延遲加載的方案,只有真正在getBean時才會實例化Bean

可以通過getBean(配置文件中id名稱)來獲取指定的對象。

這就是一個基本的spring入門

Bean的實例化方式(這裏介紹兩種)

這種方式:bean類必須提供無參構造

配置

<bean name="bean1" class="com.learn.bean.Bean1" scope="singleton"></bean>

bean

public class Bean1 {
    public void show() {
        System.out.println("bean1......");
    }
}

測試

    //測試無參構造的實例化方式
    @Test
    public void test1() {
        ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
        Bean1 bean1 = (Bean1) context.getBean("bean1");
        bean1.show();
    }

靜態工廠方法實例化

bean

public class Bean2 {
    public static Bean2 Bean2Factory() {
        return new Bean2();
    }
    public static  void show() {
        System.out.println("bean2");
    }
}

配置

         <!-- 靜態工廠創建實例 -->
            <bean name="bean2" class="com.learn.bean.Bean2" factory-method="Bean2Factory"></bean>            

需要註意的是,在工廠類中提供一個static返回bean對象

測試

  //測試靜態工廠的實例化方式
    @Test
    public void test2() {
        ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
        Bean2 bean2 = (Bean2) context.getBean("bean2");
        bean2.show();
    }

DI

DI:dependency injection 依賴註入

在spring框架負責創建Bean對象時,動態將依賴對象註入到Bean組件。

第一種屬性註入方式:
一個類

public class UserServiceImpl implements UserService {
    //聲明一個依賴註入的屬性
    //提供get/set方法
    private String INFO;
    public String getINFO() {
        return INFO;
    }
    public void setINFO(String iNFO) {
        INFO = iNFO;
    }
    @Override
    public void sayHello() {
        System.out.println("不忘初心,"+INFO);
    }
}

屬性註入

        <!-- setter註入屬性 -->
            <bean class="com.learn.domain.Person" name="person">
                <property name="name" value="張三"></property>
                <property name="car" ref="car"></property>
            </bean>

測試

  //測試構造器註入
    @Test
    public void test() {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
        Car car = (Car) context.getBean("car");
        System.out.println(car);
    }

第二種屬性註入方式:

        <!-- 構造器註入屬性 -->
            <bean name="car" class="com.learn.domain.Car">
                <constructor-arg type="String" value="寶馬"/>
                <constructor-arg type="Double" value="1000000"></constructor-arg>
            </bean>

bean類

public class Car {
    private String name;
    private Double price;
    public Car(String name, Double price) {
        super();
        this.name = name;
        this.price = price;
    }
    public Car() {
        super();
        // TODO Auto-generated constructor stub
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Double getPrice() {
        return price;
    }
    public void setPrice(Double price) {
        this.price = price;
    }
    @Override
    public String toString() {
        return "Car [name=" + name + ", price=" + price + "]";
    }
}

集合屬性的註入:

public class CollectionDemo {
    private List list;
    private Set set;
    private Map map;
    private Properties prop;
    public CollectionDemo() {
        super();
        // TODO Auto-generated constructor stub
    }
    public List getList() {
        return list;
    }
    public void setList(List list) {
        this.list = list;
    }
    public Set getSet() {
        return set;
    }
    public void setSet(Set set) {
        this.set = set;
    }
    public Map getMap() {
        return map;
    }
    public void setMap(Map map) {
        this.map = map;
    }
    public Properties getProp() {
        return prop;
    }
    public void setProp(Properties prop) {
        this.prop = prop;
    }
    public CollectionDemo(List list, Set set, Map map, Properties prop) {
        super();
        this.list = list;
        this.set = set;
        this.map = map;
        this.prop = prop;
    }
}

配置註入屬性

<!-- 集合註入 -->
            <bean name="collection" class="com.learn.domain.CollectionDemo">
                <!-- list集合註入 -->
                <property name="list">
                    <list>
                        <value>李四</value>
                        <value>18</value>
                        <ref bean="car"/>
                    </list>
                </property>
                <!-- set屬性註入 -->
                <property name="set">
                    <set>
                        <value>王五</value>
                        <value>20</value>
                        <ref bean="car"/>
                    </set>
                </property>
                <!-- map屬性註入 -->
                <property name="map">
                    <map>
                        <entry key="username" value="tom"></entry>
                        <entry key="password" value="123"></entry>
                    </map>
                </property>
                <!-- properties屬性註入 -->
                <property name="prop">
                    <props>
                        <prop key="username">123</prop>
                        <prop key="password">123</prop>
                    </props>
                </property>
            </bean>

bean的作用域:

  在bea聲明時它有一個scope屬性,它用於描述bean的作用域:

singleton:單例 代表在spring ioc容器中只有一個Bean實例 (默認的scope)
prototype多例 每一次從spring容器中獲取時,都會返回一個新的實例
request 用在web開發中,將bean對象request.setAttribute()存儲到request域中
session 用在web開發中,將bean對象session.setAttribute()存儲到session域中
在開如常用的值是singleton與prototype


bean的聲明周期

  

1. instantiate bean對象實例化
2. populate properties 封裝屬性
3. 如果Bean實現BeanNameAware執行setBeanName
4. 如果Bean實現BeanFactoryAwar或ApplicationContextAwar設置工廠setBeanFactory或上下文對象setApplicationContext
5. 如果存在類實現BeanPostProcessor(後處理Bean),執行postProcessBeforeInitialization
6. 如果Bean實現InitializingBean執行afterPropertiesSet
7. 調用自定義的init-method方法
8. 如果存在類實現BeanPostProcessor(處理Bean),執行postProcessAfterInitialization
9. 執行業務處理
10. 如果Bean實現DisposableBean執行destroy
11. 調用自定義的destroy-method

下面用代碼來描述聲明周期:

public class BeanLifeCycle implements BeanNameAware,ApplicationContextAware,InitializingBean,DisposableBean{
    private String name;
    
    public BeanLifeCycle() {
        System.out.println("第一步:實例化beanLifeCycle對象");
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        System.out.println("第二步:name屬性的註入");
        this.name = name;
    }
    @Override
    public void setBeanName(String arg0) {
        System.out.println("第三步:得到bean的id或name屬性的值"+name);
    }
    @Override
    public void setApplicationContext(ApplicationContext arg0) throws BeansException {
        System.out.println("第四步:得到applicationContext對象");
    }
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("第六步:調用屬性註入完成後的方法");
    }
    public void myInit() {
        System.out.println("Init");
        System.out.println("第七步:自定義init方法");
    }
    public void add() {
        System.out.println("第九步:執行bean自己的功能");
    }
    @Override
    public void destroy() throws Exception {
        System.out.println("第十步:調用銷毀的方法");
    }
    public void myDestroy() {
        System.out.println("myDestory");
        System.out.println("第十一步:自定義銷毀方法");
    }
}
public class MyBeanPostProcess implements BeanPostProcessor{

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("第八步:beanPostAfter的方法");
        
        return bean;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("第五步:beanPostBefore的方法");
        System.out.println("處理的bean是:"+bean +"它的名稱是:"+beanName);
        return bean;
    }
    
}
<bean name="beanLifeCycle" class="com.learn.bean.BeanLifeCycle" init-method="myInit" destroy-method="myDestroy">
                <property name="name" value="beanLifeCycle"></property>
            </bean>
            <bean name="myBeanPostProcess" class="com.learn.bean.MyBeanPostProcess"></bean>

測試:

[email protected]
    public void test2() {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
        BeanLifeCycle blc = (BeanLifeCycle) context.getBean("beanLifeCycle");
        blc.add();
        context.close();
    }

對於bean的生命周期,我們需要關註的主要有兩個方法:
1. 增強bean的功能可以使用後處理Bean, BeanPostProcessor
2. 如果需要初始化或銷毀操作我們可以使用init-method destroy-method

註意:destroy-method只對scope=singleton有效果。

SpEl

spring expression language 是在spring3.0以後的版本提供
它類似於ognl或el表達式,它可以提供在程序運行時構造復雜表達式來完成對象屬性存儲及方法調用等。
Spel表達式的格式 #{表達式}

        <bean class="com.learn.domain.Person" name="person">
                <property name="name" value="張三"></property>
                <property name="car" ref="car"></property>
            </bean>

        <!-- spEL -->
            <bean name="person1" class="com.learn.domain.Person">
                <property name="name" value="猥瑣逼"></property>
                <property name="car" value="#{person.car}"></property>
            </bean>
public class Person {
    private String name;
    private Car car;
    public Person() {
        super();
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Car getCar() {
        return car;
    }
    public void setCar(Car car) {
        this.car = car;
    }
    public Person(String name, Car car) {
        super();
        this.name = name;
        this.car = car;
    }
    @Override
    public String toString() {
        return "Person [name=" + name + ", car=" + car + "]";
    }
}

Spring註解開發
在spring中使用註解,我們必須在applicationContext.xml文件中添加一個標簽
<context:annotation-config/>作用是讓spring中常用的一些註解生效。
要使用contex名稱空間,必須在applicationContext.xml文件中引入

<?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">

快速入門

@Component("customer")
public class Customer {
    @Value("張三")
    private String name;

    public Customer(String name) {
        super();
        this.name = name;
    }

    public Customer() {
        super();
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Customer [name=" + name + "]";
    }
    
}
@Test
    public void test2() {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        Customer c = (Customer) context.getBean("customer");
        System.out.println(c);
    }

註意:運行之前需要在applicationContext中配置:

<context:component-scan base-package="com.learn"></context:component-scan>

[email protected]
@Rpository 用於DAO層
@Service 用於service層
@Controller 用於表現層
對於我們的bean所處在的位置可以選擇上述三個註解來應用,如果你的bean不明確位置,[email protected]

屬性註入

    @Value("張三")
    private String name;

復雜屬性註入

  

    @Autowired
    private CustomerDaoImpl cdi;

@Value @Autowired它們可以修飾屬性,也可以修飾setter方法,如果寫在屬性上,就不需要提供setter方法。
@Autowired它默認是根據類型進行註入。
[email protected],就可以根據名稱來進行註入。
我們也可以使用下面的方式來根據名稱進行屬性註入

其它註解
@Scope它以描述bean的作用域。

@PostConstruct
public void myInit(){}

@PostConstruct相當於:init-method="myInit"

@PreDestory
public void myDestory(){}

@PreDestory相當於:destroy-method=”myDestroy”
註意:對於銷毀的方法它只對bean的scope=singleton有效。

Spring整合junit4測試

//整合
@RunWith(SpringJUnit4ClassRunner.class)
//聲明加載的配置文件
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class Test2 {
    @Autowired
    private CustomerServiceImpl csi;
    @Autowired
    private CustomerDaoImpl cdi;

    @Test
    public void test1() {
        csi.add();
    }

    @Test
    public void test2() {
        cdi.add();
    }
}

spring IOC快速入門,屬性註入,註解開發