spring-ioc基础学习(2)基于注解方式的ioc配置

使用java注解的方式去实现IOC的配置

主要目标:

  • 1.学习spring基于java注解的配置方式
  • 2.熟悉spring配置注解

进行环境搭建

  • 1.创建maven项目
  • 2.引入spring依赖包
<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.6.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.21</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.47</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
</dependencies>
  • 3.创建spring-ioc.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
  • 4.创建数据库配置文件db.properties
mysql.username=mall
mysql.password=mall
mysql.url=jdbc:mysql://192.168.1.150:3306/mall
mysql.driver=com.mysql.jdbc.Driver
  • 5.创建接口和类
com.learn.controller
UserController
com.learn.service
IUserService
com.learn.service.impl
UserServiceImpl
com.learn.dao
IUserDao
com.learn.dao.impl
UserDaoImpl
com.learn.bean
User
Role

开始学习基础内容

- 1.对类进行注解标注,将bean注册到容器中有4种方式:

1.使用xml进行配置bean标签
2.使用@Component以及相关的标签进行注解后,使用包扫描方式进行注册
3.使用@Bean注解
4.使用@Import注解

本例主要使用@Component方式进行注册bean

@Component,@Controller,@Service,@Repository 四个注解性质基本相同具体如下:

@Component

@Component:spring 注册组件的注解,@Service,@Controller,@Repository等的注册功能都是由该注解提供,使用该标注后对应类将注册到容器中

源码:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface Component {

    /**
     * The value may indicate a suggestion for a logical component name,
     * to be turned into a Spring bean in case of an autodetected component.
     * @return the suggested component name, if any (or empty String otherwise)
     */
    String value() default "";

}
@Controller

@Controller:控制器,推荐给controller层添加此注解

源码

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {

    /**
     * The value may indicate a suggestion for a logical component name,
     * to be turned into a Spring bean in case of an autodetected component.
     * @return the suggested component name, if any (or empty String otherwise)
     */
    @AliasFor(annotation = Component.class)
    String value() default "";

}
@Service

@Service:业务逻辑,推荐给业务逻辑层添加此注解

源码

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Service {

    /**
     * The value may indicate a suggestion for a logical component name,
     * to be turned into a Spring bean in case of an autodetected component.
     * @return the suggested component name, if any (or empty String otherwise)
     */
    @AliasFor(annotation = Component.class)
    String value() default "";

}
@Repository

@Repository:仓库管理,推荐给数据访问层添加此注解

源码

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Repository {

    /**
     * The value may indicate a suggestion for a logical component name,
     * to be turned into a Spring bean in case of an autodetected component.
     * @return the suggested component name, if any (or empty String otherwise)
     */
    @AliasFor(annotation = Component.class)
    String value() default "";

}

从源码上看@Controller,@Service,@Repository的源码没有区别,只是名称定义不同,实现功能上三者完全一致,只是表示不同意义,方便开发者更直观的定义各个类的意义.
并且能对不同类型的bean进行一个区别,方便进行操作.

2.给各个类加上@Component相关注解

Controller类加上@Controller注解
例如:

@Controller//将组建添加到容器中--标注为控制器
public class UserController 

ServiceImpl相关的类均加上@Service注解
例如:

@Service//配置对象加载到容器中--标注为业务逻辑类
public class UserServiceImpl implements IUserService 

给DaoImpl相关类加上@Repository注解

@Repository//配置对象加载到容器中--标注为数据访问
public class UserDaoImpl implements IUserDao{

给其他需要注册的类加上@Component注解
例如

@Component
public class User 

3.在spring-ioc.xml文件中进行包扫描相关配置,将指定包内的被我们标注要注册的类均注册到spring容器中

示例:

 <context:component-scan base-package="com.learn" >
</context:component-scan>
//base-package为指定的包路径
context:component-scan标签

包含2个子标签,7个属性

如图:
context:component-scan源码

各个标签和属性的意义示例:
<context:component-scan base-package="com.wjx.betalot" <!-- 扫描的基本包路径 -->
                        annotation-config="true" <!-- 是否激活属性注入注解 -->
                        name-generator="org.springframework.context.annotation.AnnotationBeanNameGenerator"  <!-- Bean的ID策略生成器 -->
                        resource-pattern="**/*.class" <!-- 对资源进行筛选的正则表达式,这边是个大的范畴,具体细分在include-filter与exclude-filter中进行 -->
                        scope-resolver="org.springframework.context.annotation.AnnotationScopeMetadataResolver" <!-- scope解析器 ,与scoped-proxy只能同时配置一个 -->
                        scoped-proxy="no" <!-- scope代理,与scope-resolver只能同时配置一个 -->
                        use-default-filters="false" <!-- 是否使用默认的过滤器,默认值true -->
                                  >
            <!-- 注意:若使用include-filter去定制扫描内容,要在use-default-filters="false"的情况下,不然会“失效”,被默认的过滤机制所覆盖 -->                   
            <!-- annotation是对注解进行扫描 -->
            <context:include-filter type="annotation" expression="org.springframework.stereotype.Component"/> 
            <!-- assignable是对类或接口进行扫描 -->
            <context:include-filter type="assignable" expression="com.wjx.betalot.performer.Performer"/>
            <context:include-filter type="assignable" expression="com.wjx.betalot.performer.impl.Sonnet"/>
            
