spring入门-Bean

简介spring

  • Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One J2EE Development and Design中阐述的部分理念和原型衍生而来
  • 轻量级:与EJB对比,依赖资源少,销毁的资源少。

spring由来

Expert One-to-One J2EE Design and Development
Expert One-to-One J2EE Development without EJB

spring核心

  • 控制反转(IoC)(Inverse of Control)原本是自己控制对象变成由spring控制bean对象
  • 面向切面(AOP)

spring优点

  • 方便解耦,简化开发 (高内聚低耦合)
  • Spring就是一个大工厂(容器),可以将所有对象创建和依赖关系维护,交给Spring管理
  • spring工厂是用于生成bean
  • AOP编程的支持
  • Spring提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能
  • 声明式事务的支持
  • 只需要通过配置就可以完成对事务的管理,而无需手动编程
  • 方便程序的测试
  • Spring对Junit4支持,可以通过注解方便的测试Spring程序
  • 方便集成各种优秀框架
  • Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架(如:Struts、Hibernate、MyBatis、Quartz等)的直接支持
  • 降低JavaEE API的使用难度
  • Spring 对JavaEE开发中非常难用的一些API(JDBC、JavaMail、远程调用等),都提供了封装,使这些API应用难度大大降低

配置环境

  1. 引入jar
    下载四个核心(beans、core、context、expression) + 1个依赖(commons-loggins.jar)
    四个核心:spring-framework的lib目录下
    依赖下载:commons-loggins.jar

IOC(控制反转)入门

  • 之前开发中,直接new一个对象即可。
  • 学习spring之后,将由Spring创建对象实例–> IoC 控制反转(Inverse of Control)之后需要实例对象时,从spring工厂(容器)中获得,需要将实现类的全限定名称配置到xml文件中
  • 就是把创建对象的控制权反转给了spring,以前是通过new,现在是通过spring创建
  1. 创建Bean类

    1
    2
    3
    4
    5
    public class TestClass {
    public void add() {
    System.out.println("a_add");
    }
    }
  2. 创建配置文件
    在任意地址创建一个任意名字的xml文件,但是默认是在src目录下创建一个applicationContext.xml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 配置service
    <bean> 配置需要创建的对象
    id :用于之后从spring容器获得实例时使用的
    class :需要创建实例的全限定类名
    -->
    <bean id="TestClassId" class = "cn.xwmdream.springMain.TestClass"></bean>

    </beans>
  3. spring读取xml文件调用类

    1
    2
    3
    4
    5
    6
    7
    8
    //读取xml文件
    String xmlPath = "applicationContext.xml";
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);

    //通过xml中的id创建类
    TestClass test = (TestClass)applicationContext.getBean("TestClassId");
    //调用类方法
    test.add();

DI(依赖注入)入门

  • DI Dependency Injection ,依赖注入

概念

1
2
3
class B{
private A a;//这就是B类依赖于A类
}
  • 依赖:一个对象需要使用另外一个对象
  • 注入:通过setter(set&get的那个set)方法进行另一个对象实例设置
    1
    2
    3
    4
    5
    6
    7
    //原来是
    private B b = new B();
    //spring之后是
    private B b;
    public void setB(B b){
    this.b = b;
    }

模拟spring执行过程

动作 实现 对应spring 对应xml标签
创建service Service service = new Service() IOC <bean>
创建dao Dao dao = new Dao() IOC <bean>
把dao设置给service service.setDao(dao) DI <property>

入门实例

  1. Dao.java

    1
    2
    3
    4
    5
    public class Dao {
    public void add() {
    System.out.println("a_add");
    }
    }
  2. Service.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    public class Service {
    private Dao dao;
    public void setDao(Dao dao) {
    this.dao = dao;
    }
    public void addDao() {
    dao.add();
    }
    }
  3. 配置文件
    applicationContext.xml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--
    <property> 用于进行属性注入
    name: bean中的属性名,通过setter方法获得
    setBookDao ##> BookDao ##> bookDao
    ref :另一个bean的id值的引用
    -->

    <!-- 创建service -->
    <bean id="serviceId" class="cn.xwmdream.springMain.Service">
    <property name="dao" ref="DaoId"></property>
    </bean>
    <!-- 创建dao实例 -->
    <bean id="DaoId" class="cn.xwmdream.springMain.Dao"></bean>
    </beans>
  • 解释一下property标签,是因为Service类中有一个Dao的成员名字叫dao,所以name为dao,他是一个Dao类,引用Dao类的id,所以是DaoId

