Spring4.3.8学习[二]

如果转载文章请注明出处, 谢谢 !
本系列文章是学习完 Spring4.3.8 后的详细整理, 如果有错误请向我指明, 我会及时更正~😝

Spring4.3.8

Spring4.3.8学习[一]

3.4 依赖注入(DI)

控制反转,我们可以把它看作是一个概念。而依赖注入(Dependency Injection)是控制反转的一种实现方法.
James Shore给出了依赖注入的定义:依赖注入就是将实例变量传入到一个对象中去(Dependency injection means giving an object its instance variables)。

3.4.1 xml 形式

3.4.1.1 使用构造器注入

通过参数顺序, 类型等

<bean id="person" class="com.lanou.domain.Person">
    <!--根据参数名称注入-->
    <constructor-arg name="name" value="大老王"/>
    <!--根据索引index注入-->
    <constructor-arg index="1" value="24"/>
    <!--根据构造器参数的类型-->
    <constructor-arg type="java.lang.String" value="men"/>
</bean>

3.4.1.2 使用属性 setter 方法

public class Person {
    private String name;
    private int age;
    private String gender;
    private Car car;
    private List list;
    private Set set;
    private Map map;
    private Properties properties;
    private Object[] objects;
     [属性 setter 方法]
}

简单Bean的注入

<bean name="person" class="com.lanou.domain.Person">
    <!-- property 就是一个bean 的属性
        name 用来描述属性的名称
        value 就是属性值, 一般类型(基本类型和 String)
    -->
    <property name="name" value="狗蛋儿"/>
    <property name="age" value="22"/>
    <property name="gender" value="men"/>
</bean>

引用其他Bean

<bean name="car" class="com.lanou.domain.Car"></bean>
<bean name="person" class="com.lanou.domain.Person">
    <!--spring 容器内部创建的car 对象给 Person 的 car属性赋值-->
    <property name="car" ref="car"/>
</bean>

3.4.1.3 装配 list 集合

<property name="list">
    <list>
        <value>list1</value>
        <ref bean="car"/>
    </list>
</property>

3.4.1.4 装配 set

<property name="set">
    <set>
        <value>set1</value>
        <ref bean="car"/>
    </set>
</property>

3.4.1.5 装配 map

<property name="map">
    <map>
        <entry key="m1">
            <value>map1</value>
        </entry>
        <entry key="m2">
            <ref bean="car"/>
        </entry>
    </map>
</property>

3.4.1.5 装配 properties

<property name="properties">
    <props>
        <prop key="p1">pp1</prop>
        <prop key="p2">pp2</prop>
    </props>
</property>

3.4.1.6 装配 Object[]

<property name="objects">
    <list>
        <value>obj1</value>
        <ref bean="car"/>
    </list>
</property>

3.4.2 注解 Annotation

注解的注入会在XML之前,因此后者配置将会覆盖前者.

配置bean

3.4.2.1 @Component

@Component是所有受 Spring 管理组件的通用形式,泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
@Component 不推荐使用。

@Component
public class Person {
}

3.4.2.2@Controller

@Controller对应表现层的Bean,也就是Action, 例:

@Controller
@Scope("prototype")
public class UserAction {
}

3.4.2.3 @Respository

用于标注数据访问组件,即DAO组件

@Repository
public class UserDao {
} 

3.4.2.4 @Service

用于标注业务层组件

@Service
public class UserServiceImpl {
}


对于扫描到的组件, Spring有默认的命名策略 :
1)使用非限定类名,第一个字母小写
(UserServiceImpl -> userServiceImpl)

2)在注解中通过 value 属性值标识组件的名称
(通常可以将UserServiceImpl -> userService,可以将Impl拿掉,这是一个习惯)

@Service("userService")
public class UserServiceImpl {
}

