后端主流框架Spring基础

50 阅读6分钟

image.png

常见的设计模式

image.png

单例模式

单例模式是保障了程序运行期间,一个类只能有一个对象(实例)的代码开发模块
使用场景:工具类(一种做法,所有的方法都是static,还有一种单例模式让工具类只有一个实例), 某类工厂(SqlSessionFactory)
以下为三种实现方式:

饿汉模式(迫切加载)

实现方式

public class Singleton {
    //构造方法私有化保证自己才能创建
    public Singleton() {
    }
    //创建一个private对象
    private static final Singleton INSTANCE = new Singleton();
    //提供一个方法来获取这个单例对象
    public static Singleton getInstance(){
        return INSTANCE;
    }
}

调用方法查看是否是调用的同一个对象

Singleton instance = Singleton.getInstance();
Singleton instance02 = Singleton.getInstance();
System.out.println(instance02);
System.out.println(instance);

image.png 调用两个方法的地址值相同,可以看出调用的同一个对象

懒汉模式(懒加载)

饿汉模式的方法不管用不用都会创建,占用资源,懒汉模式只在需要的时候再创建

实现方式

以下为多线程容易出现问题的

//构造方法私有化保证自己才能创建
public Singleton02() {
}
//创建一个private对象
private static  Singleton02 INSTANCE =null;
//提供一个公有方法来获取这个单例对象
public static Singleton02 getInstance(){
    //如果为null就是没有创建过,进if创建
    //多线程容易出问题的位置
    if (INSTANCE==null){
        INSTANCE=new Singleton02();
    }
    //如果创建过,直接返回INSTANCE
    return INSTANCE;
}

修改后:双重校验加同步锁

//构造方法私有化保证自己才能创建
public Singleton02() {
    System.out.println(Thread.currentThread().getName());
}
//创建一个private对象
private static  Singleton02 INSTANCE =null;
//提供一个公有方法来获取这个单例对象
public static Singleton02 getInstance(){

    if (INSTANCE==null){
        //加代码块锁防止多线程问题
        synchronized (Singleton02.class){
            //如果为null就是没有创建过,进if创建
            if (INSTANCE==null){
                INSTANCE=new Singleton02();
            }
        }
    }
    //如果创建过,直接返回INSTANCE
    return INSTANCE;
}

测试方法:

for (int i = 0; i < 10; i++) {
    new Thread(() -> {
        Singleton02.getInstance();
    }).start();
}

枚举

工厂模式

对象工厂使用别人的包,如果别人改名字,会影响到自己代码的运行,可以使用映射并用配置文件进行解耦

public class ObjectFactory {
    /**
     * 对象工厂,传入对象字节码就能创建一个对象
     */
    public static Object getObj(String key) throws Exception{
        Properties properties = new Properties();
        properties.load(ObjectFactory.class.getClassLoader().getResourceAsStream("factory.properties"));
        String value = properties.getProperty("key");
        Object o = Class.forName(value).newInstance();
        return o;
    }
}

配置文件factory.properties

factory.date=java.util.Date//如果别人改包名,只要把java.util.Date改了就行

Spring

概念

Spring是一个开源的轻量级控制反转(IOC:将对象交给框架管理)和面向切面编程(AOP)的容器框架; Spring是Bean的容器,Bean就是对象,之前都是自己new对象,而有了Spring框架就不用new,直接用就行

导包&配置

需要哪个模块自己下载 image.png

完成第一个Spring

 <dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-context</artifactId>
     <version>5.2.4.RELEASE</version>
</dependency>

准备Spring配置文件

  • 在resources下新建一个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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">

</beans>

将类交给Spring容器中

  • 准备一个普通的类
public class Hello {
    public void test(){
        System.out.println("hello.Spring");
    }
}
  • 将它交到Spring容器, 在applicationContext.xml里配置
<!--配置bean,将类交给spring容器管理,表示对象配置
    id属性: bean的唯一标识
    class属性:  类的全限定名-->
    
    <bean id="hello" class="com.lifei._03Spring.Hello"></bean>

注意:Spring容器中不允许有两个名字【不管是id指定还是name指定】一个的对象

Spring容器的实例化

Spring容器对象有两种:BeanFactory和ApplicationCOntext

BeanFactory

  • BeanFactory是一个接口,可以通过其实现类XmlBeanFactory获取其实例。
//读取配置文件
ClassPathResource resource = new ClassPathResource("applicationContext.xml");
//拿到BeanFactory接口
XmlBeanFactory factory = new XmlBeanFactory(resource);
//从工厂中获取Bean
Hello hello = (Hello) factory.getBean("hello");
//调用
hello.test();

//以下为调用另外两种方式
Hello hello1 = factory.getBean(Hello.class);
hello1.test();
Hello hello2 = factory.getBean("hello", Hello.class);
hello2.test();

执行以上代码,可以调到Hello类里的方法:

image.png

ApplicationCOntext(常用)

//加载工程classpath下的配置文件实例化
ApplicationContext factory = new ClassPathXmlApplicationContext("applicationContext.xml");
Hello hello = factory.getBean("hello", Hello.class);
hello.test();