核心api

spring关系树

  • BeanFactory :这是一个工厂,用于生成任意bean。采取延迟加载,第一次getBean时才会初始化Bean
  • ApplicationContext:是BeanFactory的子接口,功能更强大。(国际化处理、事件传递、Bean自动装配、各种不同应用层的Context实现)。当配置文件被加载,就进行对象实例化。
  • ClassPathXmlApplicationContext 用于加载classpath(类路径、src)下的xml。加载xml运行时位置 –> /WEB-INF/classes/…xml
  • FileSystemXmlApplicationContext 用于加载指定盘符下的xml。加载xml运行时位置 –> /WEB-INF/…xml
  • 通过java web ServletContext.getRealPath() 获得具体盘符

Bean装配基于xml

实例化方式

  • 3种bean实例化方法:默认构造,静态工厂,实例工厂

默认构造

上面ioc用配置文件实例化对象的方法必须有默认构造方法

1
<bean id="" class=""></bean>必须有默认构造方法

静态工厂

  • 常用于spring整合其他框架(工具)
  • 静态工厂:用于生产实例对象,所有的方法必须是static
    1
    <bean id="" class="工厂全限定类名" factory-method="静态方法"></bean>
举个栗子
  1. 创建工厂
    DaoFactory.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class MyBeanFactory {
    public static Dao createDao() {
    return new Dao();
    }
    }
    class Dao {
    public void add() {
    System.out.println("a_add");
    }
    }
  2. 配置信息
    applicationContext.xml

    1
    2
    3
    4
    5
    <!-- 将静态工厂创建的实例交予spring
    class 确定静态工厂全限定类名
    factory-method 确定静态方法名
    -->
    <bean id="daoFactoryId" class="cn.xwmdream.springMain.MyBeanFactory" factory-method="createDao"></bean>
  3. 调用

    1
    2
    3
    4
    5
    6
    7
    8
    //自定义工厂
    Dao dao = MyBeanFactory.createDao();
    dao.add();
    //spring工厂
    String xmlPath = "applicationContext.xml";
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
    Dao dao1 = applicationContext.getBean("daoFactoryId",Dao.class);
    dao1.add();

实例工厂

  • 实例工厂:必须先有工厂实例对象,通过实例对象创建对象。提供所有的方法都是“非静态”的。
栗子
  1. 创建工厂
    DaoFactory.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class MyBeanFactory {
    public Dao createDao() {
    return new Dao();
    }
    }
    class Dao {
    public void add() {
    System.out.println("a_add");
    }
    }
  2. 配置信息
    applicationContext.xml

    1
    2
    3
    4
    5
    6
    7
    <!-- 创建工厂实例 -->
    <bean id="myBeanFactoryId" class="cn.xwmdream.springMain.MyBeanFactory"></bean>
    <!-- 获得userservice
    * factory-bean 确定工厂实例
    * factory-method 确定普通方法
    -->
    <bean id="myDaoId" factory-bean="myBeanFactoryId" factory-method="createDao"></bean>
  3. 调用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    //自定义工厂
    MyBeanFactory myBeanFactory = new MyBeanFactory();
    Dao dao = myBeanFactory.createDao();
    dao.add();
    //spring工厂
    String xmlPath = "applicationContext.xml";
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
    Dao dao1 = applicationContext.getBean("myDaoId",Dao.class);
    dao1.add();

Bean种类

普通bean

之前操作的都是普通bean。 ,spring直接创建A实例,并返回

FactoryBean

  • 是一个特殊的bean,具有工厂生成对象能力,只能生成特定的对象
  • bean必须使用 FactoryBean接口,此接口提供方法 getObject() 用于获得特定bean。
    先创建FB实例,使用调用getObject()方法,并返回方法的返回值
    相当于
    1
    2
    FB fb = new FB();
    return fb.getObject();

