Spring

1. Spring

官方文档:https://docs.spring.io/spring-framework/docs/5.2.0.RELEASE/spring-framework-reference/core.html#beans-factory-instantiation

  • Spring Boot
    • 一个快速开发的脚手架
    • 基于SpringBoot可以快速开发单个微服务
    • 约定大于配置
  • Spring Cloud
    • SpringCloud是基于SpringBoot实现的

2. IoC理论推导(Inversion of control)

控制反转IoC是一种设计思想,DI(依赖注入)是实现IoC的一种方式

  1. UserDao 接口

    public interface UserDao {
        void getUser();
    }
    
  2. UserDaoImpl 实现类

    public class UserDaoImpl implements UserDao{
        @Override
        public void getUser() {
            System.out.println("默认获取用户数据");
        }
    }
    
    public class UserDaoMySQLImpl implements UserDao{
        @Override
        public void getUser() {
            System.out.println("MySQL获取用户数据!");
        }
    }
    
    public class UserDaoOracleImpl implements UserDao {
        @Override
        public void getUser() {
            System.out.println("获取Oracle用户数据!!");
        }
    }
    
  3. UserService 业务接口

    public interface UserService {
        void getUser();
    }
    
  4. UserServiceImpl 业务实现类

    public class UserServiceImpl implements UserService{
    
        /*旧方法*/
    //    private UserDao userDao = new UserDaoImpl();
    //    private UserDao userDao = new UserDaoMySQLImpl();
    //	  private UserDao userDao = new UserDaoOracleImpl();
    
        
        /*新方法*/
        private UserDao userDao;
    
        //利用set进行动态实现值的注入!
        public void setUserDao(UserDao userDao) {
            this.userDao = userDao;
        }
    
        @Override
        public void getUser() {
            userDao.getUser();
        }
    }
    

在旧方法中,用户的需求改变可能会影响原来的代码,需要根据用户需求修改源代码!而修改源代码的成本非常昂贵!!!

而新方法中,通过控制反转可以将修改代码的主动权交给用户直接控制。也不用再去管理对象的创建了。系统的耦合性大大降低,可以更加专注在业务实现上!这就是IOC的原型!!

测试类

public class MyTest {
    public static void main(String[] args) {

        // 用户实际调用的是业务层,dao层他们不需要接触
        UserServiceImpl userSeΩrvice = new UserServiceImpl();

//        userService.setUserDao(new UserDaoSQLServerImpl());
//        userService.setUserDao(new UserDaoMySQLImpl());
        userService.setUserDao(new UserDaoOracleImpl());

        userService.getUser();
    }
}

3. 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"
       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">

    
</beans>
<?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">

    <!-- 使用Spring来创建对象,在Spring中这些都成为Bean

     类型    变量名  =  new  类型();
     hello  Hello  =  new  hello();

     id => 变量名
     class  => new的对象
     property 相当于给对象重的属性设置一个值
     -->
    <bean id="Hello" class="com.inspur.pojo.hello">
        <property name="str" value="Spring"/>
    </bean>

    <!-- 什么是控制反转???
     控制:谁来控制对象的创建,传统应用程序是由程序自身控制对象的创建,使用Spring之后,对象由Spring控制创建。
     反转:程序本身不创建对象,而变成被动的接收对象。

     依赖注入:就是利用set方法来进行注入的。
     
     IoC是一种编程思想,由主动创建对象变为被动接收对象。
     -->
</beans>

4. IoC创建对象方式

实体类

package com.inspur.pojo;

public class User {
    private String name;

//    public User() {
//        System.out.println("User的无参构造!!");
//    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
  1. 使用无参构造创建对象,默认实现

    <bean id="user" class="com.inspur.pojo.User">
        <property name="name" value="spring-03-ioc2"/>
    </bean>
    
  2. 使用有参构造创建对象:三种方式

    <!--第一种:下标赋值-->
    <bean id="user" class="com.inspur.pojo.User">
    	<constructor-arg index="0" value="下标赋值"/>
    </bean>
    
    <!--不建议使用:多个参数类型数据-->
    <bean id="user" class="com.inspur.pojo.User">
    	<constructor-arg type="java.lang.String" value="类型赋值"/>
    </bean>
    
    <!--第三种:直接通过参数名传参-->
    <bean id="user" class="com.inspur.pojo.User">
    	<constructor-arg name="name" value="liuyike"/>
    </bean>
    

    当配置文件被加载的时候,容器中管理的对象就已经被初始化了。

5. Spring配置

5.1 别名

<bean id="user" class="com.inspur.pojo.User">
	<constructor-arg name="name" value="liuyike"/>
</bean>
<alias name="user" alias="userNew"/>
<bean id="user" class="com.inspur.pojo.User" name="user2,user3;user4 user5">
    <constructor-arg name="name" value="liuyike"/>
</bean>

5.2 Bean的配置

<!-- 使用Spring来创建对象,在Spring中这些都成为Bean

