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

2021-10-10

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

2021-10-10

Spring框架入门

Spring框架 Spring入门(控制反转)

核心:IOC(控制反转)和AOP(面向切面编程)

程序设计的目标:

高内聚低耦合:一个模块内的各个元素之间要高度紧密,但是各个模块之间的相互依存度却不要那么紧密。

所以需要降低模块之间的耦合关系

  • 使用IOC解决问题(步骤)

    1. 导入Spring依赖

      
          org.springframework
          spring-context
          5.0.5.RELEASE
      
    2. 创建xml配置文件

      
      
          
          
          
          
              
              
          
      
    3. 测试代码

      // 创建Spring容器
      ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
      ​
      // 从容器中获取对象(三种方式)
      AccountController  accountController = (AccountController) context.getBean("accountController");
      //调用save方法
      accountController.save(account);
  • 总结

    • 解耦的关键是:将Controller对servcie实现类的控制权(实例化)交给配置文件,通过创建容器实现对象的创建

IOC配置文件详解 容器结构
  • ApplicationContext接口的实现类

    • ClassPathXMLApplicationContext 读取类路径下的配置文件(xml)

    • FileSystemXmlApplicationContext: 读取 绝对路径下的配置文件(一般不用)

    • AnnotationConfigApplicationContext: 纯注解模式使用创建容器

Bean标签详解
  • xml配置文件

  • 创建和获取对象

1. 根据id获取对象,返回的是Object对象,需要进行强制转换
   context.getBean("account");
    
2. 根据class获取对象,返回Account类型对象,不需要进行强制转换
    context.getBean(Account.class);
    
3. 根据id 和 class获取对象,返回Account类型对象,不需要进行强制转换(需要满足两个条件)
    context.getBean("account", Account.class);
​
​
@Test
public void getBean(){
    //创建IOC容器
    ApplicationContext context = new ClassPathXmlApplicationContext("spring02.xml");
    //获取对象:根据id获取对象,返回的是Object对象,需要进行强制转换
    Object obj = context.getBean("account");
    Account account1 = (Account) obj;
    System.out.println(account1);
    //获取对象:根据class获取对象,返回Account类型对象,不需要进行强制转换
    Account account2  = context.getBean(Account.class);
    System.out.println(account2);
    //获取对象:根据id 和 class 获取对象,返回Account类型对象,不需要进行强制转换
    Account account3  = context.getBean("account", Account.class);
    System.out.println(account3);
}
对象的作用范围


​
    
    
    

        
scope 属性可设置值
  singleton[重点]: 单例模式,全局唯一,只会实例化一次, 默认为单例模式
  prototype[重点]: 原型模式(多例模式),每次getBean都会实例化一个新的对象
  request:请求范围
  session:http Session范围
  application:servletContext范围
  websocket: websocket访问(网络套接字)         
对象的生命周期
init():初始化对象
destroy():销毁对象


    
    
            
            
            
            
            

                
1. 单例模式
    创建容器时创建对象,容器销毁时 对象销毁
2. 原型模式
    创建容器时,对象不会创建,在第一次获取对象时创建对象
    对象不会随着容器的销毁而销毁
3. init-method:指定初始化时执行的方法
4. destory-method:指定销毁时执行的方法,只对scope为singleton的bean有效
依赖注入(DI)
  • 依赖注入是控制反转的一种表现方式。

  • 依赖查找也是控制反转的一种表现方式

set方法注入
  • 配置文件xml



​
    
        
        
        
    
  • 测试

@Test
public void test(){
    //创建spring容器
    ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
    Account account = context.getBean("account", Account.class);
    System.out.println(account);
}
  • 总结

1. property标签可以通过set方法给属性赋值
     name 指定属性名称
     value  给属性赋的值
2. 本质
     虽然name指定的属性名,其实本质是调用的是对象的set方法, 如set方法不存在,配置文件会有编译错误
     注意:set方法一定要符合格式
构造方法注入
  • Account类

public class Account {
    public Account(Integer id, String name, double money) {
        System.out.println("执行构造方法 -- 三个参数");
        this.id = id;
        this.name = name;
        this.money = money;
    }
​
    public Account(String name, double money) {
        System.out.println("执行构造方法 -- 两个参数");
        this.name = name;
        this.money = money;
    }
  
