其他分享
首页 > 其他分享> > spring5

spring5

作者:互联网

Spring5

1.什么是Spring

  1. 是一个轻量级(jar包少)的开源的JAVAEE框架(容器)

  2. 是为了解决企业应用开发的复杂性

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

  4. 两个核心部分:IOC和AOP

    • IOC:控制反转,把创建对象的过程交给Spring进行管理
    • AOP:面向切面,不修改源代码进行功能增强
  5. Spring的特点

    • 方便解耦,简化开发
    • Aop编程支持
    • 方便程序测试
    • 方便和其他框架进行整合
    • 方便进行事务操作
    • 降低了API的开发难度

    官网下载地址:https://repo1.maven.org/maven2/org/springframework/spring/

    Github下载地址: GitHub - spring-projects/spring-framework: Spring Framework

    Maven(导Spring web Mvc):

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

    1642993352372

2.IOC理论推导

1643013214526

引入:

  1. 首先我们的Dao层和service层

    1643012470603

  2. 当我们业务层Service调用Dao层时,会有一个创建Dao实现类的方法,并且有一个get方法去获取

     public UserDao userDao=new UserDaoImpl();
     //public UserDao userDao=new UserDaoImpl2();  修改的业务
      @Override
        public void getUser() {
            System.out.println(userDao.run());
        }
    
  3. 测试类中

    UserService userService = new UserServiceImpl();
    userService.getUser();
    
  4. 上面的我们就会发现一个弊端,当我们的业务需要修改时,我们必须去修改业务层的代码

  5. 这时就出来了一种解决办法,我们用一个set方法控制创建哪一种业务的对象

    public UserDao userDao;
        public void setUserDao(UserDao userDao){
            this.userDao=userDao;
        }
        @Override
        public void getUser() {
            System.out.println(userDao.run());
        }
    
  6. 测试类时,我们可以先调用set方法来选择不同的业务,这就是IOC的原型

    @Test
        public void test(){
            UserService userService = new UserServiceImpl();
            ((UserServiceImpl)userService).setUserDao(new UserDaoImpl());
            userService.getUser();
        }
    
  7. 我们从主观的去创建对象,变成被动的去接受对象

  8. 这种思想,从本质上解决了问题,我们程序员不需要去管理对象的创建,程序的耦合性降低,可以更加专注在业务的实现上,这就是IOC的原型

3.IOC本质

4.HelloSpring

4.1丶实体类

public class Hello {
    private String name;

    public void setName(String name) {   //注意这里set方法必须有(依赖注入 : 就是利用set方法来进行注入的.)
        this.name = name;
    }
    public void show(){
        System.out.println(name+"你好呀!");
    }
}

4.2丶写bean配置文件

<?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">
 <!--
       原来:Hello hello =new Hello();
       现在:bean就代表一个对象,id是对象名,class是映射到对象类的位置(使用完全限定的类名)
            property 设置属性和属性值,一个属性就要对象相对的set
 -->
 <bean id="Hello" class="com.LiuDeHen.pojo.Hello">
     <property name="name" value="spring"/>
     						value=""//具体的值
     						ref=""//使用Spring容器中创建的对象
 </bean>
</beans>

4.3丶测试

   public void test(){
//       获取Spring上下文对象!
    ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
//    getBean获取id=Hello的bean对象
        Hello hello = (Hello) context.getBean("Hello");
        hello.show();
    }

4.4丶总结:

  1. 上面的过程 就叫控制反转 :
  2. 控制 : 谁来控制对象的创建 , 传统应用程序的对象是由程序本身控制创建的 , 使用Spring后 , 对象是由Spring来创建的 .
  3. 反转 : 程序本身不创建对象 , 而变成被动的接收对象 .
  4. 依赖注入 : 就是利用set方法来进行注入的. (跟上面推导的IOC原型一样)
  5. IOC是一种编程思想 , 由主动的编程变成被动的接收 .
  6. 所谓的IOC就是:Spring去创建,管理,装配对象

5.IOC创建的方式

5.1丶默认

5.2丶 有参构造

5.3丶注意:

spring容器,再一实例化上下文的时候,里面所有bean对象不管是否调用,全部都会创建

