【Spring学习历程】---- 遇见狂神说课程笔记

Spring学习

1、Spring组成

Spring组成

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

大多是公司都在使用SpringBoot进行快速开发,学习Springboot的前提,就是完全掌握Spring以及SpringMVC,其承上启下的作用

弊端:发展太久了,违背了之前的理念,配置十分繁琐“配置地狱

2、IOC理论推导

对象由Spring来创建,管理,装配

IOC(控制反转)的本质:是一种设计思想,将对象的创建交给了第三方,完全由程序自己控制:即获得依赖对象的方式反转了

是Spring框架的核心内容

Spring在容器初始化时,先读取配置文件,根据配置文件或元数据创建与组织对象放入容器中,程序使用时再从容器中取出需要的对象*控制反转是一种通过描述(XML或注解)并通过第三方去产生或获取特定对象的方式,在Spring中实现控制反转的是IOC容器,其实现方法是依赖注入

在这里插入图片描述

  1. UserDao接口

  2. UserDaoImpl实现类

  3. UserService业务接口

  4. UserServiceImpl业务实现类

需要根据用户修改源代码,会破坏程序的完整性,代价昂贵

通过使用set接口实现:

private UserDao userDao;
    //利用set进行动态实现值的注入
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

程序不在具有主动性,而是变成被动接受对象

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

3、IOC创建对象的方式

3.1使用无参构造创建,默认
3.2使用有参构造创建
  • 下标赋值

    <!--    1.下标赋值-->
        <bean id="user" class="com.zhai.pojo.User">
            <constructor-arg index="0" value="zhaichenji"/>
        </bean>
    
  • 通过类型创建

    <!--    2.通过类型创建  ->不建议使用-->
        <bean id="user" class="com.zhai.pojo.User">
            <constructor-arg type="java.lang.String" value="zhaichen"/>
        </bean>
    
  • 通过参数名来设置

    <!--    3.直接通过参数名来设置-->
        <bean id="user" class="com.zhai.pojo.User">
            <constructor-arg name="name" value="zhai"/>
        </bean>
    

在配置文件加载的时候,容器中的对象就已经初始化了

4、Spring配置

4.1别名
<!--别名,可以使用别名获取到Bean-->
    <alias name="user" alias="userNew"/>
4.2Bean的配置
<!--
    id:bean的唯一标识符,也就是相当于变量名
    class:bean对象所对应的全限定名:包名+类名
    name:也是别名,可以同时取多个别名
-->
    <bean id="userT" class="com.zhai.pojo.UserT" name="user2 u2">
        <property name="name" value="zhaichenji"/>
    </bean>
  1. import

    一般用于团队开发使用,可以将多个配置文件,导入合成一个

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

    • applicationContext.xml

      	<import resource="beans.xml"/>
          <import resource="beans2.xml"/>
          <import resource="beans3.xml"/>
      

5、依赖注入

5.1构造器注入
5.2Set方式注入【重点】
  • 依赖注入:set注入

    • 依赖:bean对象的创建依赖容器

    • 依赖:bean对象中的所有属性,有容器来注入

【环境搭建】

  1. 复杂类型

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

    	private String name;
        private Address address;
        private String[] books;
        private List<String> hobbys;
        private Map<String,String> card;
        private Set<String> games;
        private String wife;
        private Properties info;
    
  3. beans.xml

    <bean id="student" class="com.zhai.pojo.Student">
    <!--        1.普通值,直接使用 value-->
            <property name="name" value=""/>
    
        </bean>
    
  4. 测试类

    public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
            Student student =(Student) context.getBean("student");
            System.out.println(student.getAddress());
        }
    
  5. 完善注入信息

    <bean id="address" class="com.zhai.pojo.Address">
            <property name="address" value="宁夏"/>
        </bean>
        <bean id="student" class="com.zhai.pojo.Student">
            <!--        1.普通值,直接使用 value-->
            <property name="name" value=""/>
            <!--        2.Bean注入,使用ref-->
            <property name="address" ref="address"/>
            <!--        3.数组注入-->
            <property name="books">
                <array>
                    <value>红楼梦</value>
                    <value>数据结构</value>
                    <value>大数据</value>
                    <value>人工智能</value>
                </array>
            </property>
    <!--        4.List数组注入-->
            <property name="hobbys">
                <list>
                    <value></value>
                    <value></value>
                    <value></value>
                </list>
            </property>
    <!--        5.map注入-->
            <property name="card">
                <map>
                    <entry key="身份证" value="142536633320125582"/>
                    <entry key="银行卡" value="6969665542201236875"/>
                </map>
            </property>
    <!--        6.set注入-->
            <property name="games">
                <set>
                    <value>LOL</value>
                    <value>DNF</value>
                    <value>CSGO</value>
                </set>
            </property>
    <!--        7.null注入-->
            <property name="wife">
                <null/>
            </property>
    <!--        8.Properties注入-->
            <property name="info">
                <props>
                    <prop key="学号">12018242282</prop>
                    <prop key="性别"></prop>
                    <prop key="专业">软件工程</prop>
                </props>
            </property>
        </bean>
    
