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

Spring5学习笔记

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

Spring5学习笔记

文章目录
  • Spring5
    • 1.IOC
      • 1.1 IOC概念
      • 1.2 IOC的原理
      • 1.3 IOC的两个重要接口
      • 1.4 什么是Bean管理?
      • 1.5 Bean管理的两种方式
        • 基于xml配置文件
          • 属性注入的两种方式
          • 1.set方法注入:
          • 2.有参构造:
          • 3. 注入一些特殊的值
            • 注入null值
            • 注入带特殊字符的值
            • 注入引用类型的参数
            • 数组、集合注入值
            • 数组、集合注入对象
          • Spring中两种类型的Bean
            • 普通的bean:
            • FactoryBean:
          • Bean的作用域
          • Bean的生命周期
          • XML方式的自动装配(均针对引用类型)
          • Xml中引入外部的配置文件
        • 基于注解的Bean管理
            • 使用注解注入属性
            • 完全注解开发

Spring5 1.IOC 1.1 IOC概念

IOC,即控制反转,是将创建对象、对象调用交给了Spring管理,然后通过依赖注入(DI),将对象注入,降低了耦合度

1.2 IOC的原理

IOC容器是由工厂模式反射解析xml实现

1.3 IOC的两个重要接口
  • BeanFactory:它是IOC容器的基本实现,是Spring内部使用的接口。其特点是,加载配置时不会创建Bean的对象,使用时才会创建

  • ApplicationContext,它是BeanFactory的子接口,比BeanFactory的功能更多更强,一般是开发人员使用。其特点是,加载配置时就会创建Bean的对象。(如果Bean对象很大就可以使用ApplicationContext来创建,而不是BeanFactory在使用时才创建,那将很费时)

    这两个类就是ApplicationContext的两个实现类,File开头的是从磁盘中去找xml;Class开头的是从类路径找(常用)

1.4 什么是Bean管理?

所谓Bean管理,包括两个操作:

  • 创建对象
  • 属性注入
1.5 Bean管理的两种方式
  • 基于xml配置文件
  • 基于注解
基于xml配置文件

xml配置文件使用bean标签即可,xml方式默认使用的是无参构造(如果你写了有参构造,请把无参构造显示的写出来,因为spring在你显示的声明构造函数后就不会自动创建无参了)

基本使用如下:




    
        
        
    

属性注入的两种方式

(属性注入就是为属性赋值,即xml中的property标签):

  • set方法注入
  • 有参构造
1.set方法注入:

其实就是我上面的那段代码,同时对象中必须也要为属性添加set方法,如:

public class User {

    private String name;
    private Integer age;

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}
2.有参构造:

既然是有参构造,类中肯定要写有参构造函数的




    
        
        
    

3. 注入一些特殊的值 注入null值

测试代码:

@Test
    void test(){
        ApplicationContext context =new ClassPathXmlApplicationContext("user.xml");
        User user = context.getBean("user", User.class);
        System.out.println(user);
    }

看下效果:

注入带特殊字符的值

比如我们要注入< 开头的,它会被xml当作某个标签,会报错,应该这样()




    
        
             ]]> 
        
        
    

或者你可以将它转义:

注入引用类型的参数

注入其它bean,可以分为外部bean内部bean。它两个的作用都是注入对象类型的属性

值得注意的是,这里的内部、外部均是从一个bean的角度来说的,外部就是写两个bean,其中一个引用另一个,而内部就是bean里面套个bean,看下例子就明白了

首先,我们需要新建一个Order类,然后再User类中定义一个Order类型的属性,并加上set方法,如:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uXQCaOhL-1636293871576)(…/AppData/Roaming/Typora/typora-user-images/image-20211106193859562.png)]

外部bean写法:

外部这种还有一种写法,可做了解:(这种需要在User类里为order对象写一个getter方法,不然报错,ref那一句必须写在前面;此时对order对象属性的赋值可以在user bean中,也可以在order bean中,但是同时在两个bean中为同一个属性赋值,会使用user的,比如下图中的money,结果为123456而不是10000)

内部bean写法:

这两种方式的目的和作用是一样的,根据个人喜好,我比较喜欢第一种

数组、集合注入值

创建一个类,其属性包括数组和集合:并为它们生成setter方法,添加toString方法

xml配置:




    
        
        
            
                
                
                
            
        

        
        
            
                
                
                
            
        

        
        
            
                6
                
                6
            
        

        
        
            
                
                吧?
            
        
    

测试:

@Test
void test(){
    ApplicationContext context =new ClassPathXmlApplicationContext("test.xml");
    Test test = context.getBean("test", Test.class);
    System.out.println(test);
}

结果:

错误原因是因为Test这个类名,改一下,我该成了Pig,涉及到类名的地方都应改为Pig

可以看到没问题,但是我们现在给数组、集合的值都是String的,如果是对象呢?

数组、集合注入对象

这里就演示下list:

private List list;

我将list的元素类型改为了Order,你可以随便建一个类

public class Order {
    private Integer money;


    public void setMoney(Integer money) {
        this.money = money;
    }

    @Override
    public String toString() {
        return "Order{" +
                "money=" + money +
                '}';
    }
}

xml配置:

首先你应该再写两个bean标签:创建多个(一个也行,重复赋给list)


    


    

list的配置改为:


    
        
        
    

运行一下测试方法:

对于map:都一样的使用方式

视频里说还可以将这些map、list封装一下,让所有的bean都能使用;需要用到命名空间,我觉得用处不大,放个视频链接:

xml-数组、集合p1

