您当前的位置: 首页 > 

梁云亮

暂无认证

  • 3浏览

    0关注

    1211博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

第二章 IOC

梁云亮 发布时间:2022-04-25 12:44:52 ,浏览量:3

简介

IoC—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。如何理解好Ioc呢?理解好Ioc的关键是要明确“谁控制谁,控制什么,为何是反转(有反转就应该有正转了),哪些方面反转了

img

有了IoC/DI的容器后,在客户端类中不再主动去创建这些对象了

img

5.1 IoC是什么

IoC 不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合、更优良的程序。传统应用程序都是由我们在类内部主动创建依赖对象,从而导致类与类之间高耦合,难于测试;有了IoC容器后,把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是 松散耦合,这样也方便测试,利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。

其实IoC对编程带来的最大改变不是从代码上,而是从思想上,发生了“主从换位”的变化。应用程序原本是老大,要获取什么资源都是主动出击,但是在IoC/DI思想中,应用程序就变成被动的了,被动的等待IoC容器来创建并注入它所需要的资源了。

5.2 IoC与DI

DI—Dependency Injection,即“依赖注入”:组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。

理解DI的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么”,那我们来深入分析一下:

●谁依赖于谁:当然是应用程序依赖于IoC容器;

●为什么需要依赖:应用程序需要IoC容器来提供对象需要的外部资源;

●谁注入谁:很明显是IoC容器注入应用程序某个对象,应用程序依赖的对象;

●注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)。

IoC和DI由什么关系呢?其实它们是同一个概念的不同角度描述,由于控制反转概念比较含糊(可能只是理解为容器控制对象这一个层面,很难让人想到谁来维护对象关系),所以2004年大师级人物Martin Fowler又给出了一个新的名字:“依赖注入”,相对IoC 而言,“依赖注入”明确描述了“被注入对象依赖IoC容器配置依赖对象”。

看过很多对Spring的Ioc理解的文章,好多人对Ioc和DI的解释都晦涩难懂,反正就是一种说不清,道不明的感觉,读完之后依然是一头雾水,感觉就是开涛这位技术牛人写得特别通俗易懂,他清楚地解释了IoC(控制反转) 和DI(依赖注入)中的每一个字,读完之后给人一种豁然开朗的感觉。我相信对于初学Spring框架的人对Ioc的理解应该是有很大帮助的

5.3 spring常用的注入 5.3.1 单例singleton 多实列 prototype

1.Spring中的对象默认都是 单例模式。

2.使用 @Scope(“prototype”) 注解来使对象成为多例模式。

3.通过@Autowired 注入的Service 或者是其他实例其实是单例的。

4.通过 ApplicationContext.getBean(C.class); 获取的实例是多例的。

总结:在存在并发的时候,每个需要被注入的类、对象 都使用@Scope(“prototype”) 注解成为多例,每个需要被获取的对象通过ApplicationContext.getBean(C.class);来获取,确保每个线程获取的对象都是新的。

image-20210629111354860

image-20210629111412345

5.3.2 构造方法注入

image-20210701082318644



    
    

    
        
        
        
    

    
        
        
        
    

    
        
        
        
    

    
        
        
    
    
        
        
    


    
        yyyy年MM月dd日 hh时mm分ss秒
    




    
    



    
    



    
    
    
    



    
    
    
    



    
    
    
    



    



    





5.3.3 属性注入

image-20210701082416785

5.3.4. 常用类型的注入方式
集合注入相关
	构造方法数组注入
		  
					
					
					

					
					    
						北京
						天津
						上海
						重庆
					    
					
		 


    List集合
	    private List bks;
		
		    
			
			
			
		    
		

		 
			
			    
				张三
				张三丰
				李四
			    
			
		

    数组
	    private String[] addr;	
		
		    
			洛阳
			郑州
			北京
			上海
			开封
		    
		

	map集合
		
		    

		    
			
			    
				
				
			    
			

			
			    
				
				
				
				
			    
			

			
			    
				张三
				张三丰
				李四
			    
			
		    	
		    
	set 集合
        Set
		
		    
			aaaa
			bbbb
			cccc
			dddd
		    
		

	Properties 集合
		 
		    
			aaa1
			bbb2
			ccc3
			ddd4
		    
		

