Spring详细笔记

Spring详细笔记,第1张

Spring详细笔记

文章目录
    • 1.Spring
      • 1.1 简介
      • 1.2 优点
    • 2. IOC理论推导
      • 2.1.代码实现
      • 2.2 IOC本质
    • 3.Spring第一个程序
      • 3.1 代码
      • 3.2 IOC创建对象的方式
    • 4. Spring配置
      • 4.1 别名
      • 4.2 Bean的配置
      • 4.3 import
    • 5. 依赖注入
      • 5.1 构造器注入
      • 5.2 Set方式注入
      • 5.3 扩展方式注入
      • 5.4 Bean的作用域
    • 6. Bean自动装配
      • 6.1 测试
      • 6.2 注解自动装配
    • 7. 使用注解开发
    • 8.使用java的方式配置Spring
    • 9. 代理模式
      • 1. 静态代理:
      • 2.动态代理
    • 10. AOP
      • 1.AOP概念
      • 2.AOP在Spring中的作用
      • 3.使用Spring实现AOP
    • 11.整合Mybatis
      • 方式一
      • 方式二
    • 12.声明式事务
      • 1.事务概念
      • 2. 事务管理
      • 3. 为什么需要配置事务:

1.Spring 1.1 简介
  • 官网地址:Spring
  • Spring是一款以IOC(控制反转)和AOP(面向切面)为核心, 简化企业应用复杂性开发的一款轻量级框架。
  • 使用:导入依赖

            org.springframework
            spring-webmvc
            5.3.3

1.2 优点
  • Spring是一个开源的免费框架
  • Spring是一个轻量级的,非入侵式框架
  • 控制反转和面向切面编程
  • 支持事务管理,对框架整合的支持
2. IOC理论推导 2.1.代码实现
  1. UserDao接口
public interface UserDao {
    void food();
}
  1. UserDaoImpl实现类
public class UserDaoImpl implements UserDao {
    public void food() {
        System.out.println("苹果");
    }
}

  1. userService业务接口
public interface Userservice {
    void food();
}
  1. UserServiceImpl业务实现
public class UserServiceImpl implements Userservice {
    private UserDao userDao=new UserDaoImpl();
    public void food() {
        userDao.food();
    }
}
  1. 在我们之前的业务中,用户需求可能会影响原来的代码,我们要根据用户的需求取修改原代码,如果程序代码里大,那么修改成本会非常昂贵
  2. 我们使用一个set接口实现:
public class UserServiceImpl implements Userservice {
    private UserDao userDao;
//    使用set实现动态调用
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public void food() {
        userDao.food();
    }
}
  • 之前程序是主动创建对象,控制权在程序员
  • 使用set注入后,程序不在具有主动性,而是被动的接受对象
  • 这种思想从本质解决问题,对象不在由程序控制,系统耦合性大大降低,程序员只需专注于业务逻辑的实现,这就是IOC的原型。
2.2 IOC本质
  • 控制反转IoC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IoC的一种方法,也有人认为DI只是IoC的另一种说法。
  • 没有IoC的程序中 , 我们使用面向对象编程 , 对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了。
  • IoC是Spring框架的核心内容,使用多种方式完美的实现了IoC,可以使用XML配置,也可以使用注解,新版本的Spring也可以零配置实现IoC。

总结:所谓的IOC就是对象由spring容器创建,管理,装配

3.Spring第一个程序 3.1 代码
  • ApplicationContext.xml:


    
        
    
    

        
    

  • 测试代码
public void Test01(){
        //获取ApplicationContext
  ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
  UserServiceImpl userServiceImpl = (UserServiceImpl) context.getBean("UserServiceImpl");
  userServiceImpl.food();
    }
3.2 IOC创建对象的方式
  1. 使用无参构造器创建对象,默认(必须有set方法)

        

  1. 使用有参构造器创建对象
  • 构造器参数下标赋值,不建议使用
 
        
 
  • 构造器参数类型赋值

        

  • 直接通过构造器参数名赋值
 
        
 

总结:在配置文件家族的额时候,容器中管理的对象以及初始化了

4. Spring配置 4.1 别名
 
        
    
 
4.2 Bean的配置

    
        
    
4.3 import
  • 一般用于团队开发,它可以将多个配置文件导入合并为一个

5. 依赖注入 5.1 构造器注入

前面写过

5.2 Set方式注入
  • 依赖注入:Set注入
  • 依赖:bean对象的创建依赖与容器
  • 注入:bean对象的所有属性由容器注入

1.实体类