	类型    变量名  =  new  类型();
	hello  Hello  =  new  hello();

    id => 变量名
    class  => new的对象
    property 相当于给对象重的属性设置一个值
    -->
<bean id="Hello" class="com.inspur.pojo.hello">
    <property name="str" value="Spring"/>
</bean>

5.3 import

可以将多人不同开发的配置文件合并到总配置文件。使用的时候直接使用总配置就好了。

6. 依赖注入

6.1 构造器注入(4.IoC创建对象方式)

6.2 Set方式注入【重点】

  1. 复杂类型

    public class Address {
        private String address;
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    }
    
  2. 真实测试对象

    import java.util.*;
    
    public class Student {
        private String name;
        private Address address;
        private String[] books;
        private List<String> hobbies;
        private Map<String,String> card;
        private Set<String> games;
        private String wife;
        private Properties info;
    }
    
  3. 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"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            https://www.springframework.org/schema/context/spring-context.xsd">
    
        <bean id="address" class="com.inspur.pojo.Address">
            <property name="address" value="北京"/>
        </bean>
    
        <bean id="student" class="com.inspur.pojo.Student">
            <!--第一种:普通注入,value-->
            <property name="name" value="刘依珂"/>
    
            <!--第二种:Bean注入,ref-->
            <property name="address" ref="address"/>
    
            <!--第三种:数组注入-->
            <property name="books">
                <array>
                    <value>红楼梦</value>
                    <value>西游记</value>
                    <value>水浒传</value>
                    <value>三国演义</value>
                </array>
            </property>
    
            <!--第四种:List-->
            <property name="hobbies">
                <list>
                    <value>唱歌</value>
                    <value>看电影</value>
                    <value>敲代码</value>
                </list>
            </property>
    
            <!--第五种:Map-->
            <property name="card">
                <map>
                    <entry key="身份证" value="123456789012345678"/>
                    <entry key="银行卡" value="0987654321234567890"/>
                </map>
            </property>
    
            <!--第六种:Set-->
            <property name="games">
                <set>
                    <value>ZXC</value>
                    <value>ASD</value>
                    <value>QWE</value>
                </set>
            </property>
    
            <!--赋空值-->
            <property name="wife">
                <null/>
            </property>
    
            <property name="info">
                <props>
                    <prop key="学号">2019234441</prop>
                    <prop key="性别"></prop>
                    <prop key="姓名">刘依珂</prop>
                </props>
            </property>
        </bean>
    </beans>
    
  4. 测试类

    public class MyTest {
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
            Student student = context.getBean("student", Student.class););
            System.out.println(student.toString());
        }
    }
    

6.3 拓展方式(p/c命名空间注入)

导入xml约束

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

配置文件

<!-- p命名空间注入,可以直接注入属性的值:property -->
<bean id="user" class="com.inspur.pojo.User" p:name="孔舒怡" p:age="18"/>
<!-- c命名空间注入,基于构造函数的依赖注入,因此必须要有有参构造函数:construct-args -->
<bean id="user2" class="com.inspur.pojo.User" c:name="liuyike" c:age="21"/>
<?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"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--p命名空间注入,可以直接注入属性的值:property-->
    <bean id="user" class="com.inspur.pojo.User" p:name="孔舒怡" p:age="18"/>
    
    <!--c命名空间注入,基于构造函数的依赖注入,因此必须要有有参构造函数:construct-args-->
    <bean id="user2" class="com.inspur.pojo.User" c:name="liuyike" c:age="21"/>

</beans>

6.4 bean的作用域

image-20220928142429236

1. 单例模式(Spring默认机制)

只有一个单例 bean 的共享实例被管理,并且所有对具有与该 bean 定义匹配的一个或多个 ID 的 bean 的请求都会导致 Spring 容器返回一个特定的 bean 实例。

换句话说,当您定义 bean 定义并将其限定为单例时,Spring IoC 容器会创建该 bean 定义所定义的对象的一个实例。此单个实例存储在此类单例 bean 的缓存中,并且该命名 bean 的所有后续请求和引用都返回缓存的对象。

下图显示了单例作用域的工作原理:

image-20220928145103990

<!--Spring默认为singleton模式,也可显式声明-->
<bean id="user2" class="com.inspur.pojo.User" c:name="liuyike" c:age="21" scope="singleton"/>
// singleton 单例模式测试
@Test
public void test03() {
    User user = context.getBean("user2", User.class);
    User user2 = context.getBean("user2", User.class);
    System.out.println(user2 == user);
    System.out.println(user.hashCode());
    System.out.println(user2.hashCode());
}

// true
// 1738236591
// 1738236591

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

bean 部署的非单例原型范围导致每次对特定 bean 发出请求时都会创建一个新的 bean 实例。也就是说,将 bean 注入到另一个 bean 中,或者您通过getBean()容器上的方法调用来请求它。通常,您应该对所有有状态 bean 使用原型范围,对无状态 bean 使用单例范围。

