Spring

目录

1. 简介

概述

组成

扩展

2. IOC

1.创建dao层

2.创建service层

3.Test测试

4.优化代码

 修改Test测试类

3.IOC本质

5.使用xml文件实现IOC

4. IOC创建对象的方式

5.Spring配置

6. Di依赖注入

1.构造器注入

2.Set注入[重点]

3.拓展方式注入

7. Bean的作用域

测试

1.ByName自动装配

2.ByType自动装配

3.使用注解实现自动装配

8.使用注解开发

1.bean

2.属性如何注入

3.衍生的注解

4.自动装配

5.作用域

6.小结

9. 使用Java的方式配置Spring

10. 代理模式

1.静态代理

3.动态代理


1. 简介

Spring: 春天------>给软件行业带来了春天

概述

  • 2004年3月24日,Spring框架以interface21框架为基础,经过重新设计,发布了1.0正式版本。

  • Spring理念:使现有技术更加实用。本身就是一个大杂烩,整合现有的框架技术。

  • 经典: Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。

优点 :

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

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

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

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

详情简介参考各大网站

组成

 

扩展

SpringCloud

 

 Spring官网介绍: 现代化Java开发! 基于Spring的开发

 

  • Spring Boot

一个快速开发的脚手架

基于SpringBoot可以快速的开发单个微服务

约定大于配置!

  • Spring Cloud

    SpringCloud 是基于SpringBoot实现的.

学习SpringBoot的前提, 需要完全掌握Spring及SpringMVC!承上启下的作用!

2. IOC

IOC原型

 

 

1.创建dao层

package cn.you.dao;

public interface UserDao {
    void getUser();
}
package cn.you.dao;

public class UserDaoImpl implements UserDao {


    public void getUser() {
        System.out.println("默认获取用户的数据");
    }
}
package cn.you.dao;

public class UserDaoMysqlImpl implements UserDao{

    public void getUser() {
        System.out.println("Mysql获取用户数据!");
    }
}
package cn.you.dao;

public class UserDaoOracleImpl implements UserDao{

    public void getUser() {
        System.out.println("Oracle获取用户数据! ");
    }
}

2.创建service层

package cn.you.service;

public interface UserService {
    void getUser();
}
package cn.you.service;

import cn.you.dao.UserDao;
import cn.you.dao.UserDaoOracleImpl;

public class UserServiceImpl implements UserService{

    private UserDao userDao = new UserDaoOracleImpl();

    public void getUser() {
        userDao.getUser();
    }
}

3.Test测试

import cn.you.service.UserService;
import cn.you.service.UserServiceImpl;

public class Test {
    public static void main(String[] args) {
        //用户实际调用的是业务层,dao层他们不需要接触!
        UserService userService = new UserServiceImpl();
        userService.getUser();
    }
 }

 

  • 由于我们在UserServiceImpl类中我们手动选择了UserDaoOracleImpl,所以此时输出的为Oracle获取用户数据;(此时程序的选择在我们程序员选择);

  • 然而用户的需求可能会影响我们原先的代码,所以我们需要对程序做出优化;

  • 使用户想要什么样的选择,程序就会给出对于用户所选择的程序;

4.优化代码

修改UserServiceImpl类

 package cn.you.service;

import cn.you.dao.UserDao;

public class UserServiceImpl implements UserService{

    private UserDao userDao;

    //利用set进行动态实现值得注入!
    public void setUserDao(UserDao userDao){
        this.userDao = userDao;
    }
    public void getUser() {
        userDao.getUser();
    }
}
  • 我们使用一个set接口实现,使程序本身发生了革命性的变化;

 修改Test测试类

import cn.you.dao.UserDaoOracleImpl;
import cn.you.service.UserService;
import cn.you.service.UserServiceImpl;

public class Test {
    public static void main(String[] args) {
        //用户实际调用的是业务层,dao层他们不需要接触!
    UserService userService = new UserServiceImpl();
        ((UserServiceImpl)userService).setUserDao(new UserDaoOracleImpl());

                userService.getUser();
    }
}

 