image-20210701163702591

image-20210701163635013

  • 使用@Value注解,@Autowired 注入

    books=php,java,javascript,html,java,java,php
    db.set=1,2,3,1,2,3
    db.arr=1,2,3,1,2,3
    db.list=1,2,3,1,2,3
    db.map={name:'wangwu',age:28,age:22,age:33,is:true}
    
    /*
     * Copyright (c) 2006, 2021, webrx.cn All rights reserved.
     *
     */
    package cn.webrx.entity;
    
    import lombok.Data;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Component;
    
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    
    /**
     * 

    Project: spring2021 - Student *

    Powered by webrx On 2021-11-02 11:02:47 *

    Created by IntelliJ IDEA * * @author webrx [webrx@126.com] * @version 1.0 * @since 17 */ @Data @Component public class Student { @Value("1111") private int id; @Value("1.2") private double money; @Value("李青") private String name; @Value("true") private boolean isstu; @Value("java,php,html,mysql,php,html") private String[] arrstr; @Value("10,20,30,40") private int[] arrint; @Value("#{'java,php,html,mysql,php,html'.split(',')}") private Set set; @Value("#{'java,php,html,mysql,php,html'.split(',')}") private List list; @Value("#{{name:'lisi',age:18,is:true}}") private Map map; @Value("#{t1.name}") private String tname; @Value("#{student.id * 2}") private int num; @Autowired private Teacher t3; @Value("${books}") private String[] tarr; @Value("#{'${books}'.split(',')}") private Set tset; @Value("#{${db.map}}") private Map tmap; @Value("#{{t1,t2,teacher}}") private Teacher[] teachers; @Value("#{{t1,t2,teacher}}") private List listts; }

    测试程序

    package cn.webrx.config;
    
    import cn.webrx.entity.Teacher;
    import cn.webrx.entity.User;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.*;
    
    @Configuration("ccc")
    @ComponentScan("cn.webrx.entity")
    @Import(DruidConfig.class)
    @PropertySource("t.properties")
    public class AppConfig {
    
        @Bean(initMethod = "start",destroyMethod = "end") @Scope("singleton")
        public Teacher t1(){
            Teacher t = new Teacher(10,"周老师");
            System.out.println(t);
            return t;
        }
    
        @Bean("t2") @Scope("prototype")
        public Teacher t2(){
            Teacher t = new Teacher(22,"李老师");
            return t;
        }
    
        @Bean("t3") @Scope("prototype")
        public Teacher t2(@Value("88") int id, @Value("王老师") String name){
            Teacher t = new Teacher(id,name);
            return t;
        }
    
        @Bean @Scope("prototype")
        public User user(){
            User u = new User();
            u.setId(11);
            u.setName("李六");
            return u;
        }
    
        @Bean("u1") @Scope("prototype")
        public User user2(){
            User u = new User();
            u.setId(22);
            u.setName("李七");
            return u;
        }
    
    
    
        @Bean("t4") @Scope("prototype")
        public Teacher t2(@Value("88") int id, @Value("王老师") String name,@Value("#{'a,b,c,c,c,c,f'.split(',')}") String[] books,@Qualifier("u1") User user){
            Teacher t = new Teacher(id,name);
            t.setBooks(books);
            t.setUser(user);
            return t;
        }
    
    }
    
    
5.4 bean常用配置方法

image-20210701082737665

注解: @Resource() @PostConstruct @PreDestroy jdk 9以后不能使用,如果使用,添加如下依赖:



    javax.annotation
    javax.annotation-api
    1.3.2


/*
 * Copyright (c) 2006, 2021, webrx.cn All rights reserved.
 *
 */
package cn.webrx.entity;

import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;

