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

spring学习笔记

Java 更新时间:发布时间: 百科书网 趣学号
spring 简介
  • Spring:2002,首次推出雏形,interface21
  • 2004,3月24,推出1.0版本
  • spring理念:使现有的技术更加容易使用,本身是一个大杂烩,整合了现有的技术框架
优点
  • Spring是一个开源的免费的框架(容器)
  • Spring是一个轻量级的、非入侵式的框架
  • 控制反转(IOC),面向切面编程(AOP)
  • 支持事务的处理,对框架整合的支持
组成

Spirng7大模块

拓展
  • spring boot
    • 一个快速开发的脚手架
    • 基于spring boot可以快速的开发单个微服务
    • 构建一切
    • 约定大于配置
  • spring cloud
    • 基于spring boot实现的
    • 协调一切

因为现在大多数公司都在使用spring boot进行快速开发,学习spring boot的前提,需要完全掌握spring及springMVC,承上启下的作用。

spring弊端:发展了太久之后,违背了原来的理念,配置十分繁琐,人称“配置地狱”。

IOC理论推导
  1. UserDao接口

  2. UserDaoImpl实现类

  3. UserService业务接口

  4. UserServiceImpl业务实现类

在我们之前的业务中,用户的需求可能会影响我们原来的代码,我们需要根据用户的需求去修改原代码!如果程序代码量十分大,修改代码的代价十分昂贵。

我们使用了一个Set接口实现,已经发生了革命性的变化

//private UserDao userDao= new UserDaoOracleImpl();//写死了,需求变了这就要跟着变,有问题
private UserDao userDao;
//利用set进行动态实现值的注入
public void setUserDao(UserDao userDao) {
    this.userDao = userDao;
}
  • 之前,程序是主动创建对象,控制权在程序员手上!
  • 使用了set注入后,程序不再具有主动性,而是变成了被动的接受对象!

这种思想,从本质上解决了问题,我们程序员不用再去管理对象的创建了。系统的耦合性大大降低,不再牵一发而动全身了,可以更加专注在业务的实现上。这是IOC的原型!

IOC的本质

控制反转IOC,使用中设计思想,DI(依赖注入)是实现IOC的一种方法,我么使用面向对象编程,对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓的控制反转就是:获得以来对象的方式反转了。

采用XML方式配置Bean的时候,Bean的定义信息和实现分离,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。

控制反转是一种通过描述(XML或者注解)并通过第三方去生产或获取特定对象的方式。在spring中实现控制反转的是IOC容器,其实现方法是依赖注入。

所谓IOC一句话:对象由Spring创建,装配,管理

IOC创建对象的方式
  1. 下标赋值

        
        
       
 
  1. 类型匹配

        
        
        -->
        
 
  1. 参数名

        
        
        

总结:再配置文件加载的时候,容器中管理的对象就已经初始化了!

Spring 配置 别名

Bean的配置



import

一般用于团队开发使用,他可以将多个配置文件导入合成为一个。不同的人开发不同的类,需要注册在不同的bean中,我们可以通过import将所有人的beans.xml合并为一个总的


如果有重名,也会合并

放在applicationContext.xml文件中

DI依赖注入

前面说过的

  • 构造器注入

  • set方式注入

    • 依赖:bean对象的创建依赖于容器
    • 注入:bean对象的所有属性,由容器来注入
    
    
        
        
        
        
        
        
            
                红楼梦
                水浒传
                三国演义
            
        
        
        
            
                听歌
                写代码
            
        
        
        
            
                
                
            
        
        
        
            
                LOL
                CF
            
        
        
        
            
                123
                
                root
                123456
            
        
        
        
            
        
    
    

其他拓展方式:

  • 可以使用p命名空间和c命名空间注入,官方文档使用方式

  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zy4vcd3L-1632970714580)(C:UsersAdministratorAppDataRoamingTyporatypora-user-imagesimage-20210821160023423.png)]

  • 
    
    
    

注意点:p命名和c命名需要导入xml约束才可以使用

bean的作用域
  • 单例模式(spring默认)

  • 
    
  • 原型模式:每次从容器中get时,都会产生新的对象

  • 
    
  • 其余的request,session,application,这些只能在web开发中使用

