spring-IOC

1 spring优点

    • spring是一个开源的免费的框架

    •spring是一个轻量级的,非入侵式的框架

    •控制反转(IOC),面向切面编程(AOP)

    •支持事务的处理,对框架整合的支持

 2.1 IOC

    在之前的业务中,用户的需求可能会影响我们原来的代码,我们需要去修改原来的代码!代码量如果十分大,修改一次的成本就十分昂贵!

    

 

 

     以往的程序是主动创建对象!控制权在程序员手中!

     使用set注入后,程序不再具有主动性,而是变成了被动接受的对象!

     这种思想,从本质上解决了问题,程序员不用再去管理对象的创建了。系统的耦合性大大降低,可以更加专注在业务的实现上!这就是IOC的原型!

 

 

 

     IOC本质:控制反转IOC,是一种设计思想,DI(依赖注入)是实现IOC的一种方法,也有人认为DI只是Ioc的另一种说法。没有IOC的程序中,我们使用面向对象编程,对象的创建和对象之间的依赖关系完全编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转交给第三方。

 

 

 2.1XML方式注入bean

         xml配置--spring官网   ApplicationContext.xml 文件--也可命名为其他名称

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4     xsi:schemaLocation="http://www.springframework.org/schema/beans
 5         https://www.springframework.org/schema/beans/spring-beans.xsd">
 6 
 7     <bean id="..." class="...">  
 8         <!-- collaborators and configuration for this bean go here -->
 9     </bean>
10 
11     <bean id="..." class="...">
12         <!-- collaborators and configuration for this bean go here -->
13     </bean>
14 
15     <!-- more bean definitions go here -->
16 
17 </beans>

      实体类:

public class Hello {
    private  String str;

    public String getStr() {
        return str;
    }

    public void setStr(String str) {
        this.str = str;
    }

    @Override
    public String toString() {
        return "Hello{" +
                "str='" + str + '\'' +
                '}';
    }
}
使用spring来创建对象,在spring中都成为bean
<bean id="hello" class="com.lilang.Hello" >
    <property name="str" value="Spring"></property>
</bean>

    此时必须要有set方法,没有会报错

    测试:

    public static void main(String[] args) {
        //获取spring上下文对象
          ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
          //对象都在spring中管理了,我们要使用直接去里面取出来
        Hello hello = (Hello) context.getBean("hello");
System.out.println(hello.toString()); }

    控制:谁来控制对象的创建,传统应用程序的对象由程序本身控制创建,使用spring后,对象是spring容器创建的。

    反转:程序本身不创建对象,而变成被动的接受对象。

    依赖注入:就是利用set方法进行注入的。

    IOC是一种编程思想,由主动的编程变成被动的接受

2.2 有参构造器注入

    真实类:

public class User {
        private  String name;
        public  User(String name){
      this.name=name;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
        public void show(){
            System.out.println("name="+name);
        }
}

       applicatonContext.xml 文件

 <!-- 无参构造-->
<bean id="user" class="com.lilang.User">
        <property name="name" value="李浪"></property>
    </bean>

 

<!-- 有参构造-->
   <!-- 下标赋值-->
    <bean id="user" class="com.lilang.User">
        <constructor-arg index="0" value="lilang"></constructor-arg>
    </bean>
    

     index代表第一个构造器参数,以此类推。

 <!-- 类型赋值:不建议  相同类型不行-->
    <bean id="user" class="com.lilang.User">
        <constructor-arg type="java.lang.String" value="lilang"></constructor-arg>

    </bean>
 <!-- 第三种 直接用参数名-->
 <bean id="user" class="com.lilang.User">
     <constructor-arg name="name" value="lilang"></constructor-arg>
  </bean>

    Spring 容器 只要注册 就会创建实体 ,被实例化 都是同一个对象,内存中只有一个实例(可修改传播参数)

 

 

2.3 import

      import,一般用于团队开发中使用,它可以将多个配置文件,导入合并为一个。

      假设,现在有一个项目有多个人开发,这三个人负责不同的类开发,不同的类需要注册不同的bean中,我们可以用import将所有人的applicationContext合并为一个总的!

    

 

 