5.3拓展方式注入

可以使用p命名空间和c命名空间进行属性注入

官方解释:

在这里插入图片描述
在这里插入图片描述

使用:

<!--    p命名空间注入,可以直接注入属性值:property-->
    <bean id="user" class="com.zhai.pojo.User" p:name="小明" p:age="18"/>
    <!--    c命名空间注入,可以通过构造器注入属性值:constructs-args-->
    <bean id="user2" class="com.zhai.pojo.User" c:name="小明" c:age="18"/>

测试:

@Test
    public void test2(){
        //p命名空间
        ApplicationContext context = new ClassPathXmlApplicationContext("userbeans.xml");
        User user = context.getBean("user", User.class);
        System.out.println(user);
    }
    @Test
    public void test3(){
        //c命名空间
        ApplicationContext context = new ClassPathXmlApplicationContext("userbeans.xml");
        User user = context.getBean("user2", User.class);
        System.out.println(user);
    }

注意点:p命名空间和c命名空间不能直接使用,需要导入xml约束

		xmlns:p="http://www.springframework.org/schema/p"
       	xmlns:c="http://www.springframework.org/schema/c"
5.4bean的作用域

在这里插入图片描述

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

        <bean id="user2" class="com.zhai.pojo.User" c:name="18" c:age="小明" scope="singleton"/>
    
    
  2. 原型模式:每次容器中get的时候,都会产生一个新对象

        <bean id="user2" class="com.zhai.pojo.User" c:name="18" c:age="小明" scope="prototype"/>
    
    
  3. 其余的request、session、application只能在web开发中使用到!

6、Bean的自动装配

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

三种装配方式:

  1. 在xml中显示的配置
  2. 在java中配置
  3. 隐式的自动装配【重要】
6.1、测试
  1. 环境搭建:一个人有两个宠物
6.2、ByName自动装配
<!--    会自动在容器上下文中查找,和自己对象set方法后的值对应的bean id-->
    <bean id="people" class="com.zhai.pojo.People" autowire="byName">
        <property name="name" value="小明"/>
        <!--        <property name="cat" ref="cat"/>-->
        <!--        <property name="dog" ref="dog"/>-->
    </bean>
6.3、ByType自动装配
<!--    会自动在容器上下文中查找,和自己对象类型属性相同的bean,且类型必须全局唯一,甚至无需写id-->
    <bean id="people" class="com.zhai.pojo.People" autowire="byType">
        <property name="name" value="小明"/>
        <!--        <property name="cat" ref="cat"/>-->
        <!--        <property name="dog" ref="dog"/>-->
    </bean>

小结:

  • byName时,需保证所有bean的id唯一,且这个bean需要和自动注入的属性set方法一致
  • byType时,需保证所有bean的class唯一,且这个bean需要和自动注入的属性类型一致
6.4、 使用注解实现自动装配

Spring从2.5开始支持注解

“基于注解的配置的引入提出了一个问题,即这种方法是否比 XML“更好”。简短的答案是“取决于情况”。”

