Spring入门之IOC篇

  • 什么是 Spring ?

 Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One J2EE Development and Design中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。简单点来说Spring就是一个轻量级的控制反转(IOC)和面向切面(AOP)的容器。

  • IOC(控制反转)和DI(依赖注入)

IOC:也即控制反转,DI即依赖注入,控制反转IOC和依赖注入DI其实就是同个概念的两个不同角度的解释。 控制反转可以理解为获取依赖对象的控制反转过来。有反转的概念自然就有正转的概念。若有两个类,类A和类B,若类A依赖与类B,则类A要获取类B的方法,这时我们可以按照传统的JavaSE思想,在A类里,写代码B b = new B();通过new关键字获取A类的依赖对象,或者通过工厂模式进行获取,当然还有等等其它方法。这些方法,就属于正转的方法,因为A类获取B类就是通过主动的方法进行获取的,统称为正转的方法。

然后,什么是反转呢?既然正转是主动的方式,那么反转就是被动的方式。也即我们要获取某个类的依赖对象,不需要类主动去获取。然后在Spring框架里是怎么实现的呢?在Spring框架里,实现IOC,是通过IOC容器实现的,由IOC容器负责创建和获取依赖对象,对象只是被动地接受依赖对象。

比如我们要在一个客户端类里获取用户信息类,下图给出正转的方式

有了IOC容器之后,获取依赖对象的方式就变成如图所示了

IOC是一种很好的解耦合思想,下面示意图

  •  第一个Spring程序

        1.导入Jar包(我这里利用maven , 他会自动下载对应的依赖项

<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.15</version>
</dependency>

        2.编写一个Hello实体类

@Setter
@Getter
@ToString
@AllArgsConstructor
public class Hello {
    private String Str;
}

        3.编写我们的spring文件 , 我命名为applicationContext.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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
        <!--bean就是java对象 , 由Spring创建和管理-->
<!--        以前我们这样创建对象Hello hello = new Hello();-->
<!--        这里的id就类似于前面代码的hello,class的值就类似于前面代码的Hello()-->
        <bean id="Hello" class="top.yunhuisu.pojo.Hello">
            <property name="str" value="HelloSpring"/>
        </bean>
</beans>

        4.上面的三步做好我们就可以进行测试了

 @Test
    public void testHello() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        Hello hello = (Hello) applicationContext.getBean("Hello");
        System.out.println(hello.toString());
    }
  •  当实体类里面出现有参构造方法这样来创建

        1.这是一个有参构造的实体类

@Setter
@Getter
@ToString
@AllArgsConstructor
public class Hello {
    private String Str;
}

         2.applicationContext.xml 有三种方式编写(constructor-arg标签)

<bean id="Hello" class="top.yunhuisu.pojo.Hello">
    <!-- 第一种根据参数名字设置,这是常用的一种 -->
    <!-- name指参数名 -->
    <constructor-arg name="Str" value="Hello"/>
</bean>
 <bean id="Hello" class="top.yunhuisu.pojo.Hello">
     <!-- 第二种根据index参数下标设置 -->
     <!-- index指构造方法 , 下标从0开始 -->
     <constructor-arg index="0" value="HelloSpring"/>
 </bean>
<bean id="Hello" class="top.yunhuisu.pojo.Hello">
    <!-- 第三种根据参数类型设置 -->
    <constructor-arg type="java.lang.String" value="HelloSpring"/>
</bean>
  • Spring配置

        1.别名(有二种方式给bean中的id取别名,第一种比较好用)

   <!-- id是bean的标识符,要唯一,如果没有配置id,name就是默认标识符
        如果配置id,又配置了name,那么name是别名第一种采用name属性,
        可以设置多个别名,可以用逗号,分号,空格隔开-->
   <!--如果不配置id和name,可以根据applicationContext.getBean(.class)获取对象-->
   <bean id="Hello" class="top.yunhuisu.pojo.Hello" name="hello1 hello2,hello3;newHello">
       <property name="str" value="HelloSpring"/>
   </bean>
    <!--第二种采用alias设置别名,为bean设置别名,可以设置多个别名-->
    <alias name="Hello" alias="hello"/>
    <alias name="Hello" alias="hello1"/>

        2.import团队的合作通过import来实现 (将多个applicationContext合到一个,使用的时候就使用总的那个applicationContext)

<import resource="{path}/applicationContext1.xml"/>
  • 依赖注入(DI)之Set 注入,构造器注入上面讲过

        编写测试pojo类 :

Address.java类

@Setter
@Getter
public class Address {
    private String address;
}