 2.4 其他类型属性注入

       实体类:

       User:

public class User {
    private String name;
    private  String age;

    public User() {

    }

    public User(String name, String age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }

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

     使用C或P命名空间进行注入时需要导入

       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
<?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:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- p命名空间注入 可以直接注入属性-->
<bean id="user" class="com.lilang.User" p:name="lilang" p:age="18"></bean>

<!-- c命名空间 构造器注入-->
<bean id="user2" class="com.lilang.User" c:age="18" c:name="ad"></bean>
    
</beans>

 

 

      Student

public class Student {
    private String name;
    private Address address;
    private String[] books;
    private List<String> hobbys;

    public String[] getBooks() {
        return books;
    }

    public void setBooks(String[] books) {
        this.books = books;
    }

    public void setHobbys(List<String> hobbys) {
        this.hobbys = hobbys;
    }

    private Map<String ,String > card;
    private Set<String> games;
    private  String wife;
    private Properties info;

    public String getName() {
        return name;
    }

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

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    public Map<String, String> getCard() {
        return card;
    }

    public void setCard(Map<String, String> card) {
        this.card = card;
    }

    public Set<String> getGames() {
        return games;
    }

    public void setGames(Set<String> games) {
        this.games = games;
    }

    public String getWife() {
        return wife;
    }

    public void setWife(String wife) {
        this.wife = wife;
    }

    public Properties getInfo() {
        return info;
    }

    public void setInfo(Properties info) {
        this.info = info;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", address=" + address +
                ", books=" + Arrays.toString(books) +
                ", hobbys=" + hobbys +
                ", card=" + card +
                ", games=" + games +
                ", wife='" + wife + '\'' +
                ", info=" + info +
                '}';
    }

 

    <bean id="student" class="com.lilang.Student">
        <property name="name" value="lilang"></property>
        <property name="address" ref="address"></property>
       <!-- 数组注入-->
        <property name="books">
            <array>
                <value>老人与海</value>
                <value>水浒传</value>
            </array>
        </property>
        <!-- list注入-->
      <property name="hobbys">
          <list>
              <value>听歌</value>
              <value>看电影</value>
          </list>
      </property>
        <!-- set集合注入-->
        <property name="games">
            <set>
                <value>魂斗罗</value>
                <value>lol</value>
            </set>
        </property>

        <!-- map-->
      <property name="card">
          <map>
              <entry key="身份证" value="123456"></entry>
              <entry key="姓名" value="lilang"></entry>
          </map>
      </property>
        <!-- null 值-->
        <property name="wife" >
            <null></null>
        </property>
        <!-- properties 注入-->
        <property name="info">
            <props>
                <prop key="学号" >1740840231</prop>
                <prop key="性别"></prop>
            </props>
        </property>
    </bean>

 

 

 Address

    

public class Address {
    private String Address;

    public String getAddress() {
        return Address;
    }

    public void setAddress(String address) {
        Address = address;
    }

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

     

    <bean id="address" class="com.lilang.Address">
        <property name="address" value="乌鲁木齐"></property>
    </bean>

   测试:

  public static void main(String[] args) {
     ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
        Student student = (Student)context.getBean("student");
        System.out.println(student);
       // Address address = (Address)context.getBean("address");
       // System.out.println(address);
    }

    @Test
    public void user(){
       ApplicationContext context = new ClassPathXmlApplicationContext("userBeans.xml");
        User user = context.getBean("user2", User.class);
        System.out.println(user.toString());
    }

 

 

 3 bean作用域

     

 

 

         singleton:单例模式,spring默认

         prototype:原型模式,每次从容器中 get的时候,都会产生一个新的对象

         其余的request,session,application 这些只能在web开发中使用到。

    3 注解方式注入bean

       3.1 注解

            1.导入约束:context约束

            2.配置注解的支持:

     

<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></context:annotation-config>
    <!-- 指定要扫描的包 ,包下的注解会生效-->
    <context:component-scan base-package="com.lilang"></context:component-scan>

</beans>

         dao层:使用@Repository 注释

@Repository
public class UserDao {
}