/**
 * 

Project: spring - Db *

Powered by webrx On 2021-07-01 17:25:48 *

Created by IntelliJ IDEA * * @author webrx [webrx@126.com] * @version 1.0 * @since 16 */ @Data @Component("d3") // @Scope("singleton") @Lazy(true) public class Db { //@Resource(name = "php") 引入一个javax.annotation-api jar @Autowired @Qualifier("php") private Book book; public Db() { System.out.println("构造方法Db()"); } //引入一个javax.annotation-api jar @PostConstruct public void start() { System.out.println("start....."); } @PostConstruct public void a1() { System.out.println("start222..."); } //引入一个javax.annotation-api jar @PreDestroy public void close() { System.out.println("close........"); } }

5.5 spring 注解使用

image-20210701082823255


    
        
        
        
    
    
    



image-20210701083333509

@Service、
@Controller、 
@Repository 、
@Component
@Value、@Scope、@Lazy、 @PostConstruct、 @PreDestroy
@Autowired、@Resource(name="book")



    id id值
    name 名称
    class 指定类
    init-method 初始化
    destroy-method 销毁
    scopy = singleton | prototype 多实例,使用时再实例化对象
    lazy-init="true" 延迟加载
    ="false" 立即加载,立即初始实例化类bean


        spring容器使用注解
        beans.xml 文件加入关联

        










        初始化方法
        配置方式
        init-method="abc"   容器在构造方法完成后,直接执行abc方法

        scope="prototype" 如果是多实例,则是每次使用,都要执行构造方法,同时执行初始化方法

        scope="singleton" 单例模式,是默认的,是立即装载 都要执行构造方法,同时执行初始化方法

        注解方式
        package com.fz.entity;
        import org.springframework.context.annotation.Scope;
        import org.springframework.stereotype.Component;
        import org.springframework.stereotype.Controller;
        import org.springframework.stereotype.Service;
        import javax.annotation.PostConstruct;
        import javax.annotation.PreDestroy;
        /**
        * Created by webrx on 2017-07-03.
        */
        //@Controller("uok")
        //@Component("uok")
        @Service("uok")  //@Scope("prototype")
        @Scope("singleton")

        @Controller    User -> user
        userInfo -> userInfo
        public class User {
        public User(){
        System.out.println("构造方法()..");
        }
        @PostConstruct  初始化方法
        public void init(){
        System.out.println("init--初始化...");
        }
        @PreDestroy
        public void destory(){
        System.out.println("销毁方法");
        }
        public void show(){
        System.out.println("数据显示........");
        }
        @PostConstruct
        public void abc(){
        System.out.println("abc..");
        }
        }


        销毁方法
        配置方式
        destroy-method="destory"

        当容器销毁对象时,会自动调用destory方法
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
        User u = ctx.getBean("users",User.class);
        ctx.close();

        注解方式
        package com.fz.entity;
        import org.springframework.context.annotation.Scope;
        import org.springframework.stereotype.Component;
        import org.springframework.stereotype.Controller;
        import org.springframework.stereotype.Service;
        import javax.annotation.PostConstruct;
        import javax.annotation.PreDestroy;
        /**
        * Created by webrx on 2017-07-03.
        */
        //@Controller("uok")
        //@Component("uok")
        @Service("uok")  //@Scope("prototype")
        @Scope("singleton")
        public class User {
        public User(){
        System.out.println("构造方法()..");

        }
        @PostConstruct
        public void init(){
        System.out.println("init--初始化...");
        }
        @PreDestroy  //销毁方法
        public void destory(){
        System.out.println("销毁方法");
        }
        public void show(){
        System.out.println("数据显示........");
        }
        @PostConstruct
        public void abc(){
        System.out.println("abc..");
        }
        }


        @Component("st")
        @Controller
        @Service("sss")
        @Repository











        自动装配
        
        byName
        byType
        default-autowire="byName"


















        












    
    



    
    



    
    




        注解功能
        1)配置spring容器
        





        2)注解使用
        @Component 如果不写,则使用类名小写作为名称

        @Component("uuu")

        @Data @Component
        public class Book {
        @Value("100")
        private int id;

        @Value("《mysql数据库技术》")
        private String name;
        }


        @Autowired 根据类型自动装配

        @Autowired //根据类型自动装配 byType
        @Autowired @Qualifier("user") //根据名称自动装配 byName
        private User user;

        @Resource(name="book")


        3)注解bean类方法
        注解bean类  com.entity.Db类
        ---------------------------------------------------
        @Component("db")
        public class Db {
        public void show(){
        System.out.println("dbshow");
        }
        }

        @Controller("member")
        public class Member {
        public void save(){
        System.out.println("saveok");
        }
        }

        @Service("m")
        public class Member {
        public void save(){
        System.out.println("saveok");
        }
        }

        @Repository("mm")
        public class Member {
        public void save(){
        System.out.println("saveok");
        }
        }
        4)注解单例 多例
        ---------------------------------------------------
        @Repository("mm") @Scope("singleton")  单例默认
        public class Member {

        }

        @Repository("mm") @Scope("prototype")  多实例
        public class Member {

        }

        5)注解初始化方法
        import javax.annotation.PostConstruct;
        ---------------------------------------------------
        @PostConstruct
        public void a(){
        System.out.println("初始化1");
        }

        @PostConstruct
        public void init(){
        System.out.println("初始化2");
        }

        6)注解销毁方法
        import javax.annotation.PreDestroy;
        ---------------------------------------------------
        @PreDestroy
        public void close(){
        System.out.println("退出");
        }

        @PreDestroy
        public void exit(){
        System.out.println("销毁");
        }


        7)属性注入
        -------------------------------------------------------
        @Data
        @Component("book")
        @Scope("prototype")
        public class Book {
        @Value("BS101")
        private String bid;
        @Value("java书籍")
        private String bname;
        }

        @Data @Repository("mm") @Scope("prototype")
        public class Member {
        @Resource(name="book")  此处的book 就是指定工厂中的  上的那book名@Component("book")
        相当于beans.xml 中的
        private Book book;
        }


        win10

        @Data @Repository("mm") @Scope("prototype")
        public class Member {
        @Autowired  根据类型自动注入对象
        private Book book;
        }

        8)延迟加载
        -----------------------------------------------------------------
        单例模式是默认的,会立即加载  加上@Lazy 不自动加载,第一次使用时再加载
        @Data
        @Component @Scope("singletone") @Lazy
        public class Teacher {
        private String name;

        public Teacher() {
        System.out.println("空构造方法");
        }

        public Teacher(String name) {
        this.name = name;
        System.out.println("有参数name的构造方法");
        }
        public void info(){
        System.out.println("老师姓名:"+this.name);
        }
        }

        @Scope("prototype") 多实例,默认使用的使用时加载

        @Data @Repository("mm") @Scope("singleton") @Lazy   延迟加载,在第一次使用时加载
        public class Member {

        }

        @Data @Repository("mm") @Scope("singleton") @Lazy(false)  立即加载初始化
        public class Member {
        }

        beans.xml

 所有bean都延迟实例化初始化加载