Student.java类

@Setter
@Getter
public class Student {
    private String Name;
    private Address address;
    private String[] books;
    private List<String> hobbys;
    private Map<String, Object> car;
    private Set<String> games;
    private String  wife;
    private  Properties properties;

    @Override
    public String toString() {
        return "Student{" +
                "Name='" + Name + '\'' +
                ", address=" + address.getAddress() +
                ", books=" + Arrays.toString(books) +
                ", hobbys=" + hobbys +
                ", car=" + car +
                ", games=" + games +
                ", wife='" + wife + '\'' +
                ", properties=" + properties +
                '}';
    }
}

1、常量注入

<bean id="address" class="top.yunhuisu.pojo.Address">
    <property name="name" value="大阳光海盗"/>
</bean>

2、Bean注入

注意:这里的值是一个引用,ref

<bean id="address" class="top.yunhuisu.pojo.Address">
        <property name="address" value="四川"/>
</bean>
<bean id="student" class="top.yunhuisu.pojo.Student">
        <property name="address" ref="address"/>
</bean>

3、数组注入

<bean id="address" class="top.yunhuisu.pojo.Address">
      <property name="books">
           <array>
               <value>Java成神之路</value>
               <value>浅谈Spring</value>
           </array>
       </property>
</bean>

4、List注入

<bean id="student" class="top.yunhuisu.pojo.Student">
    <!--List注入-->
       <property name="hobbys">
           <list>
               <value>音乐</value>
               <value>写代码</value>
               <value>赛车</value>
           </list>
       </property>
</bean>

5、Map注入

<bean id="student" class="top.yunhuisu.pojo.Student">
       <!--Map集合注入-->
       <property name="car">
           <map>
               <entry key="学生卡" value="10001"/>
               <entry key="银行卡" value="637849039400"/>
               <entry key="饭卡" value="158539"/>
           </map>
       </property>
</bean>

6、set注入

<bean id="student" class="top.yunhuisu.pojo.Student">
       <!--Set注入-->
       <property name="games">
           <set>
               <value>LOL</value>
               <value>王者荣耀</value>
           </set>
       </property>
</bean>

7、Null注入

<bean id="student" class="top.yunhuisu.pojo.Student">
       <!--Null注入-->
       <property name="wife">
           <null/>
       </property>
</bean>

8、Properties注入

<bean id="student" class="top.yunhuisu.pojo.Student">
       <!--       Properties注入-->
       <property name="properties">
           <props>
               <prop key="性别">男</prop>
               <prop key="年龄">20</prop>
           </props>
       </property>
</bean>

测试:

@Test
    public void testStudent() {
        ApplicationContext applicationContext = new                         ClassPathXmlApplicationContext("applicationContext.xml");
        Student student = (Student) applicationContext.getBean("student");
        System.out.println(student.toString());
    }

测试结果

  • P命名和C命名空间的注入(扩展):

        编写User类:

@Setter
@Getter
@ToString
public class User {
    private String Name;
    private String Age;
}

        1.第一步在beans里面写C或者P的约束

xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"

        2.P命名空间的使用:

<!--这是没有构造方法的时候-->
<bean id="user" class="top.yunhuisu.pojo.User" p:name="大阳光" p:age="18"></bean>

        3.P命名空间的使用:

<!--这是有构造方法的时候,也就是在User类上面加上@AllArgsConstructor注解-->
<bean id="user" class="top.yunhuisu.pojo.User" c:Name="大阳光" c:Age="18"></bean>

测试:

@Test
    public void testUser() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        User user = (User) applicationContext.getBean("user");
        System.out.println(user.toString());
    }
  • Bean的作用域:

作用域描述
singleton在spring IoC容器仅存在一个Bean实例,Bean以单例方式存在,bean作用域范围的默认值。
prototype每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时,相当于执行newXxxBean()。
request每次HTTP请求都会创建一个新的Bean,该作用域仅适用于web的Spring WebApplicationContext环境。
session同一个HTTP Session共享一个Bean,不同Session使用不同的Bean。该作用域仅适用于web的Spring WebApplicationContext环境。
application限定一个Bean的作用域为ServletContext的生命周期。该作用域仅适用于web的Spring WebApplicationContext环境。

  • 单例模式的使用(默认就是单例):

<!--设置scope属性为singleton即可显示单例-->
<bean id="user" class="top.yunhuisu.pojo.User" c:Name="大阳光" c:Age="18" scope="singleton"></bean>

 单例测试(取二次同样的bean判断是True):