    // 其他的属性和方法不变
}
  • xml配置文件



​
    
        
        
        
    
​
    
        
        
    
​
    
        
        
    
​
    
        
        
        
    
  • 测试

@Test
public void test(){
    //创建spring容器
    ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
    Account account1 = context.getBean("account1", Account.class);
    Account account2 = context.getBean("account2", Account.class);
    Account account3 = context.getBean("account3", Account.class);
    Account account4 = context.getBean("account4", Account.class);
    System.out.println(account1);
    System.out.println(account2);
    System.out.println(account3);
    System.out.println(account4);
}
  • 总结

通过构造方法给属性赋值-----必须要掌握的
    
1. 支持按照参数名注入
2. 支持按照类型注入
3. 支持按照索引注入
4. 支持按照顺序注入
注入引用数据类型
  • xml配置文件



    
  • 测试

@Test
public void test(){
    //创建spring容器
    ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
    Account account5 = context.getBean("account5", Account.class);
    System.out.println(account5);
}
  • 总结

注入引用数据类型:需要先用bean标签创建对象, 再使用ref引用对象
注入复杂数据类型
  • Account类

private String[] myStrs;//数组
private List myList;//list集合
private Set mySet;//set集合
private Map myMap;//map
private Properties myProps;//Properties
//此处省略set和get方法
//修改toString方法
  • xml配置文件


    
        
            mybatis
            spring
            springMVC
        
    
    
        
            表现层
            业务层
            持久层
        
    
    
        
            模型层
            视图层
            控制层
        
    
    
        
            
            
            
        
    
    
        
            Model
            View
            Controller
        
    
  • 测试

@Test
public void test(){
    //创建spring容器
    ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
    Account account7 = context.getBean("account7", Account.class);
    System.out.println(account7);
}
  • 总结

1. 注入set,list,array 属性,分别使用 set, list , array 标签;
        因为三种标签都是单列数据,可以交换使用,建议按照对应标签配置
2. 注入map,properties 属性,分别使用 map,props 标签    
        因为都是键值对数据,可以交换使用,建议按照对应标签配置
加载Properties
  • db.properrties文件

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mydb
jdbc.username=root
jdbc.password=root
  • xml文件



​
​
    
    
        
        
        
            
        
        
    
​
    
    
        
            
                123
                321
            
        
        
            
                鱿鱼游戏
                动物世界
                长津湖
            
        
        
            
                王者荣耀
                英雄联盟
                原神
            
        
        
            
                
                
                
            
        
        
            
                值1
                值2
            
        
    
​
    
    
    
    
        
        
        
        
    
  • 测试

package com.itheima.test;
​
import com.itheima.pojo.Account;
import com.itheima.pojo.DataSource;
import com.itheima.pojo.FuZa;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
​
public class AccountTest {
    @Test
    public void test01(){
        //获取spring容器
        ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
        //从这里获取 Account对象
        Account account = context.getBean("account", Account.class);
​
        System.out.println(account);
    }
​
    @Test
    public void test02(){
        //获取spring容器
        ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
        //从这里获取 Account对象
        FuZa fuza = context.getBean("fuza", FuZa.class);
​
        System.out.println(fuza);
    }
​
​
    @Test
    public void test03(){
        //获取spring容器
        ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
        //从这里获取 Account对象
        DataSource fuza = context.getBean("dataSource", DataSource.class);
​
        System.out.println(fuza);
    }
}
​
  • 总结

1.  需要新增名称空间,具体看下图
2. 通过 标签加载属性文件
        location属性指定 属性文件的位置
        属性文件中如果有中文,需要指定加载的编码格式
3. 如果要加载多个属性文件,location属性中提供一个或多个位置作为逗号分隔的列表。
4. 加载类路径下的资源,需要添加字符串前缀:classpath: 
注解
启动注解扫描,加载类中配置的注解项
    
    例如:
        
           
Bean的定义(@Component)
名称:@Component       @Controller @Service @Repository
类型:类注解
作用:设置该类为spring管理的bean
说明: @Controller @Service @Repository是@component的衍生注解,功能和@component相同
        @Controller   用于Controller层的类 :表现层