@Getter
@Setter
@ToString
public class Student {
    private String name;
    private String empty;
    private UserDaoImpl userDao;
    private String [] books;
    private List hobbys;
    private Map userMaps;
    private Set userSet;
    private Properties properties;  
}

2.beans.xml



    
    

        

        
            
        

        

        
            
                a
                b
                c
            
        

        
            
                篮球
                足球
                乒乓球
            
        

        
            
                
                
            
        

        
            
                Lisi
                wuwu
            
        

        
            
                com:mysql:///
                root
                timi
            
        
    

3.测试类

@Test
    public void beanTest(){
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
        Student student = (Student) applicationContext.getBean("Student");
        System.out.println(student);
    }
5.3 扩展方式注入

使用命名空间注入需要在bean.xml文件中引入:

xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
  • p命名空间注入:

    

  • c命名空间注入:

    
5.4 Bean的作用域
  • singleton:单例模式(spring默认)只注入一个对象

  • prototype:原型模式:每次getBeans是就创建一个新对象

  • request:web开发有效
  • session:web开发有效
  • application:web开发有效
  • websocket:web开发有效
6. Bean自动装配
  • 自动装配是spring满足bean依赖的一种方式
  • spring会在上下文中自动寻找,并自动给bean装配属性

在Spring中有三中装配方式:

  1. 在xml中显示的配置
  2. 在java中显示配置
  3. 隐式的自动装配bean(重点)
6.1 测试
  1. pojo类
@Setter
@ToString
public class Fruit {
    private String grand;
    private Banner banner;
    private  Apple apple;
}
  1. ByName自动装配:

    
        
    
    
        
    

3.ByType自动装配


    
        
    
    
        
    

小结:

  • byname时,需要保证所有的bean的id唯一,并且这个bean需要和自动注入属性的set方法一致。
  • bytype时,需要保证所有的bean的class唯一,并且这个bean需要和自动注入的属性一致。
6.2 注解自动装配
  1. 导入约束:context约束
 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 http://www.springframework.org/schema/context/spring-context.xsd "
  1. 配置注解的支持:


  1. @Autowired
  • 直接在属性上使用,也可以在set方法上使用
  • 使用Autowired可以不用编写set方法,前提是自动装配的属性在IOC容器中存在。
  • @Autowired默认依据属性的类型从spring容器中寻找对应bean对象注入,如果spring容器中存在多个相同的bean对象需要结合@Qualifier(value=“id名”)指定唯一的bean对象注入
  • 也可以使用@Resource(name=“id名”)替代@Autowired和@Qualifier
7. 使用注解开发

在spring4之后使用注解开发必须导入aop依赖,使用注解需要导入context约束,还需要配置注解支持。




    

    

  • @Component:组件,放在类上,标志这个类被spring管理,就是bean,@Dao,@Service,@Controller效果一样
  1. bean
  2. 属性如何注入
@Component
@ToString
public class Dog {
    @Value("小王")
    private String name;
    @Value("2")
    private int age;
    public void song(){
        System.out.println("汪汪");
    }
}

  1. 衍生的注解,功能都是将对象注入spring容器,装配bean
  • @Dao
  • @Service
  • @Controller
  1. 自动装配
  2. 作用域:@Scope(“prototype”)
  3. 小结
    xml与注解:
    • xml更加万能,适用于任何场合,维护简单
    • 注解不是自己的类无法使用,维护相对比较复杂
    • xml用来管理bean
    • 注解只负责完成属性的注入
    • 使用前提:需要让注解生效



    

    

8.使用java的方式配置Spring
  1. 不使用spring的xml配置,全权交给java处理,JavaConfig是spring的一个子项目,在spring4之后成为核心功能。
    实体类:
@ToString
public class Cat {
    @Value("tom")
    private String name;
    @Value("2")
    private String age;
}

java配置类

//@Configuration代表配置类,spring的配置注解,将类对象注入到容器,相当就是一个@Component
@Configuration
@ComponentScan("com.wu.pojo")
public class CatConfig {
//    注册一个bean,方法名相当与bean标签的id属性,方法的返回值相当与bean标签的class属性
   @Bean
    public Cat getCat(){
        return new Cat();
    }
}

测试类:

 @Test
    public void testConfigurate(){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(CatConfig.class);
        Object cat = applicationContext.getBean("getCat");
        System.out.println(cat);
    }