BeanFactory 和 FactoryBean 对比

  • BeanFactory:工厂,用于生成任意bean。
  • FactoryBean:特殊bean,用于生成另一个特定的bean。例如:ProxyFactoryBean ,此工厂bean用于生产代理。 获得代理对象实例。AOP使用

作用域

  • 作用域:用于确定spring创建bean实例个数
    spring作用域
  • 取值:
  1. singleton 单例,默认值。
  2. prototype 多例,每执行一次getBean将获得一个实例。例如:struts整合spring,配置action多例。
  • 配置信息
    1
    <bean id="" class=""  scope="取值类型"></bean>

生命周期

一共有十一个生命周期Spring Bean的生命周期(非常详细)

初始化和销毁

  • 目标方法执行前后执行后,将进行初始化或销毁。
    1
    2
    3
    4
    5
    <!--
    init-method 用于配置初始化方法,准备数据等
    destroy-method 用于配置销毁方法,清理资源等
    -->
    <bean id="" class="" init-method="初始化方法名称" destroy-method="销毁的方法名称">
1
2
3
4
5
//要求:1.容器必须close,销毁方法执行; 2.必须是单例的
//applicationContext.getClass().getMethod("close").invoke(applicationContext);
// * 此方法接口中没有定义,实现类提供
//先把applicationContext定义成ClassPathXmlApplicationContext类型,然后调用close方法
applicationContext.close();
  • 容器必须close,销毁方法才能执行
  • bean类不能是prototype(多例),否则不能调用销毁方法

BeanPostProcessor 后处理Bean

  • 有两个方法,before和after
  • spring 提供一种机制,只要实现此接口BeanPostProcessor,并将实现类提供给spring容器,spring容器将自动执行,在初始化方法前执行before(),在初始化方法后执行after()。

  • 文档中的描述:Factory hook(勾子) that allows for custom modification of new bean instances, e.g. checking for marker interfaces(接口) or wrapping(装饰者) them with proxies(代理).

  • spring提供工厂勾子,用于修改实例对象,可以生成代理对象,是AOP底层。

  • 模拟

    1
    2
    3
    4
    5
    6
    A a =new A();
    a = B.before(a)//before方法是在对象init前调用
    a.init();//初始化
    a = B.after(a);//after是在对象初始化后调用,可以在此返回代理对象,目的在目标方法前后执行(例如:开启事务、提交事务)
    a.addUser();
    a.destroy()
  • B类实现了BeanPostProcessor接口,所以在A用spring实例化的前后会调用B.before(a)和B.after(a)

  • 可以在before和after去写一些代码,比如可以在after中创建一个代理,代理可以在目标执行一些函数的前后执行一些操作,比如开启提交事务、计时等操作
  • 如果是要创建代理,必须是接口创建类
  • BeanPostProcessor只需要在配置文件中写入class参数即可
例子
  1. 配置文件

    1
    2
    3
    4
    5
    <!-- 一个普通的类 -->
    <bean id="daoFactoryId" class="cn.xwmdream.springMain.MyBeanFactory" init-method="init" destroy-method="destroy"></bean>

    <!-- BeanPostProcessor在配置中声明 -->
    <bean class="cn.xwmdream.springMain.MyBeanPostProcessor"></bean>
  2. 创建一个BeanPostProcessor
    MyBeanPostProcessor.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24

    public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    System.out.println("前方法 : " + beanName);
    return bean;
    }
    @Override
    public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException {
    System.out.println("后方法 : " + beanName);
    return Proxy.newProxyInstance(
    MyBeanPostProcessor.class.getClassLoader(),
    bean.getClass().getInterfaces(),
    new InvocationHandler(){
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    System.out.println("------开启事务");
    //执行目标方法
    Object obj = method.invoke(bean, args);
    System.out.println("------提交事务");
    return obj;
    }});
    }
    }
  • 在before中是原封不动的返回
  • 在after中使用了代理,返回去的对象调用方法时候会执行”开启事务”/“提交事务”那一段代码
  • 注意:使用代理的对象必须是用接口调用方法
  • 注意Proxy、Method、InvocationHandler都是引用自java.lang.reflect.包下的
  1. 创建接口
    MyInterface.java

    1
    2
    3
    public interface MyInterface {
    public void da();
    }
  2. 创建实现类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public class MyBeanFactory implements MyInterface{
    public void da() {
    System.out.println("da");
    }
    public void destroy() {
    System.out.println("销毁了");
    }
    public void init() {
    System.out.println("创建了");
    }
    }
  3. 执行

    1
    2
    3
    4
    5
    6
    //spring工厂
    String xmlPath = "applicationContext.xml";
    ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
    MyInterface myBeanFactory = (MyInterface) applicationContext.getBean("daoFactoryId");
    myBeanFactory.da();
    applicationContext.close();

