Spring框架

一.概述

Spring框架重点提供的: IOC DI AOP
IOC : 控制翻转, 是指把创建对象的权利交给spring.
DI : 依赖注入, 是指把有依赖关系的对象也同时new出来.
AOP : 面向切面编程, 补充了OOP不足

二.IOS的使用

 1.IOC的xml方式–了解

1.1创建Hello类

package cn.tedu.spring;

public class Hello {
    public void hi(){
        System.out.println("hello springioc~");
    }
}

1.2创建User类

package cn.tedu.spring;

public class User {
    public void eat(){
        System.out.println(123);
    }
}

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

    <!--spring认为万物皆是bean,配置bean的位置,spring自动完成ioc
        class属性用来描述类的全路径, id属性用来作为bean的唯一标识
        scope="prototype"用来设置对象是多例的,默认是singleton单例的
        IOC底层是Map结构,Map<id的值,类的对象>,数据结类似: {"hello",new Hello()}
        spring只能用反射创建对象:
        {"hello",Class.forName("cn.tedu.spring.Hello").newInstance() }
    -->
    <bean class="cn.tedu.spring.Hello" id="hello"></bean>

    <bean class="cn.tedu.spring.User" id="user"></bean>

</beans>

1.4创建测试类

package cn.tedu.spring;
import org.junit.jupiter.api.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test1 {
    //测试IOC(创建类+配置类)
    @Test//junit单元测试方法:@Test void public 没有参数
    public void ioc(){
        //1,读取配置文件--参数是配置文件的路径
        ClassPathXmlApplicationContext spring =
                new ClassPathXmlApplicationContext(
                        "spring-config.xml");
        //2,获取spring创建好的对象--参数是配置文件里bean标签的id的值
        Object o = spring.getBean("hello");
        System.out.println(o);//cn.tedu.spring.Hello@43bc63a3
        Hello h = (Hello) o;
        h.hi();

        //单例对象:节省内存和时间,spring框架默认的创建单例对象的方式
        Hello h2 = (Hello) spring.getBean("hello");
//        System.out.println(o2);//cn.tedu.spring.Hello@43bc63a3
        h2.hi();

//java.lang.ClassCastException:cn.tedu.spring.Hello cannot be cast to cn.tedu.spring.User
        //User uu = (User) spring.getBean("hello");
        //System.out.println(uu);

        Object o3 = spring.getBean("user");
        System.out.println(o3);//cn.tedu.spring.User@38425407
        //向下转型:把父类类型变成子类类型,目的要用子类的功能
        User u = (User) o3 ;
        u.eat();
    }
}

2.IOC的注解方式–重点

1, 创建类, 类上使用IOC的注解
2, 创建配置文件, 指定包扫描的路径
3, 直接getBean(“类名首字母要变成小写”)

spring认为万物皆是bean,配置bean的位置,spring自动完成ioc
class属性用来描述类的全路径, id属性用来作为bean的唯一标识
scope="prototype"用来设置对象是多例的,默认是singleton单例的
IOC底层是Map结构,Map<id的值,类的对象>,数据结类似: {"hello",new Hello()}
spring只能用反射创建对象:
{"hello",Class.forName("cn.tedu.spring.Hello").newInstance() }

 2.1创建类

package cn.tedu.spring;

import org.springframework.stereotype.Component;
@Component //用来让spring完成ioc {"person"=new Person()}
public class Student {
    public void study(){
        System.out.println("Student.study()");
    }
}

package cn.tedu.spring;
import org.springframework.stereotype.Component;

@Component //用来让spring完成ioc {"person"=new Person()}
public class Person {
    public void show(){
        System.out.println("Person.show()");
    }
}

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

   <!--包扫描:扫描 指定包 以及 子包里的所有资源,找到有IOC注解的类就进行new
        IOC的注解包括: @Component   @Service  @Controller
        base-package 用来指定包路径,范围越小越好,性能高
    -->
    <context:component-scan base-package="cn.tedu"></context:component-scan>

</beans>

3.3测试

package cn.tedu.spring;

import org.junit.jupiter.api.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test1 {
    //单元测试方法
    @Test
    public void ioc(){
        //1,读取配置文件---参数是配置文件的路径
        ClassPathXmlApplicationContext spring =
                new ClassPathXmlApplicationContext(
                        "spring.xml");
        //2,getBean()---参数是类名,首字母小写
        Object o = spring.getBean("person");
        System.out.println(o);//cn.tedu.spring.Person@7e5afaa6
        Object o1 = spring.getBean("student");
        System.out.println(o1);

        Object o2 = spring.getBean("animal");
        System.out.println(o2);
    }
}


三.模拟 DI依赖注入

1.概述

维护了两个对象间的关系,方便在使用A的同时可以看到关联的B的数据

2.测试


创建Emp类

package cn.tedu.di;

public class Emp {
    String name = "吴谦";
    //绑定了两个类的关系--依赖
    private Dept d;
    //get set
    public Dept getD() {
        return d;
    }
    public void setD(Dept d) {
        this.d = d;
    }
    @Override
    public String toString() {
        return "Emp{" +
                "name='" + name + '\'' +
                ", d=" + d +
                '}';
    }
}