默认注入相关属性对象


image-20210701083800959


    
    
    
    
        
        
        
        
        
    
    
    
        
        
    
    
        
        
    
    
        aaa
        bbb
        ccc
        ddd
    
    
        100
        200
        300
        400
    


升级jdk9后 @PostConstruct、@Predestroy @Resource(name=“”)找不到

image-20210701083956662

package org.beiyou.entity;

import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Properties;

/**
 * 

功能描述:

* * @author webrx * @version 1.0 * @date 2020-04-27 9:13 */ @Data //@Repository("userbook") @Component("userbook") @Scope("prototype") //prototype singleton @Lazy(true) public class Book { @Value("10") private int id; @Value("《java项目开发》") private String name; @Value("98.92") private double price; //@Autowired @Autowired @Qualifier("author") private Author zsaasdf; @Autowired @Qualifier("addr") private List addrs; @Autowired public List show; @Autowired @Qualifier("prop") private Properties prop; @Resource(name = "my") public Author myuser; @PostConstruct public void init() { System.out.println("init(...)"); } @PreDestroy public void close() { System.out.println("close()"); } }
5.6 bean自动装配方式

image-20210701084432752

5.7 spring 注解 1. @Configuration

应用于一个类,相当于建立一个applicationContext.xml文件

2. @ComponentScan

