Spring-IOC注入

Posted Vodka~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring-IOC注入相关的知识,希望对你有一定的参考价值。

一.手动装配:

 <bean id="UserDao" class="com.vodka.dao.UserDao"></bean>
<!--
    set注入: 1.将UserDao作为一个属性,通过IOC注入到UserService中
              2.name: 在使用其他bean对象的某个对象中,自定义的属性字段的名称
              3.ref: 指定bean(作为属性被使用的bean对象)标签的id属性值
-->
     <bean id="UserService" class="com.vodka.service.UserService">
         <property name="UD" ref="UserDao"></property>
     </bean>

    <!--
    IOC通过构造器注入:
          1.通过constructor-arg 标签进行注入
                name:属性名称
                ref: 指定bean标签的id属性值
                value: 指定数据的具体值
                index: 自定义数据,在对象构造器的参数列表中的具体位置(从零开始)
         2.构造器注入会造成循环依赖问题,A构造需要B,B构造需要A;可以通过set方法注入解决,因为set方法是先实例化对象再执行注入
-->
     <bean id="UserServiceTwo" class="com.vodka.service.UserServiceTwo">
          <constructor-arg name="UD" ref="UserDao"></constructor-arg>
         <constructor-arg name="eliminate" value="淘汰"></constructor-arg>
     </bean>


   <!--
    静态工厂注入:
      1.通过静态工厂实例化需要被注入的bean对象
-->
     <bean id="TypeService" class="com.vodka.service.TypeService" >
         <property name="myType" ref="MyType"></property>
     </bean>
    <bean id="MyType" class="com.vodka.factory.StaticFactory" factory-method="createMyType"/>

<!--
   实例化工厂注入:
       1.通过实例化工厂实例化需要被注入的bean对象
-->
    <bean id="instanceFactory" class="com.vodka.factory.instanceFactory"></bean>
    <bean id="TestIOC" factory-bean="instanceIOC"></bean>

        BeanFactory beanFactory = new ClassPathXmlApplicationContext("springConstructor.tld");
        UserService userService = (UserService) beanFactory.getBean("UserService");
        UserDao userDao = (UserDao) beanFactory.getBean("UserDao");
         
         //set方法注入
        userService.setUD(userDao);  
        userService.getUD().Print();

          //构造器注入
        public UserServiceTwo(UserDao UD,String eliminate)
        this.ud = UD;
        this.Eliminate = eliminate;
        
     
        UserServiceTwo userServiceTwo = (UserServiceTwo) beanFactory.getBean("UserServiceTwo");
        userServiceTwo.USTwoTest();

         //静态工厂注入
       public class StaticFactory 
        private MyType myType;

         public static  MyType createMyType()
           return new MyType();
         
       

       public class TypeService 

     private MyType myType;

     public void setMyType(MyType mt)
         this.myType = mt;
     

     public void MyTypeTest()
         System.out.println("TypeService test——");
         myType.TypePrint();
     
  
       
       TypeService typeService = (TypeService) beanFactory.getBean("TypeService");
       typeService.MyTypeTest();

二.p 名称空间的使用:
为了简化setter方法属性注入,引用p名称空间的概念,可以将 子元素,简化为 元素属性配置。
1.属性字段提供set方法
2.在配置文件 spring.xml 引入 p 名称空间:
xmlns:p=“http://www.springframework.org/schema/p”

  <!--
     在配置文件中,已经引入p名称空间
     p:属性名  = "xxx"    引入常量值
     p:属性名-ref = "xxx"  引入其他Bean对象的id属性值
    -->
    <bean id="UserService" class="com.vodka.service.UserService" p:UD-ref="UserDao" p:name="Vodka"></bean>

三.Spring IOC 自动装配 (注入)
-1 注解的方式注入,除了xml配置以外,可以使用注解配置,从而简化配置文件,提高开发速度,让程序看上去更简洁,对于注解的解释,Spring对于注解有专门的解释器,对定义的注解进行解析,实现对应bean对象的注入,通过反射技术实现。

-2 修改配置文件

pom.xml:

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>

<!--    添加spring的配置环境-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version> 5.3.9</version>
    </dependency>
<!--引入java注解相关依赖-->
    <dependency>
      <groupId>javax.annotation</groupId>
      <artifactId>javax.annotation-api</artifactId>
      <version> 1.3.2</version>
    </dependency>

  </dependencies>
<?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
       https://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">

      <!-- 开启自动化装配 -->
      <context:annotation-config/>

      <bean id="studentDao" class="dao.StudentDao"></bean>
      <bean id="userService" class="Service.UserService"></bean>
  
      
<!--      接口实现类-->
      <bean id="implementStuInterface" class="dao.ImplementStuInterface"></bean>

</beans>

-3 给bean对象加入注解

四. @Resource 注解
1.实现原理:注解实现自动注入(反射)
2. 默认根据属性字段名查找相应的bean对象(属性字段名应与id属性值相等)
3. 若属性字段名称未找到,则会通过类型(Class类型)查找
4. 被注入的属性可以提供set方法,也可以不提供
5. 注解可以声明在属性级别或者set方法级别
6. 可以设置name属性,但name属性值必须与bean标签的id属性值一致,若设置了name属性值,则查找时,只会按照name属性值查找bean对象。

