Spring深入学习(一)——SpringIoc的理解

4 篇文章 0 订阅
2 篇文章 0 订阅

SpringIoc的理解

1、概念:控制反转(Inversion of Control),是面向对象编程中的一种设计原则,可以用来降低计算机代码之间的耦合度。最常见的实现方式叫做依赖注入(Dependency Injection),还有一种方式叫“依赖查找”(Dependency lookup)。Ioc控制反转是指将由我们控制的创建对象及获取依赖对象,交给IOC容器控制,由容器帮我们创建对象并关注依赖对象,控制对外部资源的获取。
2、使用Ioc的原因:在程序开发过程中,使用面向抽象编程,面向抽象编程会产生类的依赖,spring为我们提供了管理的容器,即Ioc。有了管理容器后,类的产生过程交给了容器,我们就不用关心对象的产生了。
3、Ioc实现的思路和方法:首先需要提供一些配置信息用来描述类之间的关系,然后由容器去解析这些配置信息,继而维护好对象之间的依赖关系,前提是对象间的依赖关系必须在类中定义好。比如A.class中有一个B.class属性,那么可以理解为A依赖了B。
大致可分为3点:①应用程序中提供类,提供依赖关系(属性或构造方法)。②把需要交给容器管理的对象通过配置信息告诉容器。③把各类之间的依赖关系通过配置信息告诉容器。
4、spring的编程风格(可混合使用)
①schema-based XML方式
②Annotation-based 注解方式(需要结合xml方式或javaconfig方式使用,开启和扫描注解)
③java-based javaconfig方式(使用时需要创建配置类@Configuration,可通过@ImportResource(xml文件)来加入xml配置文件)
注意:前两种方式通过ClassPathXMLApplicationContext解析,javaconfig通过AnnotationConfigApplicationContext解析。
5、Spring对象注入方法
①Constructor-based DI 构造方法注入
②setter-based DI set方法注入
spring3以前还提供了接口注入,但是spring4以后已经不再使用。注意使用XML注入时的p空间注入(p:name)和c空间注入(c:name)。
6、自动装配:只需在类中定义对象的依赖关系,而不需要在spring中配置依赖关系,这就是通过自动装配来实现。

自动装配方法:
①no 不自动装配,需要提供对象间依赖的配置(默认方法)
②byType 按类型装配
③byName 按名称装配
④constructor 类似于byType ,但适用于构造函数参数,容器中不能有多个构造函数

XML方式:在< beans >标签中加入default-autowire=类型,来指定自动装配的方法,也可以对某个< bean >单独指定自动装配方法。需要注意的是按名称装配时,名称与set方法的值关联。
注解方式:使用@Autowired注解或@Resource注解。

@Autowired和@Resource区别:它们都可以用来自动装配bean,都可以写在字段上或setter方法上。@Autowired属于spring,默认按类型装配,如果没有找到才会按名称查找,默认是必须存在的,可以通过required属性改为false,即可允许null值。指定按名称装配可以结合@Qualifier注解进行使用。@Resource属于J2EE,默认按照名称装配,名称可通过name属性进行指定,如果没指定name属性,当注解写在属性上时,默认取属性名进行查找,如果注解写在setter方法上时,默认取setter方法中set后的值第一个字母小写进行装配。当找不到名称匹配的bean时,才会按照类型进行装配。但name或type属性一旦指定,必须按照对应值装配,找不到则报错。用名称装配速度更快。
7、spring懒加载
在第一次请求时,Ioc容器才实例化Bean,而不是在初始化时就创建。xml中全局设置为懒加载,即在< beans >标签中增加属性default-lazy-init=true;给某个bean设置为懒加载,则在< bean >标签中增加属性lazy-init=true。注解和javaconfig方式在对应类中加入@Lazy注解即可实现懒加载。
8、spring的Bean作用域
注解@Scope。
singlton 单例,每次访问都是同一个Bean对象(spring中默认)
prototype 原型,每次访问都是新的Bean对象
request
session
application
websocket

注意问题:
Singleton Beans with Prototype-bean Dependencies:在Singleton 当中引用了一个Prototype的bean,会造成Prototype作用域的bean也只能使用一个bean对象。
解决方法:
①实现ApplicationContextAware接口,重写setApplicationContext()方法获取ApplicationContext对象,通过此对象getBean获取Prototype作用域的bean。
②使用@Lookup(bean名)注解(在XML中可以使用< lookup-method >标签)查找Prototype作用域的bean,这时就不需要自动装配。
例:@Lookup(“dao”)
public abstract Dao getDao();
通过 getDao()即可获取bean对象。
9、spring生命周期的回调
①Initialization callbacks 初始化回调
实现InitializingBean接口,重写afterPropertiesSet方法,该方法会在对象创建后初始化时调用。
Destruction callbacks 销毁回调
实现DisposableBean接口,重写destroy()方法,该方法在对象销毁时调用。
②Default Initialization and Destroy Methods 默认的初始化和销毁方法
在XML配置中,增加< beans > 标签的default-init-method=‘方法名’或default-init-destroy=‘方法名’属性,在对应类中重写方法名方法即可。
③@Postconstruct和@Predestroy注解,分别表示初始化时调用方法和销毁时调用方法。

10、spring其他常用注解
①@ComponentScan:用于扫描文件
②@Primary:在多个对象进行选择时使用,当有多个数据源时,设为主源,spring在读取时会优先选择这个注解标记的类。如@Autowired装配Bean时,有多个相同类型Bean,可以设置其中一个为主类,spring会使用此类进行装配。
③@Profile:用于环境切换,在对应环境下生效。可以用于切换某个bean,也可以用于切换整个配置文件。
例:

public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext
                = new AnnotationConfigApplicationContext();
        //切换到@Profile的环境
        annotationConfigApplicationContext.getEnvironment().setActiveProfiles("@Profile的名字");
        annotationConfigApplicationContext.register(AppConfig.class);
        annotationConfigApplicationContext.refresh();

        TestService service = annotationConfigApplicationContext.getBean(TestService.class);

        System.out.println(service.getName());

    }

④@Bean依赖,可以作为参数传入到方法中

@Bean
    public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        //或者直接使用方法引入
        //sqlSessionFactoryBean.setDataSource(dataSource());
        return sqlSessionFactoryBean;
    }

    @Bean
    public DataSource dataSource(){
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setPassword("root");
        dataSource.setUsername("root");
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3308/turtle?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC");
        return dataSource;
    }

⑤@Component是@Service,@Repository和@Controller的父类,后面的注解只是将功能细分,方便查找管理。spring文档上提示将来可能会增加另外的含义,所以我们使用时最好按功能使用不同注解。
⑥可以用java注解代替spring注解使用。如@Inject代替@Autowired;@Named代替@Component;@Singleton代替@Scope(“singleton”)等。但都有局限性,如下表(来自官方文档)。
在这里插入图片描述
11、自定义注解
注解:描述数据的数据。可以在编译类加载、运行时被读取。
分类:
内建注解,标准注解类型。如:@Override,@SuppressWarnings等
元注解,修饰注解的注解。如:@Target(用于指定注解可使用的位置),@Retention(用于标注注解存活时间的长短)等
自定义注解:自己定义的注解,通过关键字@interface实现。接口名即为注解名,接口中的方法即为注解中可加的属性。
例:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Entity {

    public String value() default "";

}

@Entity("student")
public class Student {
    private String id;
    private String name;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

总结,初步了解了Ioc的原理及使用和spring的一些功能,为后面的源码学习打基础,一步步掌握spring。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值