-       @Service        用于Service层的类: 业务层
-       @Repository  用于Dao层的类: 持久层(一般不写) 
相关属性:value
定义bean的访问id,默认的id名称为“简单类名”,首字母小写
​
Bean注入(@Autowired)
名称:@Autowired, @Qualifier, @Resource
类型:属性注解,方法注解
作用:自动装配,设置属性的对象或者对方法进行传参            
说明:
    - @Autowired  按类型装配,一般生产中都使用它**,由spring提供的,只有引入spring包才可使用。
    - @Qualifier     可以指定bean的id,一般用于有多个同一类型bean的场景(必须配合@Autowired使用)。
    - @Resource     相当于同时指定了@Autowired和@Qualifier,由Jdk提供的,了解即可。       注解的方式注入bean,不需要setter方法  
相关属性:
    - @Autowired
    - **required:定义该属性是否允许为null,默认true**
    - @Qualifier
    - value:需要注入的bean的id
    - @Resource
    - name:需要注入的bean的id   
            
名称:@Primary            
作用:设置bean的优先级           
   @Autowired默认按类型装配,当出现相同类型的bean,使用@Primary提高按类型自动装配的优先级,程序就不会报错了。
​
名称:Scope类注解
作用:设置该类作为bean对应的scope属性(相当于标签的scope属性)           
            
名称:@Configuration
类型:类注解
作用:等同于xml配置文件,当前注解声明的类中,编写配置信息,所以把使用@Configuration的类称为配置类            
            
名称:@ComponentScan
类型:类注解            
作用:扫描注解(相当于xml配置文件中的context:compoent-scan标签)            
注意:扫描的包路径不写,扫描的是当前包及其子包
    
    
名称:@bean
类型:方法注解
作用:将方法的返回值存储到Spring IOC容器中(相当于xml配置文件中的)
    
    
名称:@Value    
类型:属性注解,方法注解    
作用:注入非引用类型,设置属性的值或对方法进行传参 ,用在指定成员变量上,用于获取配置文件属性   
说明:@Vlaue一般用于读取properties文件中的属性值
    注解的方式注入非引用数据类型,不需要setter方法
相关属性:value(默认)定义对应的属性值或参数值    
    
名称:@import注解
类型:类注解    
作用:导入其他配置类(对象),用在主要配置类上,用来引入其他配置类    
例:@import(RedisConfig.class)
相当于xml中的标签    
注意:也可以直接将配置类放在注解扫描器可以扫描到的位置,就不需要使用@import注解导入
    
名称:@PropertySource    
类型:类注解(标记在类上)
@PropertySource("jdbc.properties")    
作用:用在配置类上,用于解析配置文件,引入外部属性文件(jdbc.properties)
相当于xml配置文件中的context:property-placeholder标签
  
     
名称:@RunWith(SpringJUnit4ClassRunner.class)
作用:spring的单元测试运行器替换原有运行器
​
名称:@ContextConfiguration(classes = SpringConfig.class)
作用:指定配置类或者配置文件所在位置
     
名称:@EnableAspectJAutoProxy 
类型:配置类注解(配置类定义上方)     
作用:开启注解格式的AOP功能    
    
名称:@Aspect    
类型:类注解(切面类定义上方)    
作用:设置当前类为AOP切面类
     
名称:@Pointcut     
类型:方法注解(切入点方法定义上方)     
作用:设置切入点方法
属性:value(默认):切入点表达式
     
名称:@Before     
类型:方法注解(通知方法定义上方)     
作用:设置当前通知方法与切入点之间的绑定关系,当前通知方法在原始切入点方法前运行     
属性:value(默认):切入点方法名,格式为类名.方法名()     
例如:
    @Before("AOPAdvice.pt()")
public void beforeSave(){
    System.out.println("save功能执行前系统时间:" + System.currentTimeMillis());
}
​
名称:@After
类型:方法注解(通知方法定义上方)
作用:设置当前通知方法与切入点之间的绑定关系,当前通知方法在原始切入点方法后运行
属性:value(默认):切入点方法名,格式为类名.方法名()
​
名称:@Around   
类型:方法注解(通知方法定义上方)
作用:设置当前通知方法与切入点之间的绑定关系,当前通知方法在原始切入点方法前后运行
属性:value(默认):切入点方法名,格式为类名.方法名() 
    