3.IOC本质

  • IOC是Spring框架的核心内容, 使用多种方式完美实现了IOC,可以使用注解,也可以使用XML配置, 新版Spring可以零配置实现IOC

  • Spring容器初始化时会先读取读取配置文件,根据配置文件或者元数据创建与组织对象储存容器中,程序使用时再从IOC容器中取出需要的对象.

 注: 所谓的IOC就是对象由Spring来创建,管理,装配 !

5.使用xml文件实现IOC

创建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">

    <!-- services -->

    <bean id="mysqlImpl" class="cn.you.dao.UserDaoMysqlImpl"/>
    <bean id="oracleImpl" class="cn.you.dao.UserDaoOracleImpl"/>

    <bean id="userServiceImpl" class="cn.you.service.UserServiceImpl">
        <property name="userDao" ref="mysqlImpl"/>
    </bean>

    <!--
               ref : 引用Spring容器中创建好的对象
               value : 具体的值 , 基本数据类型!
          -->
</beans>

修改测试类

import cn.you.service.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

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

        // 获取ApplicationContext;
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

        //容器在手 天下我有 需要什么 就直接get什么
        UserServiceImpl userServiceImpl = (UserServiceImpl) context.getBean("userServiceImpl");

        userServiceImpl.getUser();
    }
}
  • 可以通过 ClassPathXmlApplicationContext 浏览底层代码

4. IOC创建对象的方式

新建一个maven项目

pojo

package cn.you.pojo;

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;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }
    public void show() {
        System.out.println("name="+name);
    }
}

测试类

import cn.you.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test_ioc_02 {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        User user = (User) context.getBean("user");
        user.show();
    }
}

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="user" class="cn.you.pojo.User">
        <constructor-arg index="0" value="王狗蛋"/>
    </bean>

</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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 第二种方式: 通过类型创建   不推荐使用  -->
    <bean id="user" class="cn.you.pojo.User">
        <constructor-arg type="java.lang.String" value="王狗蛋"/>
    </bean>
</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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 第三种方式: 直接通过参数名来设置  -->
    <bean id="user" class="cn.you.pojo.User">
        <constructor-arg name="name" value="王狗蛋"/>
    </bean>
</beans>

 

注: 可以看到在配置文件加载的时候 , 容器中管理的对象就已经初始化了 !

5.Spring配置

1. singleton 单例模式 (单线程)

  • (Default) Scopes a single bean definition to a single object instance for each Spring IoC container.

  • (默认)为每个SpringIOC容器将单个bean定义的范围限定为单个对象实例。

2. proptotype 原型模式(多线程)

  • Scopes a single bean definition to any number of object instances.

  • 将单个bean定义的范围限定为任意数量的对象实例。

3. request

  • Scopes a single bean definition to the lifecycle of a single HTTP request. That is, each HTTP request has its own instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring ApplicationContext.

  • 将单个bean定义限定为单个HTTP请求的生命周期。也就是说,每个HTTP请求都有自己的bean实例,该实例是在单个bean定义的后面创建的。仅在支持web的Spring“ApplicationContext”上下文中有效。

4. session

  • Scopes a single bean definition to the lifecycle of an HTTP Session. Only valid in the context of a web-aware Spring ApplicationContext.

  • 将单个bean定义的范围限定到HTTP“会话”的生命周期。仅在支持web的Spring“ApplicationContext”上下文中有效。

5. application

  • Scopes a single bean definition to the lifecycle of a ServletContext. Only valid in the context of a web-aware Spring ApplicationContext.

  • 将单个bean定义限定为“ServletContext”的生命周期。仅在支持web的Spring“ApplicationContext”上下文中有效。

6. websocket

  • Scopes a single bean definition to the lifecycle of a WebSocket. Only valid in the context of a web-aware Spring ApplicationContext.

  • 将单个bean定义的范围限定到WebSocket的生命周期。仅在支持web的Spring应用程序上下文的上下文中有效。

6. Di依赖注入

1.构造器注入

@Autowired

2.Set注入[重点]

