初见Sping之Bean

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_30322803/article/details/78457756

初见Sping之Bean

    Spring一款优秀的开源框架,现在已经成为了java开发的标配框架,Spring框架提供的主要特性便是IOC(Inversion  of control,控制反转)和DI(Dependency Injection,依赖注入)。这两个概念紧密联系,却又有些许不同。

一丶依赖注入和控制反转

       (1)Spring 中的控制反转是基于这样的一种场景:

        User  user =new User();

         上述获取对象的方法是直接new出来,对象何时new,在哪里new都是客户端代码直接决定的,这称为硬性编码。

                                                                           User user =spring.getUser();

        上述获取对象的方法是通过一个方法得到的,对象何处创建,创建的对象究竟是User的实例还是User的子类实例等等都是由applicationContex这个容易决定的,想对应的可以称为软编码。从硬性编码到软编码的过程中对象控制权限发生了转移,由客户端的代码转移到了spring,这种过程就是控制反转的含义,就是工厂设计模式的一种体现。

       (2)依赖注入

       依赖注入是基于控制反转概念上的一种延伸,个人理解是对控制反转这种思想的具体应用。考虑如下情景。

class UserService{
    publicUserDao userDao;
}
class UserDao{
}

UserService是一个类,UserDao是其的一个成员变量,在这种情况下Userservice依赖UserDao,UserDao是被依赖类。在spring实现控制反转的概念上,spring需要创建一个Userservice对象,那么对Userservice对象所依赖的UserDao对象进行赋值的过程就是依赖注入,说白了就是一个赋值的过程,只是这个赋值的方法和过程由Spring管理,这点上联系了依赖注入的概念。

二丶Spring在控制反转上的体现

       Spring管理Bean对象的创建是IOC的一种体现,本文主要总结Spring创建Bean对象方式。

        (1)直接利用构造方法创建Bean对象。

         每个对象被创建时都会调用构造方法,此时将这个方法单列出来是因为Spring还有许多绕着弯创建Bean对象的方法,后续会描述。

Bean 对象设置如下:

class User{
       public User(){
              System.out.println(“user构造方法被调用了”);
       }
}

Spring配置文件如下:

<?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-4.3.xsd">
    <bean name="user"class ="com.hello.spring.User"/>
</beans>

测试方法如下:

public class Main{
    publicstatic void main(String []args){
      //获取Spring容器
      ApplicationContextcontext = newClassPathXmlApplicationContext("applicationContext.xml");
     User user =(User)context.getBean("user");
    }
}

输出结果:

                                

            图1程序运行结果

       (2)利用静态工厂的方法创建Bean对象

       方法(1)是Spring直接利用构造方法创建Bean对象,这点从Spring的配置文件中也可以看出来,class属性直接是User类的权限定类型。利用静态工厂创建Spring的方法和上述方法较大不同,下面来看一下代码的组合以及Spring配置文件的改变。

       Bean对象:

 class Bean1{
     publicBean1(){
         System.out.println(“Bean1的方法被调用”)
     }
     public void say(){
     System.out.println(“bean1say good afternoon”);
  }
}

工厂类:

class BeanFactory{
       publicstatic Bean1 getBean(){
         System.out.println(“静态工厂方法被调用”)
              returnnew Bean1();
       }
}
测试代码:
public class Main1{
       publi cstatic void main(String []args){
             ApplicationContextcontext = new ClassPathXmlApplicationContext("applicationContext.xml");
             Bean1 bean1= (Bean1) context.getBean("bean1");
             bean1.Say();
    }
}
Spring的配置文件:

<bean name =”bean1” class=”Bean.BeanFactory”factory-method=”getBean”></bean>

       测试结果:

 

图2 静态工厂运行结果

       从上图的运行结果可以知道,利用这种方式配置Bean时,Spring并不是直接new Bean1(),而是借助工厂类的静态方法创建Bean对象的事例。

       (3)利用实例工厂创建Bean对象

       Bean对象:

class Bean1{
    publicBean1(){
    System.out.println(“Bean1的方法被调用”)
    }
    public void say(){
       System.out.println(“bean1say good afternoon”);
    }
}

工厂类:

class BeanFactory{
       publicBeanFactory(){
           System.out.println(“BeanFactory的构造方法被调用”)
      }
       publicstatic Bean1 getBean(){
         System.out.println(“静态工厂方法被调用”)
              returnnew Bean1();
       }
       publicBean1 getBeanByInstance(){
           System.out.println(“实例方法创建Bean对象”);
       }
}
测试代码:
public class Main1{
       publicstatic void main(String []args){
           ApplicationContextcontext = new ClassPathXmlApplicationContext("applicationContext.xml");
           Bean1 bean1= (Bean1) context.getBean("bean1");
           bean1.Say();
        }
}

spring配置文件

<bean name =”factory” class=” Bean.BeanFactory”></bean>
<bean name=”bean1” factory-bean=”factory”factory-method=”getBeanByIntance”>

       程序运行结果:

       

       图3实例子工厂的运行结果