名称:@AfterReturning    
类型:方法注解(通知方法定义上方)    
作用:设置当前通知方法与切入点之间绑定关系,当前通知方法在原始切入点方法正常执行完毕后执行   属性:value(默认):切入点方法名,格式为类名.方法名()  
    
名称:@AfterThrowing
类型:方法注解(通知方法定义上方)   
作用:设置当前通知方法与切入点之间绑定关系,当前通知方法在原始切入点方法运行抛出异常后执行   属性:value(默认):切入点方法名,格式为类名.方法名() 

Spring纯注解开发
两个注解一个类:
注解一: @Configuration  表示是一个配置类,用来替代了xml配置文件,代表当前是配置入口类
注解二: @ComponentScan("com.itheima") 表示要扫描那些包,扫描指定包下注解,这些包中的类如果有@omponet就代表该类对象交给Spring管理
类:AnnotationConfigApplicationContext 用来解析配置类的,产生一个容器对象

步骤:
1.设置spring管理的bean
2.设置自动装配,设置属性的对象或者对方法进传参
3.配置注解@Configuration 表名此类是一个配置类
4.配置注解@ComponentScan("包名路径") 配置包扫描机制
    
总结:
      @Service  @Controller 用在指定的类上,用来替代bean标签。

  @Autowired 用在需要注入的属性上,完成自动属性注入。

  @Configuration 用在配置类上,用来替代spring核心配置xml文件。

  @ComponentScan("com.itheima")   用来进行注解包的扫描 

  new AnnotationConfigApplicationContext(SpringConfig.class) 用于创建注解spring容器。
Spring整合Druid
步骤:
1.导入druid依赖坐标
2.使用注解的形式完成外部属性文件的引入(jdbc.properties),使用@PropertySource
3.将引入的文件注入到成员变量上使用@Value
4.将获取数据库连接池返回值,当做bean交给Spring管理,使用@Bean
5.测试代码,创建解析注解的对象

 
            com.alibaba
            druid
            1.1.21



package com.itheima.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;


@PropertySource("jdbc.properties")
public class JdbcConfig {

    @Value("${jdbc.driver}")
    private String driverClassName;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.user}")
    private String username;
    @Value("${jdbc.password}")
    private String password;


    @Bean
    public DruidDataSource createDataSource(){
        //创建数据源对象并返回
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setDriverClassName(driverClassName);
        druidDataSource.setUrl(url);
        druidDataSource.setUsername(username);
        druidDataSource.setPassword(password);

        return druidDataSource;
    }
}


@Configuration
@ComponentScan("com.itheima")
@import(JdbcConfig.class)
public class SpringConfig {
}


public class Test02 {

    
    @Test
    public void test02(){
        // 创建 解析注解的容器类
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);

        DruidDataSource dataSource = context.getBean(DruidDataSource.class);

        System.out.println(dataSource);
    }
}
  • 总结

  @PropertySource 用在配置类上,用于解析配置文件。

  @Value 用在指定成员变量上,用于获取配置文件属性。

 @import(JdbcConfig.class)   用在主要配置类上,用来引入其他配置类。
Spring整合JUnit

Spring对junit的支持的好处

  • 好处一:配置完之后,不需要我们手动创建Spring的容器,容器由Junit帮我们自动初始化

  • 好处二:可以在junit测试类中使用@AutoWired等方式注入对象,直接对其进行调用测试

整合实现步骤:(将练习1中的测试改为整合形式测试)

  1. 导入依赖坐标

  2. 在测试类上加入@RunWith注解,指定Spring的运行器

  3. 配置初始化Spring容器的配置文件(配置类)

  4. 删除原有的初始化代码ClassPathXmlApplicationContext

  5. 注入Account,执行测试代码

实现过程:

1.导入依赖坐标


    org.springframework
    spring-test
    5.0.5.RELEASE

2.在测试类上加入@RunWith注解,指定Spring的运行器