使用注解须知:

  1. 导入约束:context约束

  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
            http://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/>
    
    </beans>
    
    

    @Autowired:

    1、直接在属性上使用即可,也可以在set方法上使用**

    2、使用@Autowired可以不写set方法,前提是自动装配属性在IOC中(Spring中)存在,且符合名字byName

    注:

    @Nullable 被次注解标记的字段,值可以为Null
    
    //如果显示required 的属性为false,则该值可以为null
    public @interface Autowired {
        boolean required() default true;
    }
    

    测试代码:

    public class People {
        //如果显示required 的属性为false,则该值可以为null
        @Autowired(required = false)
        private Cat cat;
        @Autowired
        private Dog dog;
        private String name;
    }
    

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

    public class People {
        @Autowired
        @Qualifier(value = "cat111")
        private Cat cat;
    
        @Autowired
        @Qualifier(value = "dog222")
        private Dog dog;
    }
    

    @Resource注解

    public class People {
        @Resource(name = "cat2")
        private Cat cat;
        @Resource
    
        private Dog dog;
    
        private String name;
    }
    

    小结:

    @Resource和@Autowired的区别:

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

7、使用注解开发

在Spring4之后,使用注解开发,必须导入AOP的包

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

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       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.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
</beans>
注解
  • @Autowired:通过名字自动装配
    • 如果@Autowired不能唯一的自动装配,则需要使用@Qualifier(value = “xxx”)
  • @Nullable:被此标记标记的属性,可以为null
  • @Resource:通过名字自动装配,其次是类型
  • @Component:放在类上,说明这个类被Spring管理了,就是bean
  1. bean

  2. 属性如何注入

    @Component
    public class User {
        //通过注解赋值
        //相当于<bean name="name" value = "小明"/>
        @Value("小明")
        public String name;
    }
    
  3. 衍生的注解

    @Component有几个衍生注解,web开发中,按照MVC三层架构:

    • dao【@Repository
    • service【@Service
    • controller【@Controller

    四个注解功能一样,都是将类注册到Spring容器中装配bean

  4. 自动装配置

    - @Autowired:通过名字自动装配
      - 如果@Autowired不能唯一的自动装配,则需要使用@Qualifier(value = "xxx")
    - @Nullable:被此标记标记的属性,可以为null
    - @Resource:通过名字自动装配,其次是类型
    
  5. 作用域

    @Component
    //作用域
    @Scope("prototype")
    public class User {
        //通过注解赋值
        //相当于<bean name="name" value = "小明"/>
        @Value("小明")
        public String name;
    }
    
  6. 小结

    xml与注解

    • xml万能,适用于任何场合,维护简单方便
    • 注解不是自己的类使用不了,维护相对复杂

    最佳实践:

    • xml管理bean
    • 注解完成属性注入
    • 在使用过程中,只需要注意一个问题,必须让注解生效,需要开启注解支持
    <!--指定要扫描的包,这个包下的注解就会生效-->
        <context:component-scan base-package="com.zhai"/>
        <context:annotation-config/>
    

8、完全使用Java的方式配置Spring

要完全不使用Spring的xml配置,全权叫个Java来做

JavaConfig是Spring的一个子项目,在Spring4之后,成为了核心功能

实体类

//这个注解的意思就是说明这个类被Spring接管了,注册到了容器中
@Component
public class User {
    private String name;

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

    public String getName() {
        return name;
    }

    //属性注入值
    @Value("小明")
    public void setName(String name) {
        this.name = name;
    }
}

测试类

@Test
    public void Test1() {
        //如果完全使用配置类方式,就只能通过AnnotationConfigApplicationContext上下文来获取容器,通过配置类的class对象加载
        ApplicationContext context = new AnnotationConfigApplicationContext(ZhaiConfig.class);
        User getUser = context.getBean("user", User.class);
        System.out.println(getUser.getName());
    }

这种纯Java的配置方式,在SpringBoot中,随处可见

9、代理模式

为什么学习代理模式?

  • 因为这是SpringAOP的底层【SpringAOP 和 SpringMVC】

代理模式分类:

  • 静态代理
  • 动态代理
9.1、静态代理

角色分析:

  • 抽象角色:一般会使用接口或者抽象类来解决
  • 真实角色:被代理的角色
  • 代理角色:代理真实角色,会做一些附属操作
  • 客户:访问代理对象的人