bean的自动装配
  • 自动装配是spring满足bean以来的一种方式
  • Spring会在上下文中自动寻找,并自动给bean装配属性

在spring中由三种装配方式

  1. 在xml中显式的配置
  2. 在java中显式的配置
  3. 隐式的自动装配bean

xml显式配置


    
   
    

ByName自动装配:在容器中找与set方法后面参数名一致的bean的id进行装配


    
   

ByType自动装配:在容器中找与set方法后面参数类型一致的bean进行装配,容器中这个类型的bean必须唯一。


    
   

注解完成自动装配
  • 增加命名空间context

  • 开启注解

  • 
    
    
    
    
    
@Autowired可以根据名字或者类型自动装配,如果有类型相同id不同的多个bean,就要结合@Qualifier("dog112")注解使用

    @Autowired
    @Qualifier("dog112")
    private Dog dog;
    @Autowired
    private Cat cat;

@Autowired注解可以放在属性上,也可以放在set方法上,如果使用了注解,就可以不用写set方法。

@Resource注解也可以完成@Autowired的功能

他们的区别:

  • 都可以放在属性字段上
  • @Autowired两种方式都可以实现常用
  • @Resource默认通过byname,如果找不到名字则通过bytype
  • 执行顺序不同:
    • @Autowired:bytype
    • @Resource:byname
使用注解开发
  1. bean

  2. 属性如何注入

    @Component
    public class User {
        @Value("gfq")
        private String name;
    }
    
  3. 衍生注解

  • @Controller
  • @Service
  • @Repository
  1. 自动装配

  2. 作用域

使用注解要导入aop的包,并且开启注解支持以及指定扫描包




完全使用java配置类

配置类1

//它就是一个配置类,相当于xml配置文件
@Configuration//相当于xml中的beans,它本身也是一个组件,也要交给spring管理
@ComponentScan("com.edu.xaut.pojo")//配置扫描后,就不用再配置bean了
public class MyConfig {
    @Bean//注册一个bean
    //相当于在xml里面配置一个bean,id为方法名,class相当于返回值类型
    public User getUser(){
        return new User();//返回要注入bean的对象
    }
}

import配置类

@Configuration
@import(MyConfig.class)//导入其他配置类,相当于xml中import其他配置文件一样
public class MyConfig2 {
    @Bean
    public People getPeople(){
        return new People();
    }
}

测试

public class MyTest {
    @Test
    public void test01(){
        //完全使用配置类方式,只能通过AnnotationConfig上下文来获取容器,通过配置类的class对象加载
        ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig2.class);
        User user = context.getBean("getPeople", User.class);
        System.out.println(user.getName());
    }

}

这种方式Springboot随处可见

代理模式

为什么要学习代理模式?因为这就是Spring AOP的底层【SpringAOP,和SpringMVC】

静态代理
  • 抽象角色:代理和真实对象共同实现,一般由接口或者抽象类来解决
  • 真实角色:被代理的对象
  • 代理角色:代理真实角色,会在真实角色的基础上附加一些操作
  • 客户:访问代理对象的人

代理模式的好处:

  • 可以使真实角色的操作更加纯粹,不用去关注一些公共的业务
  • 公共的业务交给代理角色,实现了业务的分工
  • 当公共业务发生扩展的时候,方便集中管理

代码步骤:

  1. 接口

    public interface Rent {
        public void rent();
    }
    
  2. 真实角色

    public class Host implements Rent {
        @Override
        public void rent() {
            System.out.println("房东要出租房子");
        }
    }
    
  3. 代理角色

    public class Proxy implements Rent{
        private Host target;
    
        public Proxy() {
        }
    
        public Proxy(Host target) {
            this.target = target;
        }
    
        @Override
        public void rent() {
            seeHouse();
            target.rent();
            payMoney();
        }
    
        //带客人看房
        void seeHouse(){
            System.out.println("代理带客人看房");
        }
        //收费
        void payMoney(){
            System.out.println("代理收费");
        }
    }
    
  4. 客户

    public class Client {
        public static void main(String[] args) {
            //房东
            Host host = new Host();
            //中介代理房东出租房子
            Proxy proxy = new Proxy(host);
    
            //客户直接和中介交流
            proxy.rent();
        }
    }
    