执行结果:
前方法 : daoFactoryId
创建了
后方法 : daoFactoryId
——开启事务
da
——提交事务
销毁了

  • 可以用此方法在after中给创建的对象创建代理,但是必须是用接口调用才行

属性依赖注入

  • 依赖注入方式:手动装配 和 自动装配
  • 手动装配:一般进行配置信息都采用手动
  1. 基于xml装配:构造方法、setter方法
  2. 基于注解装配:
  • 自动装配:struts和spring 整合可以自动装配
  1. byType:按类型装配
  2. byName:按名称装配
  3. constructor构造装配,
  4. auto: 不确定装配。

构造方法

  1. 目标类
    User.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    public class User {
    private String username;
    private Integer age;
    public User(Integer age, String username) {
    System.out.println("构造方法1");
    this.age = age;
    this.username = username;
    }
    public User(String username, Integer age) {
    System.out.println("构造方法2");
    this.username = username;
    this.age = age;
    }
    @Override
    public String toString() {
    return "User [username=" + username + ", age=" + age + "]";
    }
    }
  2. spring配置
    applicationContext.xml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    <!-- 构造方法注入
    * <constructor-arg> 用于配置构造方法一个参数argument
    name :参数的名称
    value:设置普通数据
    ref:引用数据,一般是另一个bean id值
    index :参数的索引号,从0开始 。如果只有索引,匹配到了多个构造方法时,默认使用第一个。
    type :确定参数类型
    例如:使用名称name
    <constructor-arg name="username" value="jack"></constructor-arg>
    <constructor-arg name="age" value="18"></constructor-arg>
    例如2:【类型type 和 索引 index】
    <constructor-arg index="0" type="java.lang.String" value="1"></constructor-arg>
    <constructor-arg index="1" type="java.lang.Integer" value="2"></constructor-arg>
    -->
    <bean id="userId" class="cn.xwmdream.springMain.User" >
    <constructor-arg index="0" type="java.lang.String" value="我的名字"></constructor-arg>
    <constructor-arg index="1" type="java.lang.Integer" value="2"></constructor-arg>
    </bean>
    <bean id="userId1" class="cn.xwmdream.springMain.User" >
    <constructor-arg name="age" value="18"></constructor-arg>
    <constructor-arg name="username" value="还是我的名字"></constructor-arg>
    </bean>
  3. 运行

    1
    2
    3
    4
    5
    6
    String xmlPath = "applicationContext.xml";
    ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
    User user = (User) applicationContext.getBean("userId");
    System.out.println(user);
    user = (User) applicationContext.getBean("userId1");
    System.out.println(user);

运行结果:
构造方法2
User [username=我的名字, age=2]

  • index是第几个参数,从0开始,上面的配置文件说的是找第一个是String第二个是Integer类型的构造方法写入参数
  • 第二个方式是通过参数名的形式创建构造方法

set方法

  1. 创建bean类
    Person.java
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    public class Person {
    private String username;
    private Integer age;
    private Address homeAddress;
    private Address workAddress;
    public String getUsername() {
    return username;
    }
    public void setUsername(String username) {
    this.username = username;
    }
    public int getAge() {
    return age;
    }
    public void setAge(Integer age) {
    this.age = age;
    }
    public Address getHomeAddress() {
    return homeAddress;
    }
    public void setHomeAddress(Address homeAddress) {
    this.homeAddress = homeAddress;
    }
    public Address getWorkAddress() {
    return workAddress;
    }
    public void setWorkAddress(Address workAddress) {
    this.workAddress = workAddress;
    }
    @Override
    public String toString() {
    return "Pserson [username=" + username + ", age=" + age + ", homeAddress=" + homeAddress + ", workAddress="
    + workAddress + "]";
    }
    }