代码步骤:

  1. 接口

    //租房的接口
    public interface Rent {
        public void rent();
    }
    
  2. 真实角色

    //房东
    public class Host implements Rent{
    
        @Override
        public void rent() {
            System.out.println("房东要出租房子");
        }
    }
    
  3. 代理角色

    public class Proxy implements Rent{
        private Host host;
    
        public Proxy() {
        }
    
        public Proxy(Host host) {
            this.host = host;
        }
    
        public void rent() {
            host.rent();
            seeHouse();
            hetong();
            fare();
        }
    
        //看房
        public void seeHouse(){
            System.out.println("中介带你看房");
        }
        //收中介费用
        public void fare(){
            System.out.println("收中介费");
        }
        //签租赁合同
        public void hetong(){
            System.out.println("签租赁合同");
        }
    }
    
  4. 客户端访问代理角色

    public class Client {
        public static void main(String[] args) {
            //房东要出租房子
            Host host = new Host();
            //代理,中介帮房东出租房子,但是代理角色一般会与一些附属操作
            Proxy proxy = new Proxy(host);
            //你不用面对房东,直接找中介租房子
            proxy.rent();
        }
    }
    

代理模式好处:

  • 可以是真实角色的操作更加纯粹,不用去关注一些公共的业务
  • 公共业务就交给了代理角色去做,实现业务分工
  • 公共业务发生扩展的时候,方便集中管理

代理模式缺点:

  • 一个真实角色就会产生一个代理角色,代码量翻倍,开发效率会变低
9.2、动态代理
  • 动态代理和静态代理角色一样
  • 动态代理的代理类是动态生成的,不是直接写出来的
  • 动态代理分为两大类:
    • 基于接口的动态代理
      • JDK动态代理【使用】
    • 基于类的动态代理
      • cglib
    • java字节码实现:javassist

需要两个类:

  • Proxy:代理
  • InvocationHandler:调用处理程序

动态代理的好处:

  • 可以是真实角色的操作更加纯粹,不用去关注一些公共的业务
  • 公共业务就交给了代理角色去做,实现业务分工
  • 公共业务发生扩展的时候,方便集中管理
  • 一个动态代理类代理的是一个接口,一般就是对应一类业务
  • 一个动态代理类可以代表多个类,只要实现了同一个接口即可

10、AOP

10.1、AOP介绍

在这里插入图片描述

10.2、使用Spring实现AOP

导入AOP依赖包

	<dependencies>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.4</version>
        </dependency>
    </dependencies>

方式一:使用Spring的API接口【主要是SpringAPI接口实现】

<!--    方式一:使用原生Spring API接口-->
    <!--    需要导入aop的约束-->
    <aop:config>
        <!--        切入点:expression:表达式,execution:要执行的位置-->
        <aop:pointcut id="pointcut" expression="execution(* com.zhai.service.UserServiceImpl.*(..))"/>
        <!--        执行环绕增强-->
        <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
    </aop:config>

方式二:自定义来实现AOP【主要是切面】

<!--    方式二:自定义类-->
    <bean id="diy" class="com.zhai.diy.DiyPointCut"/>
    <aop:config>
        <!--        自定义其切面,ref:要引用的类-->
        <aop:aspect ref="diy">
            <!--        切入点-->
            <aop:pointcut id="point" expression="execution(* com.zhai.service.UserServiceImpl.*(..))"/>
            <!--        通知-->
            <aop:before method="before" pointcut-ref="point"/>
            <aop:after method="after" pointcut-ref="point"/>
        </aop:aspect>
    </aop:config>

方式三:使用注解实现

<!--    方式三:使用注解实现-->
    <bean id="annotationPointCut" class="com.zhai.diy.AnnotationPointCut"/>
<!--    开启注解支持-->
    <aop:aspectj-autoproxy/>

11、整合Mybatis

步骤:

  1. 导入相关jar包

    • junit
    • myBatis
    • mysql数据库
    • spring相关
    • aop织入
    • mybaits-spring【new】
  2. 编写配置文件

  3. 测试

11.1、回忆Mybatis
  1. 编写实体类
  2. 编写核心配置文件
  3. 编写接口
  4. 编写Mapper.xml
  5. 测试

12、声明式事务

1、回顾事务
  • 要么都成功,要么都失败
  • 事务在项目开发中,十分重要,涉及到数据的一致性问题,不能马虎
  • 确保完整性和一致性

事务的ACID原则:

  • 原子性
  • 一致性
  • 隔离性
    • 多个业务可能操作同一个资源,防止数据损坏
  • 持久性
    • 事务一旦提交,无论系统发生什么问题,结果都不会被影响,被持久化的写入到存储器中
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值