三丶Spring依赖注入的方式

       Spring总共提供了四种依赖注入的方式,分别是基于xml的setter方式,基于xml的构造函数方式,基于注解的方式以及自动装配方式,在这四种装配方式中,使用得最多的方式是基于xml的setter方式以及基于注解的注入方式,这里重点介绍前三种装配方式。

       (1)基于xml的setter方式注入

       Bean对象:   

class Student{
    Friend friend;
    public Student(){
       System.out.println(“student的构造方法被调用”);
    }
    public void say(){
       System.out.println(“studentsay hello”);
    }
    public void setFriend(Friend friend){
       System.out.println(“调用了set方法”);
       this. friend = friend;
    }
}
class Friend{
       publicFriend(){
       System.out.println(“friend的构造方法被调用”);
    }
}

Spring配置文件:

<Bean name =”friend” class=”Bean.Friend”></Bean>
<Bean name =”stduent” class=”Bean.Student”>
       <propertyname =”friend” ref =”friend”></property>
</Bean>

测试类:

public class Main{
       public static void main(String [] args){
              ApplicationContext context= newClassPathXmlApplicationContext("applicationContext.xml");
              Student student= (Student) context.getBean("student");
              student.say();
       }
}

测试结果:


图4基于XML的set方法注入

   观察上述的代码和执行结果,首先可以清晰看到这种方法的特点:被注入的属性必须设置set方法,在spring文件中对依赖属性需要配置property元素,其次可以发现Spring在注入的时候,先创建依赖对象,然后利用无参数构造方法创建Student对象,最后通过set方法将依赖对象friend注入到student对象中。

       (2)基于xml的构造方法注入   

//Bean对象:
class Student{
    Friend friend;
    public Student(Friend friend){
       System.out.println(“student有参构造函数被调用”);
       this.friend = friend;
    }
    public Student(){
       System.out.println(“student的构造方法被调用”);
    }
    public void say(){
       System.out.println(“studentsay hello”);
    }
    public void setFriend(Friend friend){
       System.out.println(“调用了set方法”);
       this. friend = friend;
    }
}
class Friend{
       publicFriend(){
       System.out.println(“friend的构造方法被调用”);
      }
}

Spring配置文件:

<Bean name =”friend” class=”Bean.Friend”></Bean>
<Bean name =”stduent” class=”Bean.Student”>
       <constructor-arg index=”0” ref =”friend”/>
</Bean>

测试类:

public class Main{
       public static void main(String [] args){
           ApplicationContext context= newClassPathXmlApplicationContext("applicationContext.xml");
           Student student= (Student) context.getBean("student");
           student.say();
        }
}

测试结果:


图 5基于xml的构造函数注入方式

       基于构造函数的注入方式的实现原理也很明显,在创建Student对象的时候,利用有参构造函数创建对象,完成属性注入,这种方式就是必须提供带参数的构造函数,spring的配置文件也要修改。

       (3)基于注解的注入方式

      上述介绍了两种基于xml的注入方式,这两种注入方式都十分的简单,但是当需要配置Bean对象十分对,且依赖关系十分复杂的时候,基于xml方式的注入方式将会使spring的配置文件十分臃肿,不利于后期维护,所以spring提供了一种基于注解的注入方式。

1.利用注解配置userControl对象

@Controller("userControl")
public class UserControl {
    @Resource(name="userService")
    UserService userService;
    publicUserControl(){
       System.out.println("UserControl的构造方法被调用了");
    }
    publicvoid say(){
       System.out.println("UserControl say hello");
    }
}

Controller声明了这个类交给Spring管理,并且暗示他在javaEE三层架构中处于Control层,Controller注解中的”userControl”相当于Spring配置文件中Bean的name属性。

2.利用注解配置userService对象

@Service("userService")
public class UserService {
    @Resource(name="userDao")
    privateUserDao userDao;
    publicUserService(){
       System.out.println("UserService构造方法被调用了");
    }
}

Service声明了这个类交给Spring管理,并且暗示他在javaEE三层架构中处于service层,Service注解中的”userService”相当于Spring配置文件中Bean的name属性。

3.利用注解配置userDao对象

@Repository("userDao")
public class UserDao {
    publicUserDao(){
       System.out.println("UserDao构造方法被调用");
    }
}

Repository声明了这个类交给Spring管理,并且暗示他在javaEE三层架构中处于Dao层,Repository注解中的”userDao”相当于Spring配置文件中Bean的name属性。

4.测试代码

public classMain3 {
    public  staticvoid main(String [] args){
       ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
       UserControl userControl = (UserControl)context.getBean("userControl");
       userControl.say();
    }
}

5.spring配置文件

   <!—开启注解-->
   <context:annotation-config/>
    <!—扫描annotaation包下的所有Bean对象-->
<context:component-scanbase-package="annotation" />

6.测试结果

   

图6 基于注解的注入结果

    利用注解配置Bean对象,可以极大的简化xml书写的工作量,但是其表达依赖关系的时候可能不是太直观。
阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页