<?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="address" class="cn.you.pojo.Address">
        <property name="address" value="上海"/>
    </bean>


    <bean id="student" class="cn.you.pojo.Student">

        <!-- 第一种, 普通方式注入 -->
        <property name="name" value="王狗蛋"/>

        <!-- 第二种, Bean注入,ref  -->
        <property name="address" ref="address"/>

        <!-- 数组注入,ref  -->
        <property name="books">
            <array>
                <value>红楼梦</value>
                <value>西游记</value>
                <value>水浒传</value>
                <value>三国演义</value>
            </array>
        </property>

        <!-- List注入 -->
        <property name="hobby">
            <list>
                <value>敲代码</value>
                <value>看电影</value>
                <value>打游戏</value>
                <value>听歌</value>
            </list>
        </property>

        <!-- Map注入 -->
        <property name="card">
            <map>
                <entry key="身份证" value="00000000000001"/>
                <entry key="手机号" value="119"/>
            </map>
        </property>

        <!-- Set注入 -->
        <property name="games">
            <set>
                <value>DNF</value>
                <value>LOL</value>
                <value>CF</value>
            </set>
        </property>

        <!-- null注入 -->
        <property name="wife">
            <null/>
        </property>

        <!-- Property注入 -->
        <property name="info">
            <props>
                <prop key="userid">202107001</prop>
                <prop key="sex">男</prop>
                <prop key="username">王狗蛋</prop>
                <prop key="password">123456</prop>
            </props>
        </property>
    </bean>
</beans>

3.拓展方式注入

<?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命名空间注入, 可以直接注入属性的值: property  -->
  <bean id="user" class="cn.you.pojo.User" p:name="王狗蛋" p:age="99"/>
  <!-- c命名空间注入, 通过构造器注入: construct-args  -->
  <bean id="user2" class="cn.you.pojo.User" c:name="如花" c:age="18"/>
</beans>

7. Bean的作用域

  • 自动装配是Spring满足bean依赖的一种方式

  • Spring会在上下文中自动寻找,并自动给bean装配属性

在Spring中的三种装配方式

  1. 在xml中显示的配置

  2. 在java中显示配置

  3. 隐藏的自动装配bean(重要)

测试

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

1.ByName自动装配

<?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="cat" class="cn.you.pojo.Cat"/>
    <bean id="dao" class="cn.you.pojo.Dog"/>
<!--
    byName: 会自动在容器上下文中查找
            和自己对象set方法后面的值对应的 beanId !
-->
    <bean id="people" class="cn.you.pojo.People" autowire="byName">
        <property name="name" value="王狗蛋"/>
    </bean>

</beans>

2.ByType自动装配

<?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="cat" class="cn.you.pojo.Cat"/>
    <bean id="dao" class="cn.you.pojo.Dog"/>

<!--
 byType: 会自动在容器上下文中查找 和自己对象属性类型相同bean! -->
    <bean id="people" class="cn.you.pojo.People" autowire="byType">
        <property name="name" value="王狗蛋"/>
    </bean>

</beans>

 

3.使用注解实现自动装配

  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"
       xmlns:aop="http://www.springframework.org/schema/aop"
       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
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/context/spring-aop.xsd">

     <!-- 配置注解的支持 -->
    <context:annotation-config/>


    <bean id="cat" class="cn.you.pojo.Cat"/>
    <bean id="dao" class="cn.you.pojo.Dog"/>


    <bean id="people" class="cn.you.pojo.People" >

    </bean>

</beans>

 

 

可以看到我们使用了@Autowired注解 直接可以反射出Cat和Dao的show方法直接调用输出

  • @Atuowired 直接在属性上使用

拓展 :

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

注解内部

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

测试

//如果显示定义了Autowired的required属性为false,说明这个对象可以为null,否则不能为空
@Autowired(required = false)
private Cat cat;
@Autowired
private Dog dog;
  • 如果@Autwired自动装配的环境比较复杂, 自动装配无法通过一个注解[@Autowired]完成时的时候, 我们可以使用 @Qualifier(value="xxx")去配合 @Autowired 的使用, 使其指定一个唯一的Bean对象注入;

* @Resource : 自动装配通过名字/类型(该注解不是Spring是Java的)

 

  • @Resource和@Autowired的区别

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

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

    • @Resource 默认通过byname的方式实现,如果找不到名字,则通过byType实现!如果两个都找不到的情况下,就报错 ! (常用)

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

      @Resource通过byName的方式实现;

8.使用注解开发

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

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

1.bean

2.属性如何注入

// @Component组件 
// 等于 <bean id="user" class="cn.you.pojo.User"/>
@Component
public class User {

    public String name;

