首页 > 代码库 > spring IOC快速入门,属性注入,注解开发

spring IOC快速入门,属性注入,注解开发

我们使用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>

在测试类中测试

  @Test
    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="http://www.mamicode.com/张三"></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="http://www.mamicode.com/宝马"/>
                <constructor-arg type="Double" value="http://www.mamicode.com/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="http://www.mamicode.com/tom"></entry>
                        <entry key="password" value="http://www.mamicode.com/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="http://www.mamicode.com/beanLifeCycle"></property>
            </bean>
            <bean name="myBeanPostProcess" class="com.learn.bean.MyBeanPostProcess"></bean>

测试:

  @Test
    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="http://www.mamicode.com/张三"></property>
                <property name="car" ref="car"></property>
            </bean>

        <!-- spEL -->
            <bean name="person1" class="com.learn.domain.Person">
                <property name="name" value="http://www.mamicode.com/猥琐逼"></property>
                <property name="car" value="http://www.mamicode.com/#{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>

在spring2.5后为@Component添加了三个衍生的注解
@Rpository 用于DAO层
@Service 用于service层
@Controller 用于表现层
对于我们的bean所处在的位置可以选择上述三个注解来应用,如果你的bean不明确位置,就可以使用@Component.

属性注入

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

复杂属性注入

  

    @Autowired
    private CustomerDaoImpl cdi;

@Value @Autowired它们可以修饰属性,也可以修饰setter方法,如果写在属性上,就不需要提供setter方法。
@Autowired它默认是根据类型进行注入。
如果与@Qualifier一起使用,就可以根据名称来进行注入。
我们也可以使用下面的方式来根据名称进行属性注入

 

其它注解
@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快速入门,属性注入,注解开发