(3)当在组件类上使用了特定的注解之后, 还需要在 Spring 的配置文件中声明 <context:component-scan>
base-package 属性指定一个需要扫描的基类包,Spring 容器将会扫描这个基类包里及其子包中的所有类.
当需要扫描多个包时, 可以使用逗号分隔.

配置 bean 的属性

3.4.2.5 @Autowired

使用@Autowired 注解自动装配, @Autowired 默认按类型装配.

可以在普通setter方法上使用@Autowired注解

public class UserServiceImpl implements UserService{
    private UserDao userDao;

    @Autowired
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

可以将注解应用到构造器和字段上

public class UserServiceImpl implements UserService{
    private UserDao userDao;

    @Autowired
    public UserServiceImpl(UserDao userDao) {
        this.userDao = userDao;
    }
}
public class UserServiceImpl implements UserService{
    @Autowired
    private UserDao userDao;
}

可以将注解应用到任意名称或参数的方法上

public class UserServiceImpl implements UserService{
    private UserCatalog userCatalog;
    private UserDao userDao;
    
    @Autowired
    public void prepare(UserCatalog catalog, UserDao dao){
        this.userCatalog = catalog;
        this.userDao = dao;
    }

可以把指定类型的所有Bean提供给一个数组类型, 集合类型的变量

public class UserServiceImpl implements UserService{
    @Autowired
    private UserCatalog[] catalogs;
}

xml 中只定义了几个 对应bean

<bean id="userService" class="com.lanou.service.impl.UserServiceImpl"/>
<bean id="dao" class="com.lanou.dao.impl.UserDaoImpl"/>
<bean id="catalog" class="com.lanou.domain.UserCatalog"/>

@Autowired注解是按类型装配依赖对象,默认情况下它要求依赖对象必须存在,一旦找不到对应的Bean,自动注入就会失败。若要改变默认的策略或允许null值,可以设置它required属性为false。

public class UserServiceImpl implements UserService{
      // xml 中没有定义UserFinder的 bean
    @Autowired(required = false)
    private UserFinder userFinder;
}

3.4.2.6 @Qualifier

使用@Qualifier调整基于注解的自动注入.
在指定参数上使用@Qualifier,可以缩小类型匹配的范围,更容易为参数找到指定的Bean。
[想使用按名称装配,可以结合@Qualifier注解一起使用]

public class UserServiceImpl implements UserService{
    @Qualifier("userD")
    @Autowired
    private UserDao userD;
}

对应的Bean定义如下所示。
标识值为“userDe”的Bean将会被标记为@Qualifier(“userDe”)的参数所注入:

<bean id="dao" class="com.lanou.dao.impl.UserDaoImpl">
    <qualifier value="userD"/>
</bean>

如果全部使用注解, 可以在UserDaoImpl中使用Repository配置

@Repository("userDe")
public class UserDaoImpl implements UserDao{
}

3.4.2.7 @Resource

@Resource 注解和@Autowired一样,也可以标注在字段或属性的setter方法上.

@Resource注解默认按名称装配。

名称可以通过@Resource的name属性指定,如果没有指定name属性,
当注解标注在字段上,即默认取字段的名称作为bean名称寻找依赖对象;
当注解标注在属性的setter方法上,即默认取属性名作为bean名称寻找依赖对象。

public class UserServiceImpl implements UserService{
    @Qualifier("userD")
    @Autowired
    private UserDao userD;

    @Resource(name = "daoU")
    private UserDao userDao;
}

注: 如果没有指定name属性,并且按照默认的名称找不到依赖对象时, @Resource注解会回退到按类型装配。但一旦指定了name属性,就只能按名称装配了。

3.4.2.8 @Required

@Required注解应用于Bean属性的setter方法,如下:

public class UserServiceImpl implements UserService{
    private UserDao userDao;
    @Required
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
}

这个表明Bean的属性值必须在配置中指定,可以通过显示的在Bean定义中指定,也可以使用自动注入。若没有为这个属性指定值,那么容器会抛出一个异常。

<bean id="userService" class="com.lanou.service.impl.UserServiceImpl">
    <property name="userDao" ref="dao"/>
</bean>
<bean id="dao" class="com.lanou.dao.impl.UserDaoImpl"/>

3.4.2.8 @PostConstruct & @PreDestroy

生命周期注解
之前的做法是在xml中定义init-method 和 destroy-method方法

public class User {
    public User() {
        System.out.println("user .. 构造函数");
    }
    @PostConstruct
    public void  init(){
        System.out.println("I'm  init  method  using  @PostConstrut....");
    }

