栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring5

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring5

Spring5 01、Spring简介

Spring的历史

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

2002年,Rod Jahnson首次推出了Spring框架雏形interface21框架

Rod Johnson是悉尼大学的博士,然而他的专业不是计算机,而是音乐学

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

官网:Spring | Home

Spring的优点

Spring是一个开源免费的框架,容器(免费且开源是最重要的)

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

控制反转IOC(Inversion of Control),面向切面AOP(Aspect Oriented Programming)

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

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

02、控制反转(IOC)

IOC是Spring的核心内容

IOC是一种设计思想,DI(依赖注入)是实现IOC的一种方法

在没有IOC的程序中 , 我们使用面向对象编程 , 对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,从而实现程序的解耦。个人认为所谓控制反转就是:获得依赖对象的方式反转了。(这里的第三方在Spring中就是IOC容器,所有需要的对象都交给IOC容器来创建,管理和装配,需要的时候只需get一下就可以了)

实现IOC可以使用XML配置,也可以使用注解,或者使用纯Java代码实现(新版本Spring官方推荐使用)。

先导入一下jar包(maven会导入与其相关的jar包,例如core,aop,beans等)


    org.springframework
    spring-webmvc
    5.3.14

03、依赖注入(DI)

依赖 : 创建Bean对象所依赖资源 .注入 : 由容器来注入Bean对象所依赖的资源 Set注入

被注入的属性一定要有set方法

创建Student对象(只展示了属性部分)

public class Student {
    private String name;
    private Address address;
    private String[] books;
    private List games;
    private Set hobbies;
    private Map card;
    private String wife;
    private Properties info;
}

创建Address对象(只展示了属性部分)

public class Address {
    private String city;
}
    常量注入

    




    

    Bean注入

    数组注入

    
        西游记
        三国演义
        水浒传
        红楼梦
    

    List注入

    
        王者
        和平精英
    

    Set注入

    
        打游戏
        听歌
        不学习
    

    Map注入

    
        
        
    

    Null注入(null和字符串长度为0不是一回事啊)

    

    Properties注入

    
        root
        123.com
    

构造器注入

被注入的属性一定要有构造方法

创建People对象(只展示了属性部分)

public class People {
    private String name;
    private Address address;
}
    构造器参数下标注入

    
    

    构造器参数名称注入(推荐使用名称注入)

    
    

    构造器参数类型注入(尽量就不要用这个了)

    
    

p命名和c命名注入

p(properties),c(construction)命名空间可以实现直接在一行进行注入

一定要加加入头文件约束

xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"




Bean的作用域


默认是singleton,也就是单例模式。

singleton:从容器中get到的相同名字的Bean对象是同一个对象

prototype:从容器中get到的相同名字的Bean对象不是同一个对象

在xml中同一个类可以写多个bean(名字不能相同),不同的bean,不是一个对象

04、自动装配 xml中配置

创建猫,狗,人类(只展示了属性部分)

被注入的属性一定要有set方法

public class Cat {
    public void shout(){
        System.out.println("喵喵喵~~");
    }
}

public class Dog {
    public void shout(){
        System.out.println("汪汪汪~~");
    }
}

public class People {
    private String name;
    private Cat cat;
    private Dog dog;
}





    




    

byName是根据set方法后的名称在容器中寻找是否有对应id的对象(命名规范很重要)

byType是根据所需类型在容器中寻找,如果有多个类型相同的,就寄了

使用注解

加上头文件约束,并开启注解支持

使用注解来实现自动装配可以没有set方法

xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
public class People {
    private String name;

    //Autowired先byType,如果有多个相同Type,再byName
    //required设置为false,表示目标对象可以不在IOC容器中,也就是可以为空,@Nullable注解也可以允许为空
    @Autowired(required = false)
    private Dog dog;

    //Qualifier直接找名字,必须和Autowired搭配使用
    @Autowired
    @Qualifier(value = "cat")
    private Cat cat;
}
05、使用注解开发

加上头文件约束,并开启注解支持,扫描指定包下的类,使得类中的注解生效

xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">




@Component("people")//相当于    ,若不写参数,则默认是people
@Scope("singleton") //相当于   定义bean的作用域配置
public class People {

    @Value("司南杓")//对属性进行注入,此时不需要set方法,如有set方法,也可以写在set方法上
    private String name;
}

@Component三个衍生注解

@Controller:web层@Service:service层@Repository:dao层

这些衍生注解仅仅是为了更好的进行分层,功能都是一样的

基于Java类进行配置

编写Dog类,MyConfig配置类

public class Dog {
    public void shout(){
        System.out.println("汪汪汪");
    }
}

@Configuration  //代表这是一个配置类
@import(MyConfig2.class)    //导入其他的配置类,就像xml配置里的import
public class MyConfig {
    @Bean   //方法名就是bean对象的id
    public Dog dog(){
        return new Dog();
    }
}
06、静态/动态代理模式

为什么要学习代理模式,因为AOP的底层机制就是动态代理!

静态代理

静态代理角色分析

抽象角色 : 一般使用接口或者抽象类来实现真实角色 : 被代理的角色代理角色 : 代理真实角色 ,代理真实角色后 , 一般会做一些附属的操作 .客户 : 使用代理角色来进行一些操作 .

RentHouse就是租房的抽象角色

public interface RentHouse {
    void rent();
}

Owner房东就是真实角色

public class Owner implements RentHouse{
    @Override
    public void rent() {
        System.out.println("房东出租房子");
    }
}

MyProxy中介公司就是代理角色

public class MyProxy implements RentHouse{
    private RentHouse rentHouse;
    public void setRentHouse(RentHouse rentHouse) {
        this.rentHouse = rentHouse;
    }