            <!-- 注意:在use-default-filters="false"的情况下,exclude-filter是针对include-filter里的内容进行排除 -->
            <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
            <context:exclude-filter type="assignable" expression="com.wjx.betalot.performer.impl.RainPoem"/>
            <context:exclude-filter type="regex" expression=".service.*"/> 

</context:component-scan>

<context:exclude-filter>和<context:include-filter>两个标签的tyep类型决定加载与排除的规则,具体type类型有如下几种

/*
annotation:按照注解进行排除,标注了指定注解的组件不要,expression表示要过滤
的注解
assignable:指定排除某个具体的类,按照类排除,expression表示不注册的具体类名
aspectj:后面讲aop的时候说明要使用的aspectj表达式
custom:定义一个typeFilter,自己写代码决定哪些类被过滤掉
regex:使用正则表达式过滤
*/

参考链接https://www.cnblogs.com/fightingcoding/p/component-scan.html

4.完成包扫描后可以使用自动注入来获取bean实例

自动注入实现有两个标签分别是

@Autowired
@Resource

@Autowired标签的使用

使用@Autowired来实现自动注入

·默认优先根据类型去匹配
·如果匹配到多个类型则会按照名字匹配
·如果名又没有匹配到则会报错:
1.可以去修改属性的名字对应bean的名字:userServiceImpl
2.可以去修改Bean的名字对应属性的名字:@Service("userService")
3.可以通过@Qualifier设置属性的名字(覆盖) :@Qualifier("userServiceImpl")
4.可以通过@Primary 设置其中一个Bean为主要的自动注入Bean:@Primary
5.使用泛型作为自动注入限定符

注意:
    1. 如果只找到一个,则直接进行赋值
    1. 如果没有找到,则直接抛出异常
    1. 如果找到多个,那么会按照变量名作为id继续匹配
      1. 匹配上直接进行装配
      2. 如果匹配不上则直接报异常
    1. 当定义@Autowired的required为false时,没有匹配上是不会报错的,默认为ture
示例
    /**
     * @Autowired 也可以写在构造器上面
     * ·默认优先根据参数类型去匹配
     * ·如果匹配到多个类型则会按照参数名字匹配*/
    @Autowired
    public UserController(UserService userService) {
        this.userService = userService;
    }
   /**
     * @Autowired 也可以写在方法上面
     * ·默认优先根据参数类型去匹配
     * ·如果匹配到多个类型则会按照参数名字匹配
     * @Qualifier注解也可以作用在属性上,用来被当作id去匹配容器中的对象,如果没有此注解,那么直接按照类型进行匹配
     * @param userService*/
    @Autowired
    public void createUserSerive(@Qualifier("userServiceImpl")UserService userService){
        this.userService=userService;
    }
@Autowired源码
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {

    /**
     * Declares whether the annotated dependency is required.
     * <p>Defaults to {@code true}.
     */
    boolean required() default true;
}

@Autowired和@Resource都可以自动进行bean注入,但是有一定区别

1.@Autowired:是spring中提供的注解,@Resource:是jdk中定义的注解,依靠的是java的标准
2.@Autowired默认是按照类型进行装配,默认情况下要求依赖的对象必须存在,@Resource默认是按照名字进行匹配的,同时可以指定name属性。
3.@Autowired只适合spring框架,而@Resource扩展性更好

5.对类的注入设置依赖关系@DependsOn

使用@DependsOn标签可以设定当前类的注入需要依赖哪些类,将对应类写入其中后,写入的类会优先于当前类加载到容器中

示例
@Repository//配置对象加载到容器中--标注为数据访问
@DependsOn({"user","role"})
public class UserDaoImpl implements IUserDao

6.将类的注入方式设置为懒加载模式@Lazy

使用@Lazy标签标注类后,该类将不会自动加载,而是在主动调用后才进行加载

示例
@Repository//配置对象加载到容器中--标注为数据访问
@Lazy//配置对象为懒加载
public class UserDaoImpl implements IUserDao

7.设定bean的作用域使用@Scope标签

@Scope标签默认为单例模式,可以根据情况设置为原型模式(多实例)

示例
@Repository//配置对象加载到容器中--标注为数据访问
@Scope(value = "prototype")
public class UserDaoImpl implements IUserDao

8.设定生命周期控制使用@PostConstruct和@PreDestroy两个注释

@PostConstruct设置的是bean初始化时的方法;
@PreDestroy设置的是bean销毁时调用的方法

示例
//    配置对象初始化时调用的方法
    @PostConstruct
    public void init(){
        System.out.println(" userDaoImpl init");
    }
//    配置对象销毁时的调用方法
    @PreDestroy
    public void destroy(){
        System.out.println("userDaoImpl destroy");
    }

总结

1.bean注册到容器中的方式
2.@Component的细节和使用
3.包扫描配置方式context:component-scan
4.自动注入@Autowired和@Resource
5.对类的注入设置依赖关系@DependsOn
6.将类的注入方式设置为懒加载模式@Lazy
7.设定bean的作用域使用@Scope标签
8.设定生命周期@PostConstruct和@PreDestroy
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342