//根据name属性查找
    @Resource(name = "sd")
    private StudentDao studentDao; //注入bean对象
   7. 当注入接口时,如果接口只有一个实现则正常实例化,如果接口存在多个实现,则需要使用name属性,指定需要被实例化的bean对象。
//    注入接口 ,若有多个实现类实现了该接口,则应该通过name属性值来匹配
    @Resource(name = "implementStuInterface")
    public InterfaceOfStu interfaceOfStu;

五. @Autowired注解
1.实现自动化注入,默认通过类型(Class类型) 查找bean 对象,与属性字段的名称无关。
2.属性可以提供set方法,也可以不提供set方法。
3.注解可以声明在属性级别或set方法级别。
4.可以添加 @Qualifier 结合使用,通过value 属性值查找bean对象(value属性值必须要设置,且值要与bean标签的id属性值对应)


//   不根据id名称查找,而是根据Class类型查找, 若想根据id名称匹配查找,则需配合@Qualifier 一起使用
    @Autowired
    @Qualifier (value = "sd")
    public   StudentDao studentDaoTwo;

六. Spring IOC 扫描器
1.实际开发中,bean对象的数量众多,手动配置的方式不现实,所以Spring 提供了扫描器,统一管理对象,简化开发配置,提高开发效率。
2.Spring IOC 扫描器:
-设置自动化扫描的范围: 如果bean对象未在指定包范围,即使声明了注解,也无法实例化。
-在需要实例化的Bean对象的相应类中,添加指定的注解(声明在类级别) :bean对象的id属性值,首字母默认小写
Dao层:
@Repository (通常与数据库做交互)
Service层:
@Service (Service层通常需要Dao层的数据,所以注入Dao层)
Controller层:
@Controller ( Controller层通常需要Service层的数据,所以注入Service层)
任意类:
@Component (通常不属于任何层,作为组件使用)

七. 1.Bean的作用域: 默认情况下,从Spring容器中拿到的对象均是单例的。
2.Singleton作用域:

lazy-init:是懒加载,如果等于true时作用是指:Spring容器启动时,不会实例化相应的bean,而是当相应的bean被调用时才去实例化,默认是false,即容器启动时则实例化bean。建议设置为false: 一来可以提前发现潜在的配置文件,二来就是Bean对象在启动时就会设置在单例缓存池中,使用时无需再实例化bean对象,提高程序运行效率。

 <bean id="userFactory" class="com.vodka.Factory.UserFactory"></bean>
 <bean id="userDao" factory-bean="userFactory" factory-method="ProduceUser" lazy-init="true"></bean>

3.默认情况下,被管理的bean只会 IOC容器中存在一个实例,对于所有获取相应bean的操作,Spring容器只返回同一个是利好的bean。

4.什么对象适合作为单例对象: 无状态或状态不可改变的对象适合用单例模式(即不存在改变对象状态的成员变量),如:
Controller层,service层,dao层,无状态对象没有实例变量存在,如user类,有账号密码,账号密码的改变会改变某个对象的状态,破坏线程安全,为了保证了线程的安全性,应使用无状态对象作为单例对象,例如controller层业务对象,通常直接调用service层对象即可,无需担心实例变量引起的改变。

5、prototype作用域:

6.Web应用中的作用域:


7.Bean的生命周期:
-定义: 在配置文件中定义Bean,通过不同的bean标签定义对应的Bean对象
-初始化: IOC容器启动时,自动实例化Bean对象
7.1 在配置文档中通过指定 init-method属性来完成

  <bean id="userFactory" class="com.vodka.Factory.UserFactory" scope="prototype" init-method="Initial">
              <constructor-arg name="ud" ref="UserDao"></constructor-arg>
       </bean>
       <bean id="UserDao" class="com.vodka.dao.UserDao" scope="prototype"></bean>
 
 public void Initial()
        System.out.println("UserFactory had been initialized!");
    
                     7.2  实现 org.springframework.beans.factory.InitializingBean 接口。
public class UserService implements InitializingBean 
 @Override
    public void afterPropertiesSet() throws Exception 
        System.out.println("UserService implement afterPropertiesSet interface");
    

      -Bean的使用:
           使用BeanFactory或 ApplicationContext
     -Bean的销毁:
          一,Spring容器会维护Bean对象的管理,可以指定bean对象的销毁所要执行的方法。
          二,通过 AbstractApplicationContext 对象,调用其 close 方法实现bean 的销毁过程。

8.IOC/DI ——
控制反转:将对象实例化的创建过程转交给外部容器(IOC容器则充当工厂加工的角色);
依赖注入:完成各种赋值操作等等

以上是关于Spring-IOC注入的主要内容,如果未能解决你的问题,请参考以下文章

Spring-IOC注入

Spring-IOC学习笔记-03DI依赖注入

Spring-IOC源码解读3-依赖注入

Spring-IOC源码解读1-整体设计

二:Spring-IOC源码

Spring-IOC容器-Bean管理-基于XML方式超详解!