    @Override
    public void rent() {
        seeHouse();
        rentHouse.rent();
        contract();
    }
    private void seeHouse(){
        System.out.println("看房子");
    }

    private void contract(){
        System.out.println("签合同");
    }
}

Client就是客户

public class Client {
    @Test
    public void test(){
        MyProxy myProxy = new MyProxy();
        myProxy.setRentHouse(new Owner());
        myProxy.rent();
    }
}

代理模式就是用户这边不用操心别的事情,只需要找中介就可以,简化用户操作,所有的活都让中介来做被代理角色需要添加新的东西,不需要修改被代理角色内容,只需在中介处添加新功能即可核心就是,不改变原有代码,再加一层,来实现拓展业务缺点就是每一次代理,代码量就会扩大一倍 动态代理

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

动态代理的代理类是动态生成的 . 静态代理的代理类是我们提前写好的死代码

public class ProxyInvocationHandler implements InvocationHandler {
    //被代理的接口
    private Object target;

    public void setTarget(Object target) {
        this.target = target;
    }

    //生成得到代理类
    public Object getTargetProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
    }

    
    // proxy : 代理类 method : 代理类的调用处理程序的方法对象.
    //处理代理实例,返回结果
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        seeHouse();
        contract();
        Object result = method.invoke(target, args);
        fee();
        return result;
    }

    private void fee(){
        System.out.println("收取房租费用");
    }
    private void seeHouse(){
        System.out.println("看房");
    }
    private void contract(){
        System.out.println("签合同");
    }
}
public class User {
    public static void main(String[] args) {
        ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler();
        proxyInvocationHandler.setTarget(new Owner());
        RentHouse targetProxy = (RentHouse) proxyInvocationHandler.getTargetProxy();
        targetProxy.rent();
    }
}
07、面向切面(AOP)

什么是AOP

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

一句话总结就是: AOP在不改变原有代码的情况下 , 去增加新的功能

横切关注点:跨越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点。如日志 , 安全 , 缓存 , 事务等等 …

切面(ASPECT):横切关注点 被模块化 的特殊对象。即,它是一个类。

通知(Advice):切面必须要完成的工作。即,它是类中的一个方法。

目标(Target):被通知对象。

代理(Proxy):向目标对象应用通知之后创建的对象。

切入点(PointCut):切面通知 执行的 “地点”的定义。

连接点(JointPoint):与切入点匹配的执行点。

使用Spring API原生接口实现

先导入需要的jar包


    org.aspectj
    aspectjweaver
    1.9.8

导入约束

xmlns:aop="http://www.springframework.org/schema/aop"
http://www.springframework.org/schema/aop 
https://www.springframework.org/schema/aop/spring-aop.xsd">

BeforeLog类

@Component
public class BeforeLog implements MethodBeforeAdvice {

    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println(target.getClass().getName()+"的"+method.getName()+"方法执行之前");
    }
}

AfterLog类

@Component
public class AfterLog implements AfterReturningAdvice {
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println(target.getClass().getName()+"的"+method.getName()+"方法执行完成,返回值是"+returnValue);
    }
}

UserService接口

public interface UserService {
    void add();
    void del();
}

UserServiceImpl类

@Component
public class UserServiceImpl implements UserService{
    @Override
    public void add() {
        System.out.println("增加操作");
    }

    @Override
    public void del() {
        System.out.println("删除操作");
    }
}

xml配置


    
    
    
    
    
    

测试类

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //AOP代理的是接口,所以类型是接口类型
        UserService userServiceImpl = context.getBean("userServiceImpl", UserService.class);
        userServiceImpl.add();
    }
}

测试结果

自定义实现AOP(自定义切面)

DiyLog类

public class DiyLog {
    public void beforeExe(){
        System.out.println("操作执行前");
    }

    public void afterExe(){
        System.out.println("操作执行后");
    }
}

xml配置


    
    
        
        
        
        
        
    

测试结果

使用注解实现AOP

开启AOP注解支持


DiyLog类

@Component
@Aspect //标注这个类是一个切面
public class DiyLog {

    @Before("execution(* com.sinan.service.UserServiceImpl.*(..))")
    public void beforeExe(){
        System.out.println("操作执行前");
    }

    @After("execution(* com.sinan.service.UserServiceImpl.*(..))")
    public void afterExe(){
        System.out.println("操作执行后");
    }

    //在环绕增强中,可以给定一个参数,代表我们要获取处理切入的点
    @Around("execution(* com.sinan.service.UserServiceImpl.*(..))")
    public void around(ProceedingJoinPoint pj) throws Throwable {
        System.out.println("环绕前");

        Object proceed = pj.proceed();

        System.out.println("环绕后");
    }

    
}

测试结果

08、整合MyBatis

首先导入一堆包和添加头文件约束


	
        org.mybatis
        mybatis
        3.5.7
    
    
        mysql
        mysql-connector-java
        8.0.25
    
    
        org.mybatis
        mybatis-spring
        2.0.7
    
    
        org.aspectj
        aspectjweaver
        1.9.8
    
    
        org.springframework
        spring-jdbc
        5.3.13
    
    
        org.projectlombok
        lombok
        1.18.20
    



    
        
            src/main/java
            
                ***.xml
            
        
        
            src/main/resources
            
                **/*.*
            
        
    

User类

@Data
@AllArgsConstructor
@NoArgsConstructor
@Component
public class User {
    private int id;
    private String name;
    private int age;
    private String sex;
}

UserMapper接口

public interface UserMapper {
    void selectUser();
    void delUser(int id);
    void insertUser(User user);
}

UserMapper.xml