6.Spring配置

6.1丶别名

 <alias name="Hello" alias="我是傻逼"/>

6.2丶bean配置

<!--
id:是bean对象的唯一标识符
class:对应类的全限定名:包名+类名
name:别名(所以上面的别名没屌用),并且可以同时设置多个
--> 

 <bean id="Hello" class="com.LiuDeHen.pojo.Hello" name="我是大傻逼 我是小煞笔,我真是傻逼" >
        <constructor-arg name="name" value="spring"/>
        <constructor-arg name="day" value="5"/>
<!--   当传入的值类型是引用类型,可以用ref     -->
    </bean>

6.3丶import

用在团队开发时,可以将多个bean.xml导入合并成一个

 <import resource="bean.xml"/>
 <import resource="bean2.xml"/>
 <import resource="bean4.xml"/>

7.DI依赖注入

7.1丶构造器注入

前面说过

7.2丶set方法注入

7.3丶拓展方式注入

  1. 用的时候先导依赖

       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
    
  2. p命名空间:实质就是set注入

    <!--  p命名空间,就是property属性的缩写-->
        <bean id="name" class="com.LiuDeHen.Dao.Student" p:age="20" p:name="lc"/>
    
  3. c命名空间:实质就是构造器注入

<!--  c:命名空间,就是constructor-arg的缩写  -->
    <bean id="name" class="com.LiuDeHen.Dao.Student" c:name="lc"/>

7.4丶bean作用域

1643076862356

Student name1 = (Student)classEmitterTransformer.getBean("name1");
        Student name2 = (Student)classEmitterTransformer.getBean("name2");
        System.out.println(name1.hashCode());
        System.out.println(name2.hashCode());
发现hashcode不同不是同一个对象

8.bean的自动装配

8.1丶在Spring中有三种装配方式

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

8.2丶byname和byType

<!--
autowire:会在spring容器上下文自动匹配
autowire=byname:根据自己对象set方法后面的值对应的bean id匹配
autowire="byType:根据class你的对象类型来找相同的bean
   -->
<!--    <bean id="Human" class="com.LiuDeHen.Dao.Human" autowire="byName">-->
    <bean id="Human" class="com.LiuDeHen.Dao.Human" autowire="byType">
        <property name="name" value="lc"/>
    </bean>

8.3丶小结

8.4丶使用注解实现自动装配

使用注解须知:

  1. 导入约束:context约束

  2. 配置注解的支持

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

@Autowired:

直接在对应的属性上使用,也可以在set方法上使用

使用Autowired我们可以不用写set方法了,前提是你这个自动装配的的属性在IOC容器里存在,并且Byname对应

当我们设置required=false,说明这个对象可以为null
public @interface Autowired {
    boolean required() default true;
}

注意:

当注入在IoC容器中该类型只有一个时,就通过byType进行装配

当注入容器存在多个同一类型的对象时,就是根据byName进行装配

@Qualifier:

用法: @Qualifier("指向Bean的id")

一般是用来配合@Autowired来使用,指定一个唯一的bean对象注入

1.首先

<!--同一个类型有多个,此时是使用byName来装配 -->
<bean id="dog11" class="com.LiuDeHen.Dao.Dog"/>
 <bean id="dog22" class="com.LiuDeHen.Dao.Dog"/>
 <bean id="cat11" class="com.LiuDeHen.Dao.Cat"/>
 <bean id="cat22" class="com.LiuDeHen.Dao.Cat"/>

2.这个时候实体类

   //此时我们发现id与之bean里的id没有匹配的,所以会报错
    @Autowired
    private Cat cat;
    @Autowired
    private Dog dog;

3.此时可以使用注解@Qualifier指向指定的Bean下的id

    @Autowired
    @Qualifier("cat11")
    private Cat cat;
    @Autowired
    @Qualifier("dog22")
    private Dog dog;

@Resource:

跟@Autowired和@Qualifier联用差不多效果,但是效率偏低

    @Resource
    private Cat cat;
    @Resource(name="dog2")
    private Dog dog;
    private String name;

@Nullable:放在字段上,说明这个字段可以为null

9.使用注解开发

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