缺点:

  • 一个真实角色就会产生一个代理角色;代码量会翻倍,开发效率会变低
动态代理
  • 动态代理和静态代理角色一样
  • 动态代理的代理类是动态生成的,不是直接写好的
  • 动态代理分为两大类:基于接口的动态代理,和基于类的动态代理
    • 基于接口:jdk动态代理
    • 基于类:cjlib动态代理
    • java字节码实现:Javassist
  • 需要了解两个类:Proxy和InvocationHandler
public class MyInvocationHandler implements InvocationHandler {

    private Object target;

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

    public Object getProxy(){
        //创建一个代理对象
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(),this);
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        log(method.getName());
        //通过反射调用
        Object result = method.invoke(target,args);
        return result;
    }

    public void log(String msg){
        System.out.println("[DEBUG]调用了"+msg+"方法");
    }
}

测试

public class Client {
    public static void main(String[] args) {
        //通过jdk动态代理实现输出日志
        //真实对象
        UserServiceImpl userService = new UserServiceImpl();
        //生成代理类
        MyInvocationHandler invocationHandler = new MyInvocationHandler();
        //将真实对象注入,实现对其的代理
        invocationHandler.setTarget(userService);
        //获得代理对象
        UserService proxy = (UserService) invocationHandler.getProxy();
        proxy.update();
    }
}

动态代理的好处:

  • 可以使真实角色的操作更加纯粹,不用去关注一些公共的业务
  • 公共业务就交给代理角色,实现了业务的分工
  • 公共业务发生扩展的时候,方便集中管理
  • 一个动态代理类代理的是一个接口,一般就是对应的一类业务
  • 一个动态代理类可以代理多个类,只要是实现了同一个接口
AOP

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

实现AOP的方式一:JDK动态代理,使用Spring原生API接口【主要是spring API接口实现】




    
    
    
    
    


方式二:自定义类实现AOP【主要是切面定义】

aop的配置



    
    
        
        
        
        
        
    

自定义一个通知类

将这个通知类织入到切入点

public class DiyAdvice {
    public void before(){
        System.out.println("方法执行前");
    }
    public void after(){
        System.out.println("方法执行后");
    }
}

方式三:注解实现

将方式二中定义切面时用注解实现

@Aspect//标注这个类为切面
public class AnnotationDiyAdvice {
    //定义为before方法,并定义切入点
    @Before("execution(* com.edu.xaut.service.UserServiceImpl.*(..))")
    public void before(){
        System.out.println("方法执行前");
    }

    @Around("execution(* com.edu.xaut.service.UserServiceImpl.*(..))")
    public void around(ProceedingJoinPoint jp) throws Throwable {
        System.out.println("环绕前");
        jp.proceed();
        System.out.println(jp.getSignature());
        System.out.println("环绕后");
    }
}

将这个类标注为切面后,将这个类注册到spring容器中,并开启aop注解支持





源码

BeanDefinitionReader BeanDefinition BeanFactoryPostProcessor BeanFactory

实例化bean 填充属性 BeanPostProcessor:before init BeanPostProcessor:after

createProxy

ceImpl.*(…))")
public void around(/JoinPoint 它没有调用before方法,而且也没有proceed方法/ProceedingJoinPoint jp) throws Throwable {
System.out.println(“环绕前”);
jp.proceed();
System.out.println(jp.getSignature());
System.out.println(“环绕后”);
}
}

将这个类标注为切面后,将这个类注册到spring容器中,并开启aop注解支持

```xml





源码

BeanDefinitionReader BeanDefinition BeanFactoryPostProcessor BeanFactory

实例化bean 填充属性 BeanPostProcessor:before init BeanPostProcessor:after

createProxy

转载请注明:文章转载自 www.051e.com
本文地址:http://www.051e.com/it/282096.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 ©2023-2025 051e.com

ICP备案号:京ICP备12030808号