Spring

首先spring是一个企业级J2EE的框架,用于开发一个webApp,它是针对bean的生命周期进行管理的轻量级容器。主要由七个部分组成:Spring Core、Spring AOP、Spring ORM、Spring DAO、Spring Context、Spring Web、Spring Web MVC

它有两大特性IOCAOP

IOC是什么?

基本概念

1.IOC容器是一个创建对象、配置对象、连接对象、并管理对象的生命周期的一个容器,这里的对象即bean对象。

2.bean 是一个被实例化,组装,并通过IOC容器所管理的对象。

实现IOC容器的两种方式:

(1) BeanFactory

  • Spring内部使用,开发人员基本不用,加载配置文件时不会创建对象,使用时才会创建对象。

(2) ApplicationContext

  • BeanFactory的子接口,在其基础上添加更多功能,加载配置文件时就创建了好配置的对象。

基于XML管理Bean

DI:依赖注入,即注入属性

注入普通属性

<!--调用无参构造函数,使用set方法注入属性-->
<bean id="user" class="di.pojo.User">
    <property name="password" value="12345"/>
    <property name="username">
        <null/>  <!--设置为null-->
    </property>
</bean>

<!--调用有参构造函数注入属性-->
<bean id="user1" class="di.pojo.User">
    <constructor-arg name="password" value="67890"/>
    <constructor-arg name="username">
        <null/>
    </constructor-arg>
</bean>

注入引用对象属性

当一个对象中含有另一个对象的引用,可通过引用外部bean、内部bean、级联三种方式设置引用对象的属性:

<!--引入外部bean赋值-->
<bean id="bookImpl" class="di.dao.impl.BookImpl">
    <property name="bookName" value="红楼梦"/>
</bean>

<bean id="bookService" class="di.service.BookService">
    <property name="bookDao" ref="bookImpl"/>  <!--调用BookService中的setBookDao-->
</bean>

<!--引入内部bean赋值-->
<bean id="bookService1" class="di.service.BookService">
    <property name="bookDao">
        <bean class="di.dao.impl.BookImpl">
            <property name="bookName" value="水浒传"/>
        </bean>
    </property>
</bean>

<!--级联属性赋值-->
<bean id="bookService2" class="di.service.BookService">
    <property name="bookImpl" ref="bookImpl"/>  <!--这行有必要-->
    <property name="bookImpl.bookName" value="三国演义"/>
</bean>

注入集合属性

<!--注入集合属性-->
<bean id="collection" class="di.pojo.Collection">
    <property name="arr">
        <array>
            <value>arr1</value>
            <value>arr2</value>
        </array>
    </property>
    <property name="list">
        <list>
            <value>list1</value>
            <value>list2</value>
        </list>
    </property>

    <!--引用外部bean,添加到List<User>集合中-->
    <property name="userList">
        <list>
            <ref bean="user"/>
            <ref bean="user1"/>
        </list>
    </property>


    <property name="set">
        <set>
            <value>set1</value>
            <value>set2</value>
        </set>
    </property>
    <property name="map">
        <map>
            <entry key="key1" value="value1"/>
            <entry key="key2" value="value2"/>
        </map>
    </property>
</bean>

普通bean和工厂bean的区别

IOC有两种bean,一种是普通bean,配置文件中定义的class类型和在代码中获取的类型必须要一致,上面配置的所有bean都是普通bean;另外一种是工厂bean,即配置文件定义的类型和返回的类型可以不一致,其类必须实现FactoryBean接口,如下:

public class FactoryBeanTest implements FactoryBean<User> {
    @Override
    public User getObject() throws Exception {
        return new User("factory", "111111");
    }

    @Override
    public Class<?> getObjectType() {
        return null;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }
}

相应bean配置如下(注意,这里配置的类型为FactoryBeanTest):

<!--工厂bean-->
<bean id="factoryBean" class="di.pojo.FactoryBeanTest"/>