image-20220928145740010

<bean id="user2" class="com.inspur.pojo.User" c:name="liuyike" c:age="21" scope="prototype"/>
// singleton 单例模式测试
@Test
public void test03() {
    User user = context.getBean("user2", User.class);
    User user2 = context.getBean("user2", User.class);
    System.out.println(user2 == user);
    System.out.println(user.hashCode());
    System.out.println(user2.hashCode());
}

// false
// 1558021762
// 225290371

3. 其余的request、session、application这些只能在web开发中使用到!

7. Bean的自动装配

  • 自动装配是Spring满足bean依赖的一种方式!
  • Spring会在上下文中自动寻找,并自动给bean装配属性

在Spring中有三种自动装配的方式

  1. 在xml中显式的配置
  2. 在java中显式的配置
  3. 隐式的自动装配

7.1 在xml中显式的配置

<bean id="cat" class="com.inspur.pojo.Cat"/>
<bean id="dog" class="com.inspur.pojo.Dog"/>

<!--byName:会自动在容器上下文中查找和自己对象 set 方法参数类型所对应的 bean !!
    byType:会自动在容器上下文中查找和自己对象属性类型相同的 bean !!
-->
<bean id="people" class="com.inspur.pojo.People" autowire="byName">
    <property name="name" value="liuyike"/>
</bean>
<bean id="cat" class="com.inspur.pojo.Cat"/>
<bean id="dog222" class="com.inspur.pojo.Dog"/>

<!--
	byName:会自动在容器上下文中查找和自己对象 set 方法后面的值所对应的 bean !!
    byType:会自动在容器上下文中查找和自己对象属性类型相同的 bean,但要保证和自己对象属性类型相同的 bean 唯一!且id可省略。
-->
<bean id="people" class="com.inspur.pojo.People" autowire="byType">
    <property name="name" value="liuyike"/>
</bean>

小结:

  • byName:需要保证所有的bean唯一,并且这个bean需要和自动注入的对象的set方法的参数类型一致!!
  • byType:需要保证所有bean的class唯一,并且这个bean和自动注入的对象的属性类型一致。

测试类

@Test
public void test01() {
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    People people = context.getBean("people", People.class);
    people.getCat().shout();
    people.getDog().shout();
}

7.2 使用注解实现自动装配

使用须知:

  1. 导入约束

  2. 配置注解的支持:context:annotation-config

    <?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>
    

@Autowired注解

直接在属性上使用即可!也可在set方法上使用

使用**@Autowired注解**,我们可以省略set方法的编写,前提是这个自动装配的属性在IoC容器中存在,且符合byName!!

小知识:

@Autowired(required = false) //可以为空
//required 注解底层代码
public @interface Autowired {
	boolean required() default true; //默认为真
}
private String name;
// @NUllable 字段标记了这个注解,表示该字段可以为null
public People(@Nullable String name) {
    this.name = name;
}

@Qualifier注解

如果@Autowired自动装配环境比较复杂,自动装备无法通过一个注解【@Autowired】完成的时候,我们可以使用@Qualifier(value=“xxx”)去配置@Autowired的使用,指定一个唯一的bean对象注入!!

@Autowired
@Qualifier(value = "cat11") //bean的id
private Cat cat;
@Autowired
private Dog dog;

@Resource注解

@Resource(name = "cat11") //bean的id
private Cat cat;
@Resource
private Dog dog;
<bean id="cat11" class="com.inspur.pojo.Cat"/>
<bean id="dog" class="com.inspur.pojo.Dog"/>
<bean id="cat22" class="com.inspur.pojo.Cat"/>

<bean id="people" class="com.inspur.pojo.People"/>

小结:

@Resource 和 @Autowired 的区别:

  • 都是用来自动装配的,都可以放在属性字段上
  • @Autowired 通过 byType 的方式实现,而且必须要求这个对象存在!【常用】
  • @Resource 默认通过 byName 方式实现,如果找不到名字,则通过byType实现!!【类似于@Autowired集合体】
  • 执行顺序不同:@Autowired 通过 byType 实现,@Resource 默认通过 byName 方式实现。

8. 使用注解开发

  1. 注册bean

    @Component
    public class User {
        public String name = "刘依珂";
    }
    
  2. 属性注入

    @Component
    public class User {
        @Value("liuyike")
        public String name;
    }
    

注解说明:

  • @Autowired:自动装配通过类型。

    • @Qualifier:如果属性有多个相同类型的不同名称,使用@Qualifier(value = “xxx”)
  • @Nullable:标记字段可以为空(null)

  • @Resource:自动装配通过名字,类型

  • @Component:组件,放在类上,说明这个类被Spring管理了,等同于在xml文件中注册bean!!!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值