创建Dept 类

package cn.tedu.di;
public class Dept {
    String name = "java软件开发一部";
    @Override
    public String toString() {
        return "Dept{" +
                "name='" + name + '\'' +
                '}';
    }
}

创建测试类

package cn.tedu.di;
import org.junit.Test;
public class TestDi {
    @Test
    public void di(){
        //1,创建对象
        Emp e = new Emp();
        Dept d = new Dept();
        //Emp{name='吴谦', d=null}
        System.out.println(e);

        //2,di维护了两个对象间的关系-set()
        e.setD(d);
//Emp{name='吴谦', d=Dept{name='java软件开发一部'}}
        System.out.println(e);
    }
}

四.Spring提供的DI依赖注入

1.创建UserInfo 类

package cn.tedu.di2;

import org.springframework.stereotype.Component;
@Component//ioc -- {"userInfo"=new UserInfo()}
public class UserInfo {
    String name="jack";
    @Override
    public String toString() {
        return "UserInfo{" +
                "name='" + name + '\'' +
                '}';
    }
}

2.创建Order 类

package cn.tedu.di2;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component//ioc--{"order"=new Order()}
public class Order {
    String name = "iphone13";
    //get set
    @Autowired //di
    private UserInfo ui;

    @Override
    public String toString() {

        return "Order{" +
                "name='" + name + '\'' +
                ", ui=" + ui +
                '}';
    }
}

3.测试类

package cn.tedu.di2;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestDI {
    @Test
    public void di(){
        //1,读取配置文件
        ClassPathXmlApplicationContext spring =
                new ClassPathXmlApplicationContext(
                        "spring.xml");
        //2,getBean()--DI:获取A的同时也获取到B的信息
        Object o = spring.getBean("order");
//Order{name='iphone13',ui=UserInfo{name='jack'}}
        System.out.println(o);
    }
}

4.总结

IOC: 控制翻转,Spring框架创建对象.
使用步骤: 1, 在类上使用注解@Component @Service @Controller 2, 配置包扫描
DI: 依赖注入,把两个对象之间的关系依赖.
使用步骤: 1, 先完成IOC 2, 用注解@Autowired

扩展:SpringMVC源码里的核心方法

五.Spring AOP

1.概述

是面向切面编程,扩展了面向对象的不足.
切面Aspect: 其实就是一个类, 要用@Aspect注解
通知Advice: 就是类里的方法, 分为:前置通知 后置通知 环绕通知 返回后通知 异常通知
切点Pointcut: 就是定义了方法的触发时间,切入点表达式

2.使用步骤

加入jar包

<dependencies>
     <!--添加aop依赖包-->
     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-aop</artifactId>
     </dependency>
 </dependencies>

3.创建切面

package cn.tedu.service;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Component
@Aspect //切面:通知 + 切点
public class Timer {
    //2,切点表达式,通过execution属性声明
    //* cn.tedu.service.*.*(..) 方法返回值 包名.类名.方法名(参数列表)
    @Pointcut("execution(* cn.tedu.controller.*.*(..))")
    public void pointcut(){}
    //1,通知:分类: 前置通知  后置通知  环绕通知  返回后通知  异常通知
    //前置通知:在调用你的目标方法前,就要执行
    @Before("pointcut()")
    public void beforeMethod(JoinPoint joinPoint){
        System.out.println("我是前置通知~~~~~");
        //常见的使用场景:权限   缓存  开启事务  日志
    }
    //后置通知:在调用你的目标方法后,就要执行
    @After("pointcut()")
    public void afterMethod(JoinPoint joinPoint){
        System.out.println("我是后置通知~~~~~");
        //常见的使用场景:结束事务  日志  释放资源
    }
    //环绕通知:在调用你的目标方法之前和之后,都要执行
    @Around("pointcut()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();//计时开始
        Object o = joinPoint.proceed();//继续执行你的目标方法
        long end = System.currentTimeMillis();//计时结束

        System.out.println("aop统计的总耗时是:"+(end-start));
        return o;//放回给调用者,继续执行方法
    }
}

4.测试

创建启动类

package cn.tedu;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class RunApp {
    public static void main(String[] args) {
        SpringApplication.run(RunApp.class);
    }
}

创建HelloController 类

package cn.tedu.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController//Controller + ResponseBody
@RequestMapping("hello")
public class HelloController {
    @RequestMapping("hello")
    public String hello(){
        for (int i = 0; i <100 ; i++) {
            System.out.println("=");
        }
        return "恭喜您,访问成功~";
    }
    //统计hello()方法的性能
    //缺点:目前只能统计hello()方法的性能,想要统计其他方法的性能--AOP
    //AOP思想好处:让程序员更加关注业务本身,把通用的代码形成切面
    @RequestMapping("hello2")
    public String hello2(){
        long start = System.currentTimeMillis();
        hello();
        long end = System.currentTimeMillis();
        return "访问时间:"+(end-start) ;
    }

}


测试

访问HelloController 里的每个方法,都会执行对应的通知

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值