1643103585222

导入约束和支持,并需要扫描包

<!--扫描包    -->
    <context:component-scan base-package="com.LiuDeHen.pojo"/>

1.bean

@Component:创建bean对象

2.属性如何注入

@value:给属性赋值:相当于

//Component:跟xml里的创建<bean id="user" class="com.LiuDeHen.pojo.User"> 一样的作用
// Component:组件:放在类上,说明这个类呗Spring管理了,就是bean
@Component
public class User {
    @Value("nb")
    private String name;

3.衍生的注解

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

Dao:[@Repository]

service:[@Service]

controller:[@Controller]

注意:这几个注解的功能是一样的,都是将类注册到Spring容器中

4.自动装配

上面单独说过

@Autowired:和@Qualifier:

@Resource:

@Nullable:放在字段上,说明这个字段可以为null

5.作用域

@Scope("singleton")

6.小结

注解和xml:

10.使用java的方式配置Spring

11.阶段总结

1.什么是spring

  - spring是一个开源轻量级框架
  - 为了简化企业开发

2.spring核心

  - **IOC容器**
  - **AOP切面编程**

3.IOC容器的推导以及意义

  - 原本
      - 在业务层创建Dao层的对象
      - 每使用一个对象创建一次
  - IOC容器的由来
      - 在业务层创建一个set方法,参数为Dao的接口,返回一个Dao对象(多态)
      - 在我们的测试类中,不同的对象只需要设置set里的Dao对象即可
- 意义:**由主动的创建对象,变成我们可以被动的管理对象**,降低耦合性
- **IOC:控制反转**

4.怎么用spring使用IOC容器

4.1丶IOC是一种容器(思想),DI是注入(手段)

      - set注入:
          - 首先必须要有这个set方法
          - 再在property属性中就可以了
      - 构造器注入
          - 首先要有相对应的构造器,默认无参
          - 使用构造器的标签constructor-arg
          - 有使用对应参数名(推荐),参数下标,参数类型多种匹配方式 
      - bean作用域:
          - 属性:scope
          - 有单例,所有对象共用:singleton
          - 原型:单对象独享:prototype

4.2丶使用xml的方式创建

      - 创建实体类
      - 创建bean.xml文件,导入spring容器配置
      - 设置xml文件中的bean,id为唯一标识,class为类的路径,一个bean为一个对象
      - bean中标签property为属性
          - 基础类型:name为属性名,value为值
          - 其他类型,list就是又list标签,array就是array标签等
    - 测试类创建spring容器上下文对象 new ClassPathXmlApplicationContext("xml文件")

4.3丶自动装配(隐式创建):

  - xml和使用java都是显示创建

  - 常用有:byName,ByType

  - autowire=byname:根据id值来自动装配

  - autowire="byType:根据class你的类型来装配

4.4丶使用注解创建

  - 在xml文件中

    ```xml
    <!--扫描包    -->    
    <context:component-scan base-package="com.LiuDeHen"/>
    其他的bean都
    ```

  - 在对应类上使用注解**@Component**,就可以**创建bean**对象

  - 使用@value:给属性赋值

  - 自动装配@Autowired

4.5丶使用全java的方式(在springboot很常用)

  - 创建一个实体类
  - 创建一个配置类,有一个get方法,返回的就是实体类的对象
  - get方法上有一个注解**@Bean**,**创建**一个bean对象,类上有一个注解**@Configurable**实现自动装配
  - 这个类就是之前的xml文件,每一个get方法就是一个xml里的bean对象,方法名是id,返回值是class

12.代理模式

什么是代理模式?

为什么要学代理模式?

代理模式的分类

1643254816638

12.1丶静态代理

角色分析

抽象角色:
//买卖房接口
public interface Rent {
    void rent();
}

真实角色:
//房东类
public class Host implements Rent{
    @Override
    public void rent() {
        System.out.println("房东卖房");
    }
}

代理角色:
//代理类
public class proxy implements Rent{
    private Host H;
    public proxy(Host host){
        H=host;
    }
//继承的父类方法
    @Override
    public void rent() {
        H.rent();
    }
    //自己的方法
    public void sou(){
        System.out.println("收取中介费");
    }
}

客户:
//客户类
public class client{
    public static void main(String[] args) {
        proxy proxy = new proxy(new Host());
        proxy.rent();
    }
}

代理模式的好处:

缺点:

12.2丶加深理解

AOP:面向切面编程,横向开发,再不修改代码的情况下,增加业务

1643273015239

12.3丶动态代理

实现动态代理的步骤