    @PreDestroy
    public void  destroy(){
        System.out.println("I'm  destory method  using  @PreDestroy.....");
    }
}

3.5 扫描

spring2.5为我们引入了组件自动扫描机制,它可以在类路径底下寻找标注了@Component、@Service、@Controller、@Repository注解的类,并把这些类纳入进spring容器中管理.

它的作用和在xml文件中使用bean节点配置组件是一样的。要使用自动扫描机制,我们需要打开以下配置信息:

  1. 引入context命名空间 需要在xml配置文件中配置以下信息
  2. 在配置文件中添加context:component-scan标签
<?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">
        
    <!-- 自动扫描指定包及其子包下的所有Bean类 -->
    <context:component-scan base-package="com.lanou.domain"/>

在 base-package 指明一个包, 表明自动扫描目录 com.lanou 包及其子包中的注解,当需要扫描多个包时, 可以使用逗号分隔.
其他用法:

<!-- 通过resource-pattern指定扫描的资源 -->
 <!--只扫描repository下的类-->
<context:component-scan base-package="com.lanou" resource-pattern="dao/*.class"></context:component-scan>

<!-- 不扫描repository注解的类 。可以配置多个。-->
<context:component-scan base-package="com.lanou" >
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
</context:component-scan>

<!--  只扫描repository注解的类。可以配置多个。  -->
<context:component-scan base-package="com.lanou"  use-default-filters="false">
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
</context:component-scan>

<!--  不扫描某个接口。可以配置多个。使用assignable类型   -->
<context:component-scan base-package="com.lanou"  use-default-filters="true">
    <context:exclude-filter type="assignable" expression="com.lanou.dao.UserDao"/>
</context:component-scan>

<!--  只扫描某个接口。 -->
<context:component-scan base-package="com.lanou"  use-default-filters="false">
    <context:include-filter type="assignable" expression="com.lanou.dao.UserDao"/>
</context:component-scan>

3.6 Spring 的继承

public class People {
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}


public class Student extends People {

}
<bean name="people" class="com.lanou.domain.People">
    <property name="name" value="111"/>
</bean>
<bean name="student" class="com.lanou.domain.Student"></bean>
public void testExtents(){
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    Student student = (Student) context.getBean("student");
// student 打印出来的名字为 null  
 System.out.println(student.getName());
}

配置文件需要更改

<!-- parent 实现了 spring 容器内部的继承关系 
       在父类中进行赋值, 子类继承父类内容
-->
<bean name="people" class="com.lanou.domain.People">
    <property name="name" value="111"/>
</bean>
<bean name="student" class="com.lanou.domain.Student" parent="people"></bean>

还有其他方式解决 student 的名字赋值问题么?
student 也继承了 people 的 name setter 方法

Spring4.3.8学习[三]
Spring4.3.8学习之 与 Struts2 整合[四]
Spring4.3.8学习之与Hibernate4 整合[五]
Spring4.3.8学习之S2SH 整合[六]

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,585评论 4 365
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,923评论 1 301
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 110,314评论 0 248
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,346评论 0 214
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,718评论 3 291
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,828评论 1 223
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,020评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,758评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,486评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,722评论 2 251
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,196评论 1 262
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,546评论 3 258
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,211评论 3 240
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,132评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,916评论 0 200
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,904评论 2 283
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,758评论 2 274

推荐阅读更多精彩内容