      domain层: @Component 组件

@Component //相当于bean
public class User {
    @Value("lilang")
    public String name;
}

      service层: @Service 

@Service
public class UserService {

}

     测试:

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        User user = context.getBean("user", User.class);
        System.out.println(user.name);

    }

   3.2 @Autowied

            @Autowied:自动注入,通常配合@Qualifier注释一起用 (需要导入注释依赖)

            @Qualifier:指定bean的id

     import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import javax.annotation.Resource;

           cat:

public class Cat {
    public void shoot(){
        System.out.println("喵");
    }

}

       Dog:

public class Dog {
    public void shoot(){
        System.out.println("汪");
    }
}

        People:人可以养猫养狗

     

    @Autowired
    @Qualifier(value = "cat1")   注入name为cat1的bean
byname: 需要保证bean的id的唯一性,并且这个bean需要和注入的属性的set方法的值一致!
byType: 需要保证bean的class的唯一性,并且这个bean需要和自动注入的属性的类型一致!
public class People {
    @Autowired
    @Qualifier(value = "cat1")
    private Cat cat;

    @Resource
    private Dog dog;
    private String name;

    public Cat getCat() {
        return cat;
    }

    public void setCat(Cat cat) {
        this.cat = cat;
    }

    public Dog getDog() {
        return dog;
    }

    public void setDog(Dog dog) {
        this.dog = dog;
    }

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "People{" +
                "cat=" + cat +
                ", dog=" + dog +
                ", name='" + name + '\'' +
                '}';
    }

  注入:

<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></context:annotation-config>


    <bean id="cat1" class="com.lilang.Cat"></bean>
    <bean id="dog" class="com.lilang.Dog"></bean>
    <!-- byname 自动在容器上下文查找,和自己对象set对应的bean-->
   <bean id="people" class="com.lilang.People"></bean>

</beans>

    @Resource和@Autowired区别

          • 都是用来自动装配的,都可以放在属性字段上

          • @Autowired 通过byType的方式实现,而且必须要求这个对象存在!(常用)

          • @Resource 默认通过byName的方式实现,如果找不到名字,则通过byType实现!如果两个都找不到就会报错。

          • 执行顺序不同:@Autowired通过byType的方式实现

 3.3 完全采用注释,不需要xml

        1:在spring4之后,要使用注解开发,必须保证aop的包导入

 

 

        2:使用注解需要导入context约束,增加注释的支持

 

 

     配置类:等价于applicationContext.xml

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

//这个也会被spring容器托管,注册到容器中,因为他本身就是一个@Component
//@Configuration代表一个配置类,就和我们之前的beans.xml一样
@Configuration
@ComponentScan("com.lilang")
@Import(Config2.class)  //合并beans
@Scope("singleton") //单例模式 默认 public class Config { @Bean public User getUser(){ return new User(); } }

     @Bean: z注册一个bean,相当于我们之前写的一个bean标签,这个方法名就相当于标签中的id属性

                   返回值就相当于bean标签中的class属性

     @Component有几个衍生注释,在web开发中,会按照mvc三层架构分成!

              • dao @Repository

              • service @Service

              • controller @Controller

         这四个注解功能都是一样的,都是代表某个类注册到spring中,装配Bean

    测试:

    public static void main(String[] args) {
      //注解配置 获取类是AnnotationConfigApplicationContext
        ApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(Config.class);
        User getUser = annotationConfigApplicationContext.getBean("getUser", User.class);
        System.out.println(getUser.toString());
    }

    使用注解配置时获取类是AnnotationConfigApplicationContext,不再是ClassPathXmlApplicationContext.

 4 小结

     xml与注释:

                •  xml更加万能,适用于任何场合!维护简单。

                •  注解不是自己类使用不了,维护相对复杂!

      xml与注释的最佳实践:

                •  xml用来管理bean

                •  之间只负责完成属性的注入

                •  我们在使用过程中,只需要注意一个问题:必须让注解生效,就需要开启注解的支持。

                 

 

posted @ 2021-02-28 09:58  coline  阅读(106)  评论(0)    收藏  举报