    // 相当于 <property name="name" value="王狗蛋">
    @Value("王狗蛋")
    public void setName(String name){
        this.name = name;
    }
}

3.衍生的注解

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

    • dao [@Repository]

    • service [@Service]

    • controller [@Controller]

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

4.自动装配

@Autowired // 自动装配通过名字/类型
//      如果Autowired不能唯一自动装配上属性,则需要通过@Qualifier(value="xxx)来指定唯一bean
 @Nullable  // 字段标记了这个注解,说明这个字段可以为null;
 @Resource  // 自动装配通过名字/类型

5.作用域

// @Component组件 等于 <bean id="user" class="cn.you.pojo.User"/>
@Component
@Scope("singleton")//选择了单例模式
public class User {

    public String name;

    // 相当于 <property name="name" value="王狗蛋">
    @Value("王狗蛋")
    public void setName(String name){
        this.name = name;
    }
}

6.小结

xml与注解 :

  • xml 更加万能,适用于任何场景! 维护简单方便

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

xml与注解最佳实践 :

  • xml 用来管理bean

  • 注解 只负责完成属性的注入

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

<!--  指定要扫描的包,这个包下得注解就会生效   -->
    <context:component-scan base-package="cn.you"/>
    <!-- 配置注解的支持 -->
    <context:annotation-config/>

9. 使用Java的方式配置Spring

我们现在完全不使用Spring的xml配置了,全权交给Java来做!

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

  • @Configuration

    • 这个也会Spring容器托管, 注册到容器中,因为他本来就是一个@Component

    • @configuration代表这是一个配置类,就和我们之前看的Beans.xml

实体类

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

    public String getName() {
        return name;
    }

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

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

配置类

//这个也会被Spring容器托管, 注册到容器中,因为他本来就是一个@Component
//@configuration代表这是一个配置类,就和我们之前看的Beans.xml
@Configuration
@ComponentScan("cn.you.pojo")
@Import(UserConfig2.class)
public class UserConfig {

    //注册一个Bean , 就相当于我们之前写的一个bean标签
    //这个方法的名字 , 就相当于bean标签中的id属性
    //这个方法的返回值, 就相当于bean标签中的class属性
    @Bean
    public User getUser(){
        return new User(); //就是返回要注入到bean的对象!
    }
}
@Configuration
public class UserConfig2 {
    @Bean
    public User getUser(){
        return new User(); //就是返回要注入到bean的对象!
    }
}

测试类

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

这种纯java的配置方式,在springBoot中随处可见 !

10. 代理模式

为什么要学代理模式? 因为这是SpringAOP的底层 ! 面试必问[SpringAOP 和 SpringMVC]

代理模式的分类 :

  • 静态代理

  • 动态代理

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;
    }

    @Override
    public void rent() {
        seeHouse();
        host.rent();
        hetong();
        fare();
    }
    //看房
    public void seeHouse(){
        System.out.println("中介带你看房");
    }
    //看房
    public void hetong(){
        System.out.println("签租赁合同");
    }
    //收中介费
    public void fare(){
        System.out.println("收中介费");
    }
}

4.客户端访问代理角色

public class Client {
    public static void main(String[] args) {
        //房东要出租房子
        Host host = new Host();
        //代理,中介帮房东出租房子,但是代理角色一般会有一些附属操作!
        Proxy proxy = new Proxy(host);


        //你不用面对房东, 直接找中介租房即可!
        proxy.rent();;
    }

代理模式的好处 :

  • 可以使真实角色的操作更加纯粹 ! 不要去关注一些公共的业务

  • 公共也就交给代理角色 ! 实现了业务的分工 !

  • 公共业务发生拓展的时候, 方便集中管理!

却点 :

  • 一个真实角色就会产生一个代理角色; 代码量会翻倍 (开发效率会变低)

3.动态代理

  • 动态代理和静态代理角色一样

  • 动态代理的代理类是动态生成的, 不是我们直接写好的

  • 动态代理分为两大类 : 基于接口的动态代理 , 基于类的动态代理

    • 基于接口 -- JDK动态代理 (我们在这里使用)

    • 基于类 : cglib

    • Java字节码实现 : javasist

我们需要了解两个类 : Proxy : , InvocationHandler : 调用处理程序实现的接口

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值