9. 代理模式 1. 静态代理:
+ 静态代理角色分析:
  • 抽象角色:一般会使用接口或抽象类来解决
  • 真实角色:被代理的角色
  • 代理角色:代理真实角色,一般会做一些附属 *** 作
  • 客户:访问代理对象的人
    代理模式的优点:
  • 可以让真实角色的 *** 作更加纯粹,不用关注一些公共的业务
  • 公共部分交给代理角色,实现业务分离
  • 公共业务发生扩展时,方便集中管理
    缺点:
  • 一个真实角色就产生一个代理对象,代码量翻倍,开发效率低下。
    静态代理相当与service层调用dao层的对象进行业务逻辑 *** 作
2.动态代理
  • 动态代理和静态代理角色一样
  • 动态代理的代理类是动态生成的,不是我们直接写好的
  • 动态代理分为2大类, 基于接口的动态代理,基于类的动态代理
    1. 基于接口:JDK动态代理
    2. 基于类:cglib动态代理
    3. java字节码实现:javasist
      关键类:Proxy:代理类,生成代理对象;InvocationHandler:调用处理类接口
      代码实现:
      接口:
public interface Rent {
    void sing();
}

被代理的类:

public class Host implements Rent {

    public void sing() {
        System.out.println("狗在叫");
    }
}

动态生成代理对象的类,实现InvocationHandler接口:

//自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler {
    public void setRent(Rent rent) {
        this.rent = rent;
    }

    //被代理的接口
    private Object rent;
    //生成得到代理类
    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),rent.getClass().getInterfaces(),this);
    }
//    处理代理实例并返回结果
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//        动态代理的本质就是利用反射机制实现
        System.out.println("方法增强");
        Object invoke = method.invoke(rent, args);
        System.out.println("日志信息");
        return invoke;
    }
}

测试代码:

public class Client {
    public static void main(String[] args) {
        ProxyInvocationHandler handler = new ProxyInvocationHandler();
        Host host=new Host();
//     设置需要代理的对象
        handler.setRent(host);
        //获取动态生成的代理对象
        Rent proxy = (Rent) handler.getProxy();
        proxy.sing();
    }
}

一个动态代理类代理的是一个接口,一般对应一类业务
一个动态代理类可以代理多个类,只需要实现了相同的接口

10. AOP 1.AOP概念
  • 面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。
  • AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。
  • 利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
2.AOP在Spring中的作用
  • Aspect: Aspect 声明类似于 Java 中的类声明,在 Aspect 中会包含着一些 Pointcut 以及相应的 Advice。
  • Joint point:表示在程序中明确定义的点,典型的包括方法调用,对类成员的访问以及异常处理程序块的执行等等,它自身还可以嵌套其它 joint point。与切入点匹配的执行点。
  • Pointcut:表示一组 joint point,这些 joint point 或是通过逻辑关系组合起来,或是通过通配、正则表达式等方式集中起来,它定义了相应的 Advice 将要发生的地方。
  • Advice:Advice 定义了在 pointcut 里面定义的程序点具体要做的 *** 作,它通过 before、after 和 around 来区别是在每个 joint point 之前、之后还是代替执行的代码。类中的一个方法。
  • Target:被通知的对象

Spring支持的5种类型的Advice:
通知的5种类型:执行顺序:相同类型已配置顺序为准

  1. before:前置通知
  2. after:后置通知
  3. afterReturning:环绕通知,返回后加入,有异常不执行
  4. afterThrowing:异常抛出通知,有异常才会执行
    5 .round:引介通知,
3.使用Spring实现AOP
  1. 使用AOP织入,需要导入依赖

  org.aspectj
     aspectjweaver
     1.9.5
 

方式一.;使用spring原生的api接口

  • 接口:
public interface UserService {
    void add();
    void delete();
    void update();
    void select();
}
  • 接口实现类:
public class UserServiceImpl implements UserService {
    public void add() {
        System.out.println("添加数据");
    }

    public void delete() {
        System.out.println("删除数据");
    }

    public void update() {
        System.out.println("修改数据");
    }

    public void select() {
        System.out.println("查询数据");
    }
}
  • spring原生api接口实现方法增强:
public class AfterLog implements AfterReturningAdvice {

    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("环绕通知"+method.getName()+",返回结果为:"+returnValue);
    }
}

public class BeforeLog implements MethodBeforeAdvice {
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("前置方法"+method.getName()+"执行了");
    }
}
  • xml文件配置:

    
    
    
    
    
    

        
        
        
        
    
  • 测试
 @Test
    public void testAop(){
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
//动态代理代理的是接口
        UserService userService = applicationContext.getBean("userService", UserService.class);
        userService.add();
    }

方式二:自定义类

  • 自定义切面类:
public class DiyLog {
    public void before(){
        System.out.println("自定义类前置增强方法");
    }
    public void after(){
        System.out.println("自定义类后置增强方法");
    }
}
  • xml配置

    
    

        

            

            
            
        
    

方式三:使用注解实现

  • 自定义类:
Component
//声明切面类
@Aspect
public class DiyLog {
    //    使用 @Pointcut 来声明切入点表达式.后面的其他通知直接使用方法名来引用当前的切入点表达式.
    @Pointcut("execution(* com.wu.service.UserServiceImpl.*(..))")
    public void common(){

    }

//    声明前置通知和切入点
    @Before("common()")
    public void before(){
        System.out.println("自定义类前置增强方法");
    }
//    声明后置通知和切入点
    @After("common()")
    public void after(){
        System.out.println("自定义类后置增强方法");
    }
}
  • xml配置

    

    
    

    
11.整合Mybatis 方式一

步骤:

1. 导入jar包

        
            org.projectlombok
            lombok
            1.18.16
        
        
            org.springframework
            spring-webmvc
            5.3.3
        
        
            junit
            junit
            4.13.1
        
        
            org.aspectj
            aspectjweaver
            1.9.5
        
        
            mysql
            mysql-connector-java
            8.0.22
        
        
            org.mybatis
            mybatis
            3.5.3
        
        
            org.springframework
            spring-jdbc
            5.3.3
        
        
            org.mybatis
            mybatis-spring
            2.0.3
        
    

2.编写接口:

public interface BookCaseMapper {
    List selectBookCaseList();
}

实现类:

@Setter
public class BookCaseMapperImpl implements BookCaseMapper {
    private SqlSession sqlSession;
    public List selectBookCaseList() {
        return sqlSession.getMapper(BookCaseMapper.class).selectBookCaseList();
    }
}

BookCaseMapper.xml:





   

3. 编写配置文件

mybatis.xml:





    
     
    
        
    

















spring-dao.xml:




    

    
        
        
        
        
    

    
        

        
        
    


    

        
    



也可以采用多个配置文件开发:applicationContext.xml



    
    
        
    

5. 测试
    @Test
    public void Test2(){
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-dao.xml");
        BookCaseMapperImpl bookCaseMapper = applicationContext.getBean(BookCaseMapperImpl.class);
        List bookCases = bookCaseMapper.selectBookCaseList();
        System.out.println(bookCases);
    }
方式二

实现类:

//方式二
public class BookCaseMapperImpl extends SqlSessionDaoSupport implements BookCaseMapper {

    public List selectBookCaseList() {
        return getSqlSession().getMapper(BookCaseMapper.class).selectBookCaseList();
    }
}

spring-dao.xml:



    

        
    

applicationContext.xml:


    
        
     
12.声明式事务 1.事务概念
  • 把一组 *** 作作为一个业务,要么同时成功,要么同时失败
  • 事务在项目开发中,十分重要,涉及数据一致性问题
  • 确保数据的完整性和一致性

事务的ACID原则

  • 原子性
  • 一致性
  • 隔离性:多个业务可能 *** 作同一个资源,防止数据损坏
  • 永久性:事务一旦提交,就会被持久化写入存储器。
2. 事务管理
  • 编程式事务
  • 声明式事务
    1. spring-dao.xml配置

    
        
    


    


        

            
            
            
            
        
    


    
        
        
    

2.实现类:

public class BookCaseMapperImpl extends SqlSessionDaoSupport implements BookCaseMapper {

    public List selectBookCaseList() {
        add(new BookCase(22,"爱情片"));
        updateById(new BookCase(20,"动漫"));
        return getSqlSession().getMapper(BookCaseMapper.class).selectBookCaseList();
    }

    public int add(BookCase bookCase) {
        return getSqlSession().getMapper(BookCaseMapper.class).add(bookCase);
    }

    public int updateById(BookCase bookCase) {
        return getSqlSession().getMapper(BookCaseMapper.class).updateById(bookCase);
    }


}

3.测试类:

    @Test
    public void Test2(){
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        BookCaseMapper bookCaseMapper = applicationContext.getBean(BookCaseMapper.class);
        List bookCases = bookCaseMapper.selectBookCaseList();
        System.out.println(bookCases);
    }

注意采用aop事务织入时spring默认jdk基于接口的动态代理,必须获取接口的class,而不应该是实现类的bean

3. 为什么需要配置事务:
  • 如果不配置事务,可能会存在数据提交不一致问题
  • 如果不在spring中配置事务,我们需要在代码中手动配置
  • 事务在项目开发中十分重要,保证事务的ACID原则。

Baan的生命周期详解(转载)

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5672278.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存