@Test
    public void testUser() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        User user = (User) applicationContext.getBean("user");
        User user2 = (User) applicationContext.getBean("user");
        System.out.println(user==user2); // true
    }
  • 原型模式的使用:

<!--设置scope属性为prototype即可-->
<bean id="user" class="top.yunhuisu.pojo.User" c:Name="大阳光" c:Age="18" scope="prototype"></bean>

 单例测试(取二次同样的bean判断是False):

@Test
    public void testUser() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        User user = (User) applicationContext.getBean("user");
        User user2 = (User) applicationContext.getBean("user");
        System.out.println(user==user2); // false
    }
  • Bean的自动装配(bean的autowir属性):

        建一个Cat和Dog类,以及person类:

Dog.java类

public class Dog {
    public void Eat() {
        System.out.println("狗吃骨头");
    }
}

Cat.java类

public class Cat {
    public void Eat() {
        System.out.println("猫吃鱼");
    }
}

Person类.java

@Setter
@Getter
@ToString
public class Person {
   private Cat cat;
   private Dog dog;
   private String Name;
}

byType装配:

 <bean id="cat" class="top.yunhuisu.pojo.Cat"/>
    <bean id="Dog" class="top.yunhuisu.pojo.Dog"/>
    <!--    byName是通过id来找的,id要和set后面的一致,不然报错,id还要唯一-->
    <!--    byType是通过类型来找的-->
    <bean id="person" class="top.yunhuisu.pojo.Person" autowire="byType">
    <property name="name" value="大阳光"/>
 </bean>

测试代码:

   @Test
    public void testByType() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        Person person = applicationContext.getBean("person", Person.class);
        person.getCat().Eat();
        person.getDog().Eat();
    }

使用注解自动装配:

        导入约束:

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

    <context:annotation-config/>

</beans>

        注解的使用:

<bean id="cat2" class="top.yunhuisu.pojo.Cat"/>
<bean id="dog" class="top.yunhuisu.pojo.Dog"/>
<bean id="dog" class="top.yunhuisu.pojo.Person"/>

在类的属性或者set方法上面加上@Autowired,当加上这个可以不用写set方法了

其中@Qualifier("XXX")可以自定义id标识

@Setter
@Getter
@ToString
public class Person { 
    @Autowired
    @Qualifier("cat2")
   private Cat cat;
    @Autowired
   private Dog dog;
   private String Name;
}

测试代码:

 @Test
    public void testByType() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("Annotation.xml");
        Person person = applicationContext.getBean("person", Person.class);
        person.getCat().Eat();
        person.getDog().Eat();
    }
  • 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"
       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
        https://www.springframework.org/schema/context/spring-context.xsd">
    <!--扫描包的注解-->
    <context:component-scan base-package="top.yunhuisu"/>
    <context:annotation-config/>
</beans>

        编写类User.java

@Component
@Setter
@Getter
/*@Component类似于<bean id="user" class="top.yunhuisu.pojo.User"/>,也可以写在set方法上面*/
@Scope("prototype")
/*Scope是bean的作用域*/
public class User {
    @Value("大阳光")
    /*Value类似于<property name="name" value="大阳光"/>*/
    private String Name;
}

        测试:

   @Test
    public void testAnno() {
       ApplicationContext applicationContext = new ClassPathXmlApplicationContext("Annotation.xml");
        User user = applicationContext.getBean("user", User.class);
        System.out.println(user.getName());
    }

衍生注解:

@Component三个衍生注解

为了更好的进行分层,Spring可以使用其它三个注解,功能一样,目前使用哪一个功能都一样。

@Controller:web层
@Service:service层
@Repository:dao层


Javaconfig代替xml注解开发:

编写User类User.java

@Component
public class User {
    @Value("大阳光")
    private String Name;

    @Override
    public String toString() {
        return "User{" +
                "Name='" + Name + '\'' +
                '}';
    }

    public String getName() {
        return Name;
    }

    public void setName(String name) {
        Name = name;
    }
}

编写config类ConfigUtils.java

@Configuration
/*扫描包的注解*/
@ComponentScan("top.yunhuisu")
/*类似于xml的导包合成一个*/
@Import(bean2.class)
public class ConfigUtlis {
    @Bean("user")
    @Scope("prototype")
    public User getUser() {
        return new User();
    }
}

测试类tsetConfig.java:

public class testConfig {
    @Test
    public void testConfig() {
        Object object;
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ConfigUtlis.class);
        User user = applicationContext.getBean("user", User.class);
        System.out.println(user.toString());
    }
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值