其他分享
首页 > 其他分享> > Spring5

Spring5

作者:互联网

Spring5

1、Spring

1.1、简介

官网:https://spring.io/

下载历史版本地址:https://repo.spring.io/ui/native/release/org/springframework/spring

文档:https://docs.spring.io/spring-framework/docs/current/reference/html/index.html

API文档:https://docs.spring.io/spring-framework/docs/current/javadoc-api/

Github:https://github.com/spring-projects/spring-framework

<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.3.20</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.3.20</version>
</dependency>

1.2、优点

总结:Spring就是一个轻量级的控制反转(IOC)和面向切面编程(AOP)的框架

1.3、组成

image-20220608143957536

1.4、拓展

在Spring的官网有这个介绍:现代化的Java开发!说白了就是基于Spring开发

img

因为现在大多数公司都在使用SpringBoot进行快速开发,学习SpringBoot的前提,需要完全掌握Spring及SpringMVC!

承上启下的作用!

唯一弊端:发展了太久,违背了原来的理念。配置十分繁琐,人称“配置地狱”。

2、IOC理论推导

原始业务实现

  1. UserDao接口

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

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

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

public class UserServiceImpl implements UserService{
    private UserDao userDao=new UserDaoImpl();
    public void getUser() {
        userDao.getUser();
    }
}

在我们之前的业务中,用户的需求可能会影响我们原来的代码,我们需要根据用户的需求去修改源代码!

如果程序代码量十分庞大,修改一次的成本代价十分昂贵!

我们使用一个Set接口实现,已经发生革命性变化!

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

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

这是IOC的原型!

image-20220609144122291

IOC本质

控制反转IoC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IoC的一种方法,也有人认为DI只是IoC的另一种说法。没有IoC的程序中 , 我们使用面向对象编程 , 对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转。

采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。

控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)。

3、HelloSpring

实体类

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 + '\'' +
                '}';
    }
}

配置文件

<?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">
        <!--使用Spring来创建对象,在Spring这些都称为Bean
        Hello hello=new Hello();
        bean=对象 new Hello();
        id=变量名
        class=new 的对象
        property 相当于给对象的属性设置一个值!
        -->
        <bean id="hello" class="com.iamning.pojo.Hello">
            <property name="str" value="Spring"/>
        </bean>
</beans>

测试代码:

public class MyTest {
    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是一种编程思想,由主动的编程变成被动的接收

可以通过newClassPathXmlApplicationContext去浏览一下底层源码 .

**OK , 到了现在 , 我们彻底不用再程序中去改动了 , 要实现不同的操作 , 只需要在xml配置文件中进行修改
, 所谓的IoC,一句话搞定 : 对象由Spring 来创建 , 管理 , 装配 ! **

4、IOC创建对象的方式

  1. 使用无参构造创建对象,默认!

  2. 假设我们要使用有参构造创建!

    1. 下标赋值

         <!--第一种通过下标赋值-->
          <bean id="user" class="com.iamning.pojo.User">
              <constructor-arg index="0" value="张三"/>
          </bean>
      
    2. 根据类型创建

         <!--第二种方式是通过类型创建,不建议使用!-->
          <bean id="user" class="com.iamning.pojo.User">
              <constructor-arg type="java.lang.String" value="李四"/>
          </bean>
      
    3. 参数名

      <!--第三种方式:直接通过参数名创建-->
          <bean id="user" class="com.iamning.pojo.User">
              <constructor-arg name="name" value="王五"/>
          </bean>
      

总结:在配置文件加载的时候,容器中管理的对象就已经初始化了!

5、Spring配置

5.1、别名

<!--别名,如果添加了别名,我们也可以使用别名获取到这个对象-->
<alias name="user" alias="userNew"/>

5.2、Bean的配置

<!--id:bean的唯一标识符,也就是相当于我们学的对象名
class:bean对象所对应的全限定名:包名+类型
name:也是别名,而且name可以同时取多个别名
-->
<bean id="userT" class="com.iamning.pojo.UserT" name="user2,u2 u3">
    <property name="name" value="张三疯"/>
</bean>

5.3、import

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

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

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

使用的时候直接使用总的配置就可以了

6、DI依赖注入

6.1、构造器注入

前面已经提过了

6.2、Set方式注入(重点)

[环境搭建]

  1. 复杂类型

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

    @Data
    public class Student {
        private String name;
        private Address address;
        private String[] books;
        private List<String> hobbys;
        private Map<String,String> card;
        private Set<String> games;
        private Properties info;
        private String wife;
    }
    
  3. beans.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 id="student" class="com.iamning.pojo.Student">
            <!--第一种,普通值注入,value-->
            <property name="name" value="张三"/>
        </bean>
    </beans>
    