Address.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Address {
private String address;
private String tel;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getTel() {
return tel;
}
public void setTel(String tel) {
this.tel = tel;
}
@Override
public String toString() {
return "Address [address=" + address + ", tel=" + tel + "]";
}
}

  1. 配置文件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    <!-- setter方法注入
    * 普通数据
    <property name="" value="值">
    等效
    <property name="">
    <value>值
    * 引用数据
    <property name="" ref="另一个bean">
    等效
    <property name="">
    <ref bean="另一个bean"/>

    -->
    <bean id="personId" class="cn.xwmdream.springMain.Person">
    <property name="username" value="名字"></property>
    <property name="age">
    <value>1234</value>
    </property>

    <property name="homeAddress" ref="homeAddrId"></property>
    <property name="workAddress">
    <ref bean="workAddrId"/>
    </property>
    </bean>

    <bean id="homeAddrId" class="cn.xwmdream.springMain.Address">
    <property name="address" value="阜南"></property>
    <property name="tel" value="110"></property>
    </bean>
    <bean id="workAddrId" class="cn.xwmdream.springMain.Address">
    <property name="address" value="北京八宝山"></property>
    <property name="tel" value="120"></property>
    </bean>
  • 普通数据
    等效
  • 引用数据
    等效
  1. 运行
    1
    2
    3
    4
    String xmlPath = "applicationContext.xml";
    ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
    Person pserson = (Person) applicationContext.getBean("personId");
    System.out.println(pserson);

运行结果:
Pserson [username=名字, age=1234, homeAddress=Address [address=阜南, tel=110], workAddress=Address [address=北京八宝山, tel=120]]

p命名空间

  • 对“setter方法注入”进行简化,替换,而是在
  • p命名空间使用前提,必须添加命名空间
    上述配置文件可以改成

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="personId" class="cn.xwmdream.springMain.Person" p:username="我的名字" p:age="1234" p:homeAddress-ref="homeAddrId" p:workAddress-ref="workAddrId">
    </bean>

    <bean id="homeAddrId" class="cn.xwmdream.springMain.Address" p:address="安阳" p:tel="110">
    </bean>
    <bean id="workAddrId" class="cn.xwmdream.springMain.Address" p:address="北京" p:tel="120">
    </bean>
    </beans>
  • 注意加上第三行的命名空间,空间地址就是第一行的beans换成p

SpEL

  • 进行统一编程,所有的内容都使用value

    #{123}、#{‘jack’} : 数字、字符串
    #{beanId} :另一个bean引用
    #{beanId.propName} :操作数据
    #{beanId.toString()} :执行方法
    #{T(类).字段|方法} :静态方法或字段
1
2
3
4
5
6
7
8
9
10
11
<!--
<property name="cname" value="#{'jack'}"></property>
<property name="cname" value="#{customerId.cname.toUpperCase()}"></property>
通过另一个bean,获得属性,调用的方法
<property name="cname" value="#{customerId.cname?.toUpperCase()}"></property>
?. 如果对象不为null,将调用方法
-->
<bean id="customerId" class="com.itheima.f_xml.d_spel.Customer" >
<property name="cname" value="#{customerId.cname?.toUpperCase()}"></property>
<property name="pi" value="#{T(java.lang.Math).PI}"></property>
</bean>

集合注入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<!--
集合的注入都是给<property>添加子标签
数组:<array>
List:<list>
Set:<set>
Map:<map> ,map存放k/v 键值对,使用<entry>描述
Properties:<props> <prop key=""></prop> 【】

普通数据:<value>
引用数据:<ref>
-->
<bean id="collDataId" class="com.itheima.f_xml.e_coll.CollData" >
<property name="arrayData">
<array>
<value>DS</value>
<value>DZD</value>
<value>屌丝</value>
<value>屌中屌</value>
</array>
</property>

<property name="listData">
<list>
<value>于嵩楠</value>
<value>曾卫</value>
<value>杨煜</value>
<value>曾小贤</value>
</list>
</property>

<property name="setData">
<set>
<value>停封</value>
<value>薄纸</value>
<value>关系</value>
</set>
</property>

