spring-ioc-1

1.IOC和ID的区别:

  控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。

其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)--->百度:JNDI

解释:IOC是程序所需要达到的目标

  ID是实现IOC的技术手段

  有点类似于orm->mabatis

2.依赖注入

(1)什么是依赖

  A类中有个属性为B类,则称A依赖B

3.为什么要使用springioc

  在日常程序开发过程当中,我们推荐面向抽象编程,面向抽象编程会产生类的依赖,当然如果你够强大可以自己写一个管理的容器,但是既然spring以及实现了,并且spring如此优秀,我们仅仅需要学习spring框架便可。
当我们有了一个管理对象的容器之后,类的产生过程也交给了容器,至于我们自己的app则可以不需要去关系这些对象的产生了。

场景:1.我有N个类维护着List接口的实现这么一个属性,在传统情况下都是List list = new ArrayList();倘若现在业务需求发生了变化,需要变为List list = new LinkedList();name就需要修改N个类,

但是在有spring的情况下,我们只需要修改注入的类(xml方式,annotation方式)即可.

  2.为service添加事务

好处:程序解耦合等等....

4.spring实现IOC的思路和方法

  spring实现IOC的思路是提供一些配置信息用来描述类之间的依赖关系,然后由容器去解析这些配置信息,
继而维护好对象之间的依赖关系,前提是对象之间的依赖关系必须在类中定义好,比如A.class中有一个B.class的属性,那么我们可以理解为A依赖了B。

既然我们在类中已经定义了他们之间的依赖关系那么为什么还需要在配置文件中去描述和定义呢?

spring实现IOC的思路大致可以拆分成3点:

  1.应用程序中提供类,提供依赖关系(属性或者构造方法)

  2.把需要交给容器管理的对象通过配置信息告诉容器(xml、annotation,javaconfig)

  3.把各个类之间的依赖关系通过配置信息告诉容器

配置这些信息的方法有三种分别是:
  (1)xml
  (2)annotation
  (3)avaconfig
维护的过程称为自动注入,自动注入的方法有两种:
  (1)构造方法
  (2)setter
自动注入的值可以是:
(1)对象
(2)数组
(3)map
(4)list
(5)常量比如字符串整形等

 5.spring编程的风格

  • schemal-based-------xml
     
  • annotation-based-----annotation
  • java-based----java Configuration

6.注入的两种方式

spring注入详细配置(字符串、数组等)参考文档:
https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-factory-properties-detailed

(1)Constructor-based Dependency Injection  -----基于构造方法注入

构造方法注入参考文档:
https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-constructor-injection

(2)Setter-based Dependency Injection            -----基于Set注入

setter参考文档:
https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-setter-injection

7.自动装配

上面说过,IOC的注入有两个地方需要提供依赖关系,一是类的定义中,二是在spring的配置中需要去描述。自动装配则把第二个取消了,即我们仅仅需要在类中提供依赖,继而把对象交给容器管理即可完成注入。

在实际开发中,描述类之间的依赖关系通常是大篇幅的,如果使用自动装配则省去了很多配置,并且如果对象的依赖发生更新我们可以不需要去更新配置,但是也带来了一定的缺点

自动装配的优点参考文档:

https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-factory-autowire

缺点参考文档:

https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-autowired-exceptions

自动装配的方法:
1.通过xml方式对bean进行配置
    
<bean id="A" 
          class="com.cg.A">

</bean>
2.通过注解进行配置
  @autowire---spring-aop提供的注解
    默认根据type进行配置,如果一个接口下有两个实现类,则会抛出异常.
    解决方案:@Qualifier(value="xxxxName"),通过bean的名字(如果name不存在根据id,如果id也不存在,返回默认名-->(首字母小写)类名)进行匹配
  @resource(name="xxx")
    先根据指定byname进行匹配,失败则根据默认的name进行匹配,失败则根据type进行匹配.
3.全局autowire
  
<?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/context
        http://www.springframework.org/schema/context/spring-context.xsd
        default-autowire="byName">

指定自动装配的方式,通常使用byName,byTtype

如果有个别类需要特殊处理则可以通过以下方式进行处理

<bean id="A" 
      class="com.cg.A"
      autowire="byName">
<!--设置装配的方式-->
</bean>

8.springBean的作用域

文档参考:
https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-factory-scopes

singleton

(Default) Scopes a single bean definition to a single object instance for each Spring IoC container.

prototype

Scopes a single bean definition to any number of object instances.

PS:倘若存在单例Service,其内部维护着作用域为prototype的Dao,那么从spring容器中获取Service对象中的dao是否是多例的???

测试:

  Dao:

  

@Repository
@Scope(value = "prototype")
//配置多例
public class IndeDaoImpl implements IndexDao { @Override public void get() { System.out.println("dao"+this.hashCode()); } }

  Service:

@Service
//默认单例
public class IndexServiceImpl implements IndexService { @Autowired private IndexDao indexDao; @Override public void get() { indexDao.get(); } }

  Test:

  AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
        IndexService bean1 = ac.getBean(IndexService.class);
        bean1.get();
        IndexService bean2 = ac.getBean(IndexService.class);
        bean2.get();

  console:

dao1195067075
dao1195067075

由实例表明:

  service单例,dao多例的情况,获取service中的dao依旧是单例的.

原因:

  spring只对Singleton范围的对象初始化一次.......

解决方案:

  参考官方文档:

    https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-factory-method-injection

   方案一:

    A solution is to forego some inversion of control. You can make bean A aware of the container by implementing the ApplicationContextAware interface,

    and by making a getBean("B") call to the container ask for (a typically new) bean B instance every time bean A needs it. The following example shows

    this approach:

    一种解决办法是放弃某种反向控制。您可以通过实现applicationcontext - ware接口

    ,以及在bean A每次需要bean B实例时对容器发出getBean(“B”)调用来让bean A知道容器。

    下面的例子展示了这种方法:

    修改Service:

      

@Service
public class IndexServiceImpl implements IndexService,ApplicationContextAware {
   /* @Autowired
    private IndexDao indexDao;*/
    private ApplicationContext ac;
    @Override
    public void get() {
        /*indexDao.get();*/
        IndexDao bean = ac.getBean(IndexDao.class);
        bean.get();
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.ac = applicationContext;
    }
}

    test:

    

  AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
        IndexService bean1 = ac.getBean(IndexService.class);
        bean1.get();
        IndexService bean2 = ac.getBean(IndexService.class);
        bean2.get();

    console:

    

dao306206744
dao827084938

    结果显示:

    dao为多例,测试成功----->由此引申出applicationContextAware接口的实现了有什么用,上例子很好的展示了此接口的用法!!!!

  方案二:

    通过@lookup注解

    

@Service
public abstract class IndexServiceImpl implements IndexService{

    @Override
    public void get() {

        IndexDao indexDao = createIndexDao();
        indexDao.get();
    }
    @Lookup()
  
protected abstract IndexDao createIndexDao(); }

  console:

    dao2038148563
    dao2008966511

  也可以通过注解的方式,笔者就不在此演示.

PS:如有错误,请指正!谢谢

 github:https://github.com/897800754/myLearn/tree/master/springscope

posted @ 2019-07-23 04:20  简单爱1  阅读(120)  评论(0编辑  收藏  举报