  4. 测试类

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

完善注入信息

<bean id="address" class="com.iamning.pojo.Address">
    <property name="address" value="兰州"/>
</bean>
<bean id="student" class="com.iamning.pojo.Student">
    <!--第一种,普通值注入,value-->
    <property name="name" value="张三"/>
    <!--第二种,Bean注入,ref-->
    <property name="address" ref="address"/>
    <!--数组注入,-->
    <property name="books">
        <array>
            <value>本手</value>
            <value>妙手</value>
            <value>俗手</value>
        </array>
    </property>
    <!--List-->
    <property name="hobbys">
        <list>
            <value>唱歌</value>
            <value>跳舞</value>
            <value>篮球</value>
            <value>rap</value>
            <value>你干嘛~~~</value>
        </list>
    </property>
    <property name="card">
        <map>
            <entry key="身份证" value="1562245488798989"></entry>
            <entry key="银行卡号" value="566591568595656"></entry>
        </map>
    </property>
    <property name="games">
        <set>
            <value>LOL</value>
            <value>DOTA2</value>
            <value>COD</value>
        </set>
    </property>
    <!--null-->
    <property name="wife">
        <null/>
    </property>
    <!--Properties-->
    <property name="info">
        <props>
            <prop key="学号">17488155</prop>
            <prop key="性别">男</prop>
            <prop key="姓名">张三疯</prop>
        </props>
    </property>
 </bean>

6.3、拓展方式注入

我们可以使用p命名空间和c命名空间进行注入

官方解释:

image-20220612201134859

<?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命名空间注入,可以直接注入属性的值 p就是property-->
        <bean id="user" class="com.iamning.pojo.User" p:name="张三" p:age="21"/>
        <!--c命名空间注入,通过构造器注入:constructor-->
        <bean id="user2" class="com.iamning.pojo.User" c:age="18" c:name="李四"/>
</beans>

测试:

@Test
public void test2(){
    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"

6.4、Bean的作用域

一共六种作用域

image-20220612201538249

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

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

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

7、Bean的自动装配

在Spring有三种自动转配方式

  1. 在xml中显示的配置
  2. 在java中显示配置
  3. 隐式的自动装配bean(重要)

7.1、测试

环境搭建:一个人有两个宠物~

7.2、ByName自动装配

<!--
byName:会自动在容器上下文中查找,和自己对象set方法后面的值对应的beanid
-->
<bean id="people" class="com.iamning.pojo.People" autowire="byName">
    <property name="name" value="张三"/>
</bean>

7.3、ByType自动装配

   <bean id="cat" class="com.iamning.pojo.Cat"/>
        <bean  class="com.iamning.pojo.Dog"/>
        <!--
        byName:会自动在容器上下文中查找,和自己对象set方法后面的值对应的beanid
        byType:会自动在容器上下文中查找,和自己对象属性类型相同的bean~
        -->
        <bean id="people" class="com.iamning.pojo.People" autowire="byType">
            <property name="name" value="张三"/>
        </bean>

小结:

7.4、使用注解实现自动装配

jdk1.5支持的注解,Spring2.5支持注解

The introduction of annotation-based configuration raised the question of whether this approach is “better” than XML.The short answer is “it depends.”

基于注释的配置的引入引发了这种方法是否比 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
        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(Spring)容器中存在,且符合名字ByType!

科普:

@Nullable 字段标记了这个注解,说明这个注解可以为null

public @interface Autowired {
    boolean required() default true;
}

如果@AutoWired自动装配的环境比较复杂,自动装配无法通过一个注解[@AutoWired]完成的时候,我们可以使用@Qualifier(value = "xxxx")去配合@AutoWired,指定一个唯一的bean对象注入!

public class People {
    //如果显示定义了Autowired的required属性为false,说明这个对象可以为null,否则不允许为空
    @Autowired
    @Qualifier(value = "cat111")
    private Cat cat;
    @Autowired
    @Qualifier(value = "dog222")
    private Dog dog;
    private String name;
}

@Resource注解

public class People {
    //如果显示定义了Autowired的required属性为false,说明这个对象可以为null,否则不允许为空
    @Resource(name = "cat2")
    private Cat cat;
    @Resource
    private Dog dog;
    private String name;
}

小结:

@Resource和AutoWired的区别:

8、使用注解开发

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

image-20220615161340733

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

<?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>
  1. bean

  2. 属性如何注入

    //等价于    <bean id="user" class="com.iamning.pojo.User"/>
    //@Component 组件
    @Component
    public class User {
        //相当于   <property name="name" value="张三"/>
        @Value("张三")
        public String name;
    }
    
  3. 衍生的注解

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

    • dao[@Repository]

    • service[@Service]

    • controller[@Controller]

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

  4. 自动装配置

    @AutoWired:通过ByType的方式自动装配,
    @Resource:默认通过ByName的方式自动转配。
    @Nullable:字段标记了这个注解,说明这个字段可以为null
    @Component:组件,放在类上,说明这个类被Spring管理了,就是bean。
    
  5. 作用域

    @Component
    @Scope("singleton")
    public class User{
        //相当于   <property name="name" value="张三"/>
        @Value("张三")
        public String name;
    }
    
  6. 小结

    xml和注解:

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

    xml和注解的最佳实践

    • xml用来管理bean

    • 注解只负责属性的注入

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

      <!--指定要扫描的包,这个包下的注解就会生效-->
      <context:component-scan base-package="com.iamning"/>
      <!--开启注解支持-->
      <context:annotation-config/>
      

9、使用Java的方式配置Spring

现在要完全不使用Spring的xml配置,全权交给java来做!

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

image-20220615201415637

实体类:

//@Component这里这个注解的意思,就是说明这个类被Spring接管了,注册到了容器中
@Component
@ToString
public class User {
    private String name;
    public String getName() {
        return name;
    }
    @Value("张三")
    public void setName(String name) {
        this.name = name;
    }
}

配置文件:

package com.iamning.config;
import com.iamning.pojo.User;
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.iamning.pojo")
@Import(Iamning2Config.class)
public class IamningConfig {
    //注册一个bean,就相当于我们之间写的一个bean标签,
    //这个方法的名字,就相当于bean便签的id属性
    //这个方法的返回值,就相当于bean便签的class属性
    @Bean
    public User getUser(){
        return new User();//就是要返回注入到bean的对象!
    }
}

测试类

public class MyTest {
    public static void main(String[] args) {
        //如果完全使用了配置类方式去做,我们就只能通过AnnotationConfig上下文获取容器,通过配置类的class对象加载!
        ApplicationContext context = new AnnotationConfigApplicationContext(IamningConfig.class);
        User getUser =(User) context.getBean("getUser");
        System.out.println(getUser.getName());
    }
}

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

10、代理模式

为什么要学习代理模式?因为这就是SpringAOP底层![SpringAOP和SpringMVC]

代理模式的分类:

image-20220616214011386

10.1、静态代理

角色分析:

代码步骤:

  1. 接口

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

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

    @NoArgsConstructor
    @AllArgsConstructor
    public class Proxy implements Rent{
        private Host host;
    
    
        public void rent() {
            seeHouse();
            host.rent();
            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();
        }
    }
    

代理模式的好处:

缺点:

10.2、加深理解

代码:对应08-demo02

聊聊AOP

image-20220618161321805

10.3、动态代理

需要了解两个类:Proxy:代理,InvokationHandler:调用处理程序

动态代理的好处:

在原有静态代理所有好处基础上

11、AOP

11.1、什么是AOP

AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善。通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

AOP技术恰恰相反,它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。

OOP引入封装、继承、多态等概念来建立一种对象层次结构,用于模拟公共行为的一个集合。不过OOP允许开发者定义纵向的关系,但并不适合定义横向的关系,例如日志功能。日志代码往往横向地散布在所有对象层次中,而与它对应的对象的核心功能毫无关系对于其他类型的代码,如安全性、异常处理和透明的持续性也都是如此,这种散布在各处的无关的代码被称为横切(cross cutting),在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。

image-20220619205029732

11.2 AOP在Spring中的作用

提供声明式事务,允许用户自定义切面

SpringAOP中,通过Advice定义横切逻辑,Spring中支持5种类型的Advice:

按照增强在目标类方法连接点的位置可以将增强划分为以下五类:

  1. 前置增强 (org.springframework.aop.BeforeAdvice) 表示在目标方法执行前来实施增强
  2. 后置增强 (org.springframework.aop.AfterReturningAdvice)表示在目标方法执行后来实施增强
  3. 环绕增强 (org.aopalliance.intercept.MethodInterceptor)表示在目标方法执行前后同时实施增强
  4. 异常抛出增强 (org.springframework.aop.ThrowsAdvice) 表示在目标方法抛出异常后来实施增强
  5. 引介增强 (org.springframework.aop.introductioninterceptor)表示在目标类中添加一些新的方法和属性

即AOP在不改变源代码的情况下,去增加新的功能

11.3、使用Spring实现AOP

[重点]使用AOP织入,需要导入一个依赖包

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.5</version>
</dependency>

方式一:使用Spring的API接口[主要是SpringApi接口实现]

方式二:自定义类来实现AOP[主要是切面定义]

方式三:使用注解实现!

12、整合Mybatis

步骤:

  1. 导入相关jar包
    • junit
    • mybatis
    • mysql数据库
    • Spring相关的
    • aop织入
    • mybatis-spring[new]
  2. 编写配置文件
  3. 测试

12.1、回忆Mybatis

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

12.2、Mybatis-Spring

  1. 编写数据源配置
  2. SqlSessionFactory
  3. SqlSessionTemplate
  4. 需要给接口加实现类[]
  5. 将自己写的实现类,注入到Spring中
  6. 测试使用即可

13、声明式事务

1、回顾事务

事务ACID原则:

2、Spring中的事务管理

思考:为什么需要事务?

标签:String,Spring,代理,public,注解,class,Spring5
来源: https://www.cnblogs.com/iamning/p/16403814.html