相当于xml配置文件中的

3. @Bean

相当于xml配置文件中的

/*
 * Copyright (c) 2006, 2021, webrx.cn All rights reserved.
 *
 */
package cn.webrx.config;

import cn.webrx.service.UserDao;
import org.springframework.context.annotation.*;

/**
 * 

Project: spring2021 - SpringConfig *

Powered by webrx On 2021-11-02 16:28:20 *

Created by IntelliJ IDEA * * @author webrx [webrx@126.com] * @version 1.0 * @since 17 */ @Configuration @ComponentScan("cn.webrx.service") public class SpringConfig { @Bean(name="uu",initMethod = "init",destroyMethod = "close") @Scope("singleton") @Lazy public UserDao u1(){ var u = new UserDao(); return u; } }

4. @Scope

此注解一般在类上,IoC是否为单例@Scope("singleton") ,相当于配置文件中的

5. @Import

导入其它配置类,相当于配置文件中的

package cn.webrx.config;

import cn.webrx.entity.Teacher;
import org.springframework.context.annotation.*;

@Configuration("ccc")
@ComponentScan("cn.webrx.entity")
@Import(DruidConfig.class)
public class AppConfig {

    @Bean(initMethod = "start",destroyMethod = "end") @Scope("singleton")
    public Teacher t1(){
        Teacher t = new Teacher(10,"周老师");
        System.out.println(t);
        return t;
    }

    @Bean("t2") @Scope("prototype")
    public Teacher t2(){
        Teacher t = new Teacher(22,"李老师");
        return t;
    }
}


package cn;

import cn.webrx.config.AppConfig;
import cn.webrx.config.DruidConfig;
import cn.webrx.entity.Teacher;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.Arrays;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {AppConfig.class, DruidConfig.class})
public class MyDemo {
    @Autowired
    private Teacher t1;

    @Autowired
    private ApplicationContext ctx;


    @Test
    public void t1() {
        System.out.println(t1);
        System.out.println(ctx.getBeanDefinitionNames().length);
        System.out.println("--------------------");
        Arrays.stream(ctx.getBeanDefinitionNames()).forEach(System.out::println);

        var tt1 = ctx.getBean("t2");
        var tt2 = ctx.getBean("t2");
        System.out.println(tt1 == tt2);

    }
}

6. @Value
@Value("1111")
private int id;
@Value("1.2")
private double money;
@Value("李青")
private String name;
@Value("true")
private boolean isstu;
@Value("java,php,html,mysql,php,html")
private String[] arrstr;
@Value("10,20,30,40")
private int[] arrint;

@Value("#{'java,php,html,mysql,php,html'.split(',')}")
private Set set;

@Value("#{'java,php,html,mysql,php,html'.split(',')}")
private List list;

@Value("#{{name:'lisi',age:18,is:true}}")
private Map map;


@Value("#{t1.name}")
private String tname;

@Value("#{student.id * 2}")
private int num;

@Autowired
private Teacher t3;

//t.properties books=php,java,javascript,html,java,java,php
@Value("${books}")
private String[] tarr;

@Value("#{'${books}'.split(',')}")
private Set tset;

//t.properties db.map={name:'wangwu',age:28,age:22,age:33,is:true}
@Value("#{${db.map}}")
private Map tmap;

//注入List t1 t2 teacher分别是IoC容器的bean
@Value("#{{t1,t2,teacher}}")
private Teacher[] teachers;

@Value("#{{t1,t2,teacher}}")
private List listts;
7. @Autowired
//如果IoC容器没有,就装配null,不报错
@Autowired (required = false)
//自动装配,先根据类型,如果类型有多,再根据属性的变量名,如果没有变量名,报错。
@Autowired
public User user;

//自动装配,先根据类型,如果类型有多,再根据属性的变量名,如果没有变量名,可以指定 @Qualifier("uu")。
@Autowired @Qualifier("uu")
private UserDao userdao;
关注
打赏
1665409997
查看更多评论
立即登录/注册

微信扫码登录

0.0436s