@RunWith(SpringJUnit4ClassRunner.class)
public class Test01 {
    //....省略

3.配置初始化Spring容器的配置文件(配置类)

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class Test01 {
     //....省略

4.注入Account,执行测试代码

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class Test03 {

    @Autowired
    AccountController accountController;

    @Test
    public void test01(){

        accountController.save(new Account(1,"潘子",111));
    }
}
AOP(面向切面编程) AOP介绍

AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过运行期动态实现程序功能的统一维护的一种技术。面向切面编程,通过运行期动态实现程序功能的统一维护的一种技术

AOP弥补了OOP的不足,基于OOP基础上进行横向开发;OOP程序开发以类为主题模型,一切围绕对象进行,通过构建模型来完成任务;AOP程序的开发主要关注OOP开发中的共性功能,一切围绕共性功能进行。

AOP通过采取横向抽取机制,已经完全取代了传统纵向继承体系重复性代码的编写方式

AOP的底层封装了动态代理,我们可以理解为AOP是动态代理的一种简单写法进行功能的增强!。

结论:AOP就是能动态的批量的为一些对象增强功能,这些功能最终是通过代理对象来封装。代理对象功能=代理增强功能+原对象原功能。

AOP以xml配置文件的形式开发的步骤
  • 编写AOPAdvice类

package com.itheima.aop;


public class AopAdvice {
     // 通知方法  前置通知  方法执行前执行的
    public void before(){
        System.out.println("当前方法执行前初始时间毫秒值是:"+System.currentTimeMillis());
    }
    // 通知方法   后置通知  方法执行后执行的
    public void after(){
        System.out.println("当前方法执行后初始时间毫秒值是:"+System.currentTimeMillis());
    }
}
  • 特定的类交给spring管理




    

    
    

  • 编辑xml文件

 
    
        
        
        
            
            
            


            
            
            

        
    
AOP以注解的形式
  • 导入AOP开发所使用的坐标


    org.springframework
    spring-aop
    5.0.5.RELEASE


    org.aspectj
    aspectjweaver
    1.9.4
  • 创建一个新的类,将共性功能提取出来制作成独立的方法

package com.itheima.service.impl;

import com.itheima.domain.User;
import com.itheima.service.UserService;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserServiceImpl implements UserService {
    @Override
    public void save(User user) {
//        System.out.println("当前方法执行前初始时间毫秒值是:"+System.currentTimeMillis());


            System.out.println("保存了用户数据~");
//            System.out.println(1/0);


//        System.out.println("当前方法执行后初始时间毫秒值是:"+System.currentTimeMillis());
    }

    @Override
    public void update(User user) {
//        System.out.println("当前方法执行前初始时间毫秒值是:"+System.currentTimeMillis());
        System.out.println("更新了用户数据~");
//        System.out.println("当前方法执行后初始时间毫秒值是:"+System.currentTimeMillis());
    }

    @Override
    public void delete(String id) {
        System.out.println("删除了用户数据~");
    }

    @Override
    public List findAll() {
        System.out.println("查询了用户数据~");
        return null;
    }
}
  • 抽取制作新的类,在新的类中定义一个方法,无参无返回值,方法体为空。上面添加一个注解@Pointcut

public class AOPAdvice {
//    设置连接点 上有切入点
    @Pointcut("execution( * com.itheima.service.impl.*.*(..))")
    public void pc(){}

}
  • 绑定原始操作与被抽取的功能之间的关系

public class AOPAdvice {
    @Pointcut("execution(void com.itheima.service.impl.UserServiceImpl.save(..))")
    private void pt() {
    }
    @Before("AOPAdvice.pt()")
    public void before(){
        System.out.println("功能执行前系统时间:" + System.currentTimeMillis());
    }
     @Pointcut("execution(void com.itheima.service.impl.UserServiceImpl.save())")
    private void pt() {
    }
    @Before("pt()")
    public void before(){
        System.out.println("功能执行前系统时间:" + System.currentTimeMillis());
    }
    @After("pt()")
    public void afterSave(){
        System.out.println("功能执行后系统时间:" + System.currentTimeMillis());
    }
}
  • 声明切面类

@Component
@Aspect
public class AOPAdvice {
}
  • 在Spring配置类上声明开启AOP功能

@Configuration
@ComponentScan("com.itheima")
// 开启注解格式AOP功能
@EnableAspectJAutoProxy
public class SpringConfig {
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/309672.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号