<property name="mapData">
<map>
<entry key="jack" value="杰克"></entry>
<entry>
<key><value>rose</value></key>
<value>肉丝</value>
</entry>
</map>
</property>
<property name="propsData">
<props>
<prop key="a">aa</prop>
<prop key="b">bb</prop>
<prop key="c">cc</prop>
</props>
</property>
</bean>

装配Bean 基于注解

详情请参考

  • 用注解替代xml文件
  • @Component取代@Component(“id”) 取代

  • web开发,提供3个@Component注解衍生注解(功能一样)取代
    @Repository :dao层
    @Service:service层
    @Controller:web层
    这三个注解和Component功能一样,只是用来区分不同的层,例如springmvc

  • 依赖注入 ,给私有字段设置,也可以给setter方法设置
    普通值:@Value(“”)
    引用值:
    方式1:按照【类型】注入

    @Autowired
    

    方式2:按照【名称】注入1

    @Autowired
    @Qualifier("名称")
    

    方式3:按照【名称】注入2

    @Resource("名称")
    方式3就是方式2两种注解合在一起,一样
    

4.生命周期
初始化:@PostConstruct
销毁:@PreDestroy
5.作用域
@Scope(“prototype”) 多例

  1. 配置xml为扫描所需要的包

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <?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">
    <!-- 组件扫描,扫描含有注解的类 -->
    <context:component-scan base-package="cn.xwmdream.springMain"></context:component-scan>
    </beans>
  2. 开始表演
    详情请参考

总结

编写流程

  1. 导入jar包:4+1 –> beans,core,context,expression,commons-logging
  2. 编写目标类:dao和service
  3. spring配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    IoC:<bean id="" class="" >
    DI:<bean> <property name="" value="" | ref="">
    实例化方式:
    默认构造
    静态工厂:<bean id="" class="工厂类" factory-method="静态方法">
    实例工厂:<bean id="工厂id" class="工厂类"> <bean id="" factory-bean="工厂id" factory-method="方法">
    作用域:<bean id="" class="" scope="singleton | prototype">
    生命周期:<bean id="" class="" init-method="" destroy-method="">
    后处理bean BeanPostProcessor接口,<bean class="注册"> ,对容器中所有的bean都生效
    属性注入
    构造方法注入:<bean><constructor-arg index="" type="" >
    setter方法注入:<bean><property>
    p命名空间:简化<property> <bean p:属性名="普通值" p:属性名-ref="引用值"> 注意声明命名空间
    SpEL:<property name="" value="#{表达式}">
    #{123} #{'abc'}
    #{beanId.propName?.methodName()}
    #{T(类).静态方法|字段}
    集合
    数组<array>
    List <list>
    Set <set>
    Map <map><entry key="" value="">
    Properties <props><prop key="">....
  4. 核心api

  • BeanFactory,延迟实例化bean,第一次调用getBean
  • ApplicationContext 一般常用,功能更强
    ClassPathXmlApplicationContext 加载classpath xml文件
    FileSystemXmlApplicationContext 加载指定盘符文件 , ServletContext.getRealPath()

后处理bean对单一对象生效

1
2
3
4
5
6
7
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if("userServiceId".equals(beanName)){
System.out.println("前方法 : " + beanName);
}
return bean;
}

### 注解
1. 扫描含有注解的类

1
<context:component-scan base-package="....">

2. 常见的注解

  • @Component 组件,任意bean
    WEB
    @Controller web层
    @Service service层
    @Repository dao层
  • 注入 –> 字段或setter方法
    普通值:@Value
    引用值:
    类型:@Autowired
    名称1:@Autowired  @Qualifier("名称")
    名称2:@Resource("名称")
    
  • 作用域:@Scope(“prototype”)
  • 生命周期:
    初始化:@PostConstruct
    销毁方法:@PreDestroy

注解和xml混合使用

  1. 将所有的bean都配置xml中
  2. 将所有的依赖都使用注解
    @Autowired
    默认不生效。为了生效,需要在xml配置:context:annotation-config

总结:

  1. 一般情况两个注解不一起使用。
  2. “注解1”扫描含有注解(@Component 等)类,注入注解自动生效。
    “注解2”只在xml和注解(注入)混合使用时,使注入注解生效。