  1. 创建接口,定义目标类要完成的功能
  2. 创建目标类
  3. 创建InvocationHandler接口的实现类,在Invoke()方法中代理类的功能,并返回代理类
    • 调用目标方法
    • 增强功能
  4. 使用Proxy类的静态方法,创建代理对象,并把返回值转为接口类型
卖房接口类
public interface Rent {
public void rent();
}
    
房东类
    public class Host implements Rent{
    @Override
    public void rent() {
        System.out.println("我是房东我要卖房");
    }
}

代理类(动态代理就是控制这里的res,会根据传入的接口和参数返回是哪一个类,从而实现动态)
    //1.实现接口InvocationHandler,重写invoke方法实现代理类要做的功能
 public class proxy implements InvocationHandler {
     //2.创建目标类实现的接口
    private Rent rent;
    proxy(Rent rent){
       this.rent=rent;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object res=null;
//        三个参数,proxy:代理类,method:代理类实现的方法,args:参数
        res=method.invoke(rent,args);
//        3.可以增加一些额外方法
        if (res!=null){

        }
//        返回这个类
        return res;
    }
}
   
客户类    
    
public class client{
    public static void main(String[] args) {
//        1.创建目标对象
        Rent r = new Host();
//        2.自己写的实现InvocationHandle接口的类
        InvocationHandler handler = new proxy(r);
//        3.创建代理对象,并转成接口
        Rent o = (Rent)Proxy.newProxyInstance(r.getClass().getClassLoader(),
                r.getClass().getInterfaces(), handler);
//        4.通过代理执行方法
        o.rent();
    }
    

好处:

13.AOP

13.1丶基础概念:

13.2丶使用Spring的方式实现Aop

导包:aop织入

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

方式一:使用Spring原生API接口

导入约束时一般要导这几种,下面两个就修改最后那一点,比如beans改为aop

1643781073695

方式二:自定义类实现

    <bean id="diy" class="com.LiuDeHen.diy.divPointcut"/>
    <aop:config>
<!--    自定义切面  ref:要引入的类    -->
        <aop:aspect ref="diy">
<!--   切入点 -->
            <aop:pointcut id="point" expression="execution(* com.LiuDeHen.service.userServiceImpl.*(..))"/>
<!--   通知-->
            <aop:after method="After" pointcut-ref="point"/>
            <aop:before method="Before" pointcut-ref="point"/>
        </aop:aspect>
    </aop:config>

方式三:使用注解实现AOP

无非就是

//注册bean(使用前,需要bean里必须有扫描包)
@Component
//开启注解支持,有参数设置为false就是默认为jdk代理,ture为cglie代理
@EnableAspectJAutoProxy
//设置切入面
@Aspect
public class divPointcut {
//    设置切入位置和execution表达式(切入点的位置)
    @After("execution(* com.LiuDeHen.service.userServiceImpl.*(..))")
    public void After(){
        System.out.println("方法执行前");
    }
    @Before("execution(* com.LiuDeHen.service.userServiceImpl.*(..))")
    public void Before(){
        System.out.println("方法执行后 ");
    }

//    在环绕增强中,给定一个参数ProceedingJoinPoint,表示我们要获取处理切入的点
    @Around("execution(* com.LiuDeHen.service.userServiceImpl.*(..))")
    public void around(ProceedingJoinPoint jp) throws Throwable {
        System.out.println("环绕前");
        Object proceed = jp.proceed();
        System.out.println("环绕后");
    }
}

14丶整合Mybatis

15.声明式事务

1.回顾事务

事务的ACID原则(原一隔持):

2.使用声明创建事务

16.总结

标签:对象,创建,代理,private,bean,public,spring5
来源: https://www.cnblogs.com/LiuDeHen/p/15956533.html