相应单元测试如下(注意,这里返回的类型为User)

@Test
public void demo7() {
    User user = context.getBean("factoryBean", User.class);
    System.out.println(user);
}

bean作用域

创建bean配置的对象是否为单例,默认为单例。

可以通过设置bean标签的scope,设置创建的对象是否为单例

prototype 非单例

singleton 单例

<bean id="user" class="di.pojo.User" scope="prototype"/>

bean生命周期

生命周期:

一个对象从创建到销毁的周期

bean的生命周期

1.调用构造方法构造对象

2.调用set方法设置属性

3.将对象传入后置处理器重写的postProcessBeforeInitialization方法

4.调用xml配置的初始化方法

5..将对象传入后置处理器重写的postProcessAfterInitialization方法

6.真正使用对象

7.销毁对象,通过ClassPathXmlApplicationContext的close方法销毁,销毁时会调用xml配置的注销方法

<!--演示bean的生命周期-->
<bean id="beanLifeCycle" class="di.pojo.lifecycle.BeanLifeCycle" init-method="init" destroy-method="destroy">
    <property name="str" value="nothing"/>
</bean>

<!--配置后置处理器-->
<bean id="myPostProcessor" class="di.pojo.lifecycle.LifeOfPostProcessor"/>

后置处理器类

public class LifeOfPostProcessor  implements BeanPostProcessor {
    // 所有配置的bean都会调用这里
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("第三步:调用初始化方法之前" + beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("第五步:调用初始化方法之后" + beanName);
        return bean;
    }
}

基于注解管理bean

使用注解创建bean对象

@Component :通用标识bean对象的注解

@Service:标识业务层的bean对象的注解(Service层)

@Controller:标识控制器层的bean对象的注解(Web层)

@Repository:标识数据持久层的bean对象的注解(Dao层或者说Mapper层)

*这四个注解都可以标识一个bean,使其可以让IOC容器管理,但通常用不同的注解标识不同的层,更好区分。

// 默认值以类的首字母小写,相当于<bean id="components" class="di.component.Components"/>
@Component(value = "components")
public class Components {
    public void simple(){
        System.out.println("Components simple function");
    }
}

使用注解注入属性

@Autowired 通过类型注入属性

@Qualifier 通过名称注入属性,必须和@Autowired配合使用

@Resource 通过类型或者名称注入属性,位于javax.annotation.Resource,并不属于spring框架

@Value 注入普通类型属性

例如:

@Service(value = "userService")
public class UserService {
    @Autowired  // 通过类型输入属性
    @Qualifier("userImpl2")  // 如果UserDao接口有多个实现类,就需要该注解通过名称注入属性了
    private UserDao userDao;

    @Value(value = "8080")
    private String port;
    
//  @Resource   位于javax.annotation.Resource,但是现在不见了。。。。
    public void simple(){
        System.out.println("UserService simple function");
    }
    public void userDaoMethod(){
        System.out.println("port:" + port);
        System.out.println("userDao.simple:");
        userDao.simple();
    }
}

当然仅仅是有注解还不行,spring并不知道哪些是需要管理的bean,所以需要配置,配置的方法有两种,一种是基于xml配置,一种是基于注解@Configuration配置

基于xml配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="//www.springframework.org/schema/beans"
       xmlns:xsi="//www.w3.org/2001/XMLSchema-instance"
       xmlns:contex="//www.springframework.org/schema/context"
       xsi:schemaLocation="//www.springframework.org/schema/beans
        //www.springframework.org/schema/beans/spring-beans.xsd
        //www.springframework.org/schema/context
        //www.springframework.org/schema/context/spring-context.xsd">

    <!--扫描ioc包下所有的注解-->
    <contex:component-scan base-package="ioc">
    </contex:component-scan>

</beans>

基于注解@Configuration配置

//完全注解开发,不依赖xml配置文件
@Configuration
@ComponentScan(basePackages = "ioc")
public class SpringConfig {
}