ApplicationCOntext和`BeanFactory的区别

  • ApplicationCOntext是继承于BeanFactory
  • ApplicationCOntext是迫切加载(默认是在读取配置文件的时候就会根据配置创建Bean对象),BeanFactory是懒加载(在使用的时候才进行对象的创建)

让ApplicationCOntext也成为懒加载

  • 配置一:让所有Bean都变成懒加载,只需要在标签中加入default-lazy-init="true"

image.png

  • 配置二:让其中一个Bean变成懒加载,在标签中加入**lazy-init="true"**

image.png

Spring管理Bean的两种方法

  • 先创建两个类(DaoBean和ServiceBean)
  • 在ServiceBean类里用DaoBean里的方法
public class DaoBean {
   public void testDaoBean(){
       System.out.println("我是dao");
    }
}
public class ServiceBean {
    private DaoBean daoBean;

    public void testServiceBean(){
        System.out.println("我是Service");
        daoBean.testDaoBean();

    }
}

Spring依赖注入

  • Ioc的一个重点是在系统运行中,动态的向某个对象提供它所需要的对象,这一点是通过DI(Dependency Injection,依赖注入)来实现的

xml注入

在xml中进行配置,但这种方法必须要有对应的set和get方法,也被称为属性注入setter方法注入

bean定义

public class ServiceBean {

//set和get方法
    public DaoBean getDaoBean() {
        return daoBean;
    }

    public void setDaoBean(DaoBean daoBean) {
        this.daoBean = daoBean;
    }

    private DaoBean daoBean;


    public void testServiceBean(){
        System.out.println("我是Service");
        daoBean.testDaoBean();

    }
}

xml配置:

image.png 测试:

ApplicationContext factory = new ClassPathXmlApplicationContext("applicationContext.xml");
ServiceBean serviceBean = factory.getBean("serviceBean", ServiceBean.class);
serviceBean.testServiceBean();

image.png

注解注入

  • 需要在核心配置文件里面用约束开启注解扫描
<?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
"
>
  • 加注解

    @Controller , @Service , @Repository(往持久层打,dao/mapper), @component(往工具类或者公共类打)

<!--    开启注解扫描  -->
    <context:component-scan base-package="com.lifei._05annotation"></context:component-scan>

测试注解

  • 在上面的两个类中测试(注解扫描就是刚刚配的那个),在DaoBean上面打@Repository

image.png

  • ServiceBean类上打@Service,而要获取DaoBean类的数据,还需要在属性上打@Autowired注解或者@Resource注解

image.png 测试类同上
@Autowired和@Resource区别:
@Autowired:先根据类型查找,如果找到多个,再根据名字查找
@Resource: 先根据名字查找,如果找到多个,再根据类型查找

Spring测试

image.png

第一步:导包

 <dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-test</artifactId>
     <version>5.2.4.RELEASE</version>
</dependency>

第二步:编写注解和方法

注解

  • @RunWith:表示先启动Spring容器,把junit运行在Spring容器中
  • @ContextConfiguration("classpath:applilcationContext.xml"):表示从classpath路径去加载配置文件
  • @Autowired:表示自动装配,自动从Spring容器中取出对应Bean复制给当前使用的属性

Spring测试代码

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class MyTest02 {

    @Autowired
    private ApplicationContext factory;
    
    @Autowired(取代下面那行代码)
    private ServiceBean serviceBean;

    @Test
    public void test01(){
//        ServiceBean serviceBean = factory.getBean("serviceBean", ServiceBean.class);
        serviceBean.testServiceBean();
    }
}

配置细节

作用域

Spring默认是单例

代码证明:

ServiceBean serviceBean = factory.getBean("serviceBean", ServiceBean.class);
ServiceBean serviceBean02 = factory.getBean("serviceBean", ServiceBean.class);
System.out.println(serviceBean==serviceBean02);

image.png

通过xml的Bean元素中的scope属性指定

  • singleton:默认值,单例
  • prototype:多例
<bean id="daoBean" class="com.lifei._04di.DaoBean" scope="prototype"></bean>

通过注解配置

在类上方打注解@Scope("prototype") 或着@Scope("singleton")

image.png

其他属性值(一般都不用)

image.png

Bean对象的生命周期

  • 生命周期值得是:从对象创建、初始化、调用执行到销毁的一个过程
  • 不同作用域的Bean,生命周期有所区别:

1、 Spring管理的Bean对象默认是单例,生命周期会从创建到结束

2、多例的生命周期是:创建 -> 初始化 -> 工作 ,没有销毁

Bean类的创建和初始化:

public class MyBean {
    public MyBean() {
        System.out.println("对象创建");
    }
    public void init(){
        System.out.println("对象初始化");
    }
    public void work(){
        System.out.println("对象工作");
    } public void destroy(){
        System.out.println("G了");
    }
}

配置文件:

<bean id="myBean" class="com.lifei._03Spring.MyBean" init-method="init" destroy-method="destroy"></bean>

注解版本:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class MyTest02 {

    @Autowired
    private MyBean myBean;

    @Test
    public void test(){
        myBean.work();
    }
}

结果:

image.png