xml-数组、集合p2

Spring中两种类型的Bean

Spring中有两种类型的bean,一种是普通的就是我们xml中配置的那些;还有一个叫FactoryBean

普通的bean:

配置文件中的class属性指定是哪个类,就创建哪个类的对象


    

FactoryBean:

可以和class指定的类型不一样,我们只需要让Order类实现FactoryBean接口并实现其中的方法


测试方法:

@Test
void test(){
    ApplicationContext context =new ClassPathXmlApplicationContext("test.xml");
    User user = context.getBean("order1", User.class);
    System.out.println(user);
}

这样就达到了返回非class属性指定类型的对象(不过我觉得没啥意义)

Bean的作用域
  • singleton
  • prototype
  • request
  • session

singleton(默认就是它):单例,意为只会为这个类创建一个对象

我们创建两个User对象:user1和user2,并打印引用地址

可以看到,user1和user2是指向的同一个对象地址。这就是单例

prototype:多例,即可以为这个类创建多个对象,和单例相反。除此之外,单例是在加载配置文件时就创建对象,而多例则是在getBean()的时候创建的

我们只需要改下xml配置:

可以看到,引用地址是不同的,创建了两个对象

request(web环境下才可使用,即引入web依赖):将产生的对象放到request中


    

session(web环境下才可使用):将产生的对象放到session中


    

request、session不常用

Bean的生命周期
  • 实例化
  • 属性值注入
  • 初始化
  • 销毁

这里有一篇不错的博文,存个地址在这:https://www.jianshu.com/p/1dec08d290c1

这是我的Order类,里面定义了一个初始化方法和销毁方法:

运行一下:

然后我们实现一下InstantiationAwareBeanPostProcessor接口,它有两个方法分别会在实例化前后执行:

public class MyInstence implements InstantiationAwareBeanPostProcessor {
    @Override
    public Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException {
        System.out.println("我在实例化之前执行了");
        return InstantiationAwareBeanPostProcessor.super.postProcessBeforeInstantiation(beanClass, beanName);
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        System.out.println("我在实例化之后执行了");
        return InstantiationAwareBeanPostProcessor.super.postProcessAfterInstantiation(bean, beanName);
    }
}

然后在配置文件中写一个bean:(该接口就会对这个配置文件的全部bean生效)


运行一下:

BeanPostProcessor接口也是同样的用法,只是你需要实现不同的方法:

XML方式的自动装配(均针对引用类型)

byName:

byType:

如果存在多个class中的类相同,比如:

Xml中引入外部的配置文件

个人感觉用处不大,放个视频链接,有需要还能看看:https://www.bilibili.com/video/BV1Vf4y127N5?p=19

基于注解的Bean管理

有四个注解可以将类交给IOC容器管理:

@Controller

@Service

@Component

@Repository

但是仅仅加上注解还不行,我们还需要配置xml,让它去扫描带这些注解的类:



    





你需要额外加上这两句才行!!!!

我们在Order类上加上@Component:

测试类:

运行:

在配置扫描时,我们还可以选择扫描哪些、不扫描哪些:

使用注解注入属性

以下四个注解:

@Autowired :根据类型注入

@Qualifier :根据名字注入,需搭配@Autowired或者@Resource使用

@Resource :既可以根据type也可以根据name注入(先找name)

@Value :普通类型的属性注入,如:字符串

结构:

userservice中注入usermapperimpl对象(@AutoWried)

@Service
public class UserService {
    @Value("xiaoxiang")
    private String name;
    @Autowired
    private UserMapper userMapper;
    
    public void test(){
        userMapper.add();
    }
}

UserMapper:

public interface UserMapper {
    void add();
}

实现类:

@Repository
public class UserMapperImpl implements UserMapper {
    @Override
    public void add() {
        System.out.println("添加成功");
    }
}

@Resource和@AutoWried使用是一样的,只是Resource默认先匹配name,再type

说说@Qualifier和@AutoWried的搭配使用:

现在,我们再写一个UserMapper接口的实现类UserMapperImpl1:此时单独使用@AutoWried按类型注入是会报错的,因为按类型查找会找到两个类,他不知道注入哪一个

但是此时加上@Qualifier,根据name指定,就能注入指定的对象

你也许会说那直接用@Resource不就行了,来看看吧:

错误是:找不到正确的UserMapper类型的对象,期望是一个但是找到两个。

我们注入的UserMapper是接口,它的实现类都被Spring管理。这里其实是用了多态,

不管UserMapper有没有通过注解交给Spring进行Bean管理,注入接口,都会去找其实现类(当然实现类必须交给Spring管理),所以针对注入接口类型的(且实现类超过一个),都会按照type去找,此时必须使用@AutoWried+@Qualifier 或者 @Resource(因为此时会按照type注入,等于和@AutoWried一样) +@Qualifier。

因为@AutoWried是Spring中的,而@Resource是扩展包的,所以更推荐@AutoWried

完全注解开发

创建一个配置类,替代xml中的组件扫描

@Configuration
//可配置多个包路径
@ComponentScan({"com.xp.spring.mapper","com.xp.spring.service"})
public class MyConfig {
}

这样就好了,测试类我们需要改一下:

@Test
void test2(){
    ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
    UserService userService = context.getBean("userService", UserService.class);
    userService.test();
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5PYM7jPW-1636293871689)(…/AppData/Roaming/Typora/typora-user-images/image-20211107215954986.png)]

今天到这里

持续更新中。。。。。。。。。。。。。。。。。。。。。。。。。。

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

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

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