zoukankan      html  css  js  c++  java
  • Spring ( 二 ) IOC 依赖注入

    个人博客网:https://wushaopei.github.io/    (你想要这里多有)


    1、什么是IOC

    IOC 全称指的是 Inverse Of Control 控制反转。

    原来我们使用Spring之前对象都是通过代码 new 对象()来自己进行创建。

    现在使用了Spring之后。只需要在Spring的配置文件中进行配置,那么spring就会帮我们new出对象来。

    2、什么是DI

    DI 指的是Dependency Injection 。是依赖注入的意思。

    BookService{
        BookDao bookDao;
    
        public void setBookDao( BookDao bookDao ){
            this.bookDao = bookDao;
        }
    }

    只需要配置就可以把依赖的对象的值注入到引用中。

    3、第一个IOC示例程序 -- 通过id获取对象(重点)

    实验1:通过IOC容器创建对象,并为属性赋值★

    1、创建一个Java工程:

    创建相应的类

    person类代码

    为节省空间,省略getset方法,toString不写

    package com.webcode.pojo;
    import java.util.List;
    import java.util.Map;
    import java.util.Properties;
    
    /** * @author Administrator *
     */
    public class Person {	
    
    	private Integer id;
    	private String name;
    	private Integer age;
    	private String phone;
    	private Car car;
    	
    	public Person() {
    		super();
    		// TODO Auto-generated constructor stub
    	}
    	public Person(Integer id, String name, Integer age, String phone, Car car) {
    		super();
    		this.id = id;
    		this.name = name;
    		this.age = age;
    		this.phone = phone;
    		this.car = car;
    	}
    	

    Car 类的代码

    public class Car {
    	
    /*
        省略 getset方法 和 toString方法不写
    */
    	private String name;
    	private String carNo;
    	public Car() {
    		super();
    		// TODO Auto-generated constructor stub
    	}
    	public Car(String name, String carNo) {
    		super();
    		this.name = name;
    		this.carNo = carNo;
    	}
    }

    2、导入jar包:

    • commons-logging-1.1.3.jar
    • log4j-1.2.17.jar
    • spring-beans-4.3.18.RELEASE.jar
    • spring-context-4.3.18.RELEASE.jar
    • spring-core-4.3.18.RELEASE.jar
    • spring-expression-4.3.18.RELEASE.jar

    applicationContext.xml配置文件内容如下:

    <!-- 
    	bean标签标识要配置一个bean对象
    	class 属性配置你要陪哪个Bean对象的全类名
    	id 属性给配置的Bean对象起一个唯一标识
     -->
    	<bean id="p1" class="com.webcode.pojo.Person">
    		<!-- 
    			property 标签配置属性的值
    				name 标识你要配置哪个属性
    				value 属性配置这个属性的值
    	 	-->
    	 	<property name="id" value="1"></property>
    	 	<property name="name" value="旻"></property>
    		<property name="age" value="25"></property>
     		<property name="phone" value="148999999"></property>
    	</bean>

    测试的代码:

            @Test
    	public void test1()throws Exception {
    		//ApplicationContext 表示SpringIOC 容器
    		ApplicationContext applicationContext  =  new ClassPathXmlApplicationContext("applicationContext.xml");
    		//使用了Spring之后。对象都交给Spring窗口来创建和管理
    		//Spring 容器就是一个map,然后id是key class 时哪个value
    		Person person = (Person) applicationContext.getBean("p1");
    		System.out.println(person);
    	}

    打印结果:

    问题:

    1、FileSystemXmlApplicationContext怎么用?

    答:跟使用JavaSE的相对路径一样

    2、Bean是在什么时候被创建的?

    答:在创建Spring容器的时候,创建Bean对象(默认)

    1. 如果调用getBean多次,会创建几个?

    答:默认创建同一个

     

    常见的错误:

    指定的id不存在。找不到bean对象。

    4、IOC示例程序 -- 通过类型获取对象(重点)

    实验2:根据bean的类型从IOC容器中获取bean的实例★

    配置文件代码:

    	<bean id="p2" class="com.webcode.pojo.Person" >
    		<!-- 	property 标签配置属性的值
    				name 标识你要配置哪个属性
    				value 属性配置这个属性的值 -->
    	 	
    	 	<property name="id" value="2"></property>
    	 	<property name="name" value="旻"></property>
    		<property name="age" value="25"></property>
     		<property name="phone" value="148999999"></property>
    	</bean>
          @Test
          public void test2()throws Exception{
    		ApplicationContext applicationContext =new ClassPathXmlApplicationContext("applicationContext.xml");
    		
    		 * 
    		 * 按类型查找,找到一个就直接返回
    		 * 没有找到就报错
    		 * 找到多个也报错
    		 * 
    		System.out.println(applicationContext.getBean(Person.class));
    	}

    常见错误说明:

    按类型查找,找不到就报错

    当在applicationContext.xml配置文件中。有多个同Person.class类型实现的时候。

    5、IOC示例程序 -- 通过构造方法参数名注入值

    实验3:通过构造器为bean的属性赋值

            <bean id="p3" class="com.webcode.pojo.Person">
    		
    		<!-- 	constructor-arg 是按构造器参数赋值
    				name	给哪个属性赋值
    				value	传递的参数值 -->
    		
    		<constructor-arg name="name" value="王玄策" />
    		<constructor-arg name="id" value="3" />
    		<constructor-arg name="age" value="38" />
    		<constructor-arg name="phone" value="198745632" />
    	</bean>  

    测试代码:

            @Test
    	public void test3()throws Exception{
    		 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    		 System.out.println(applicationContext.getBean("p3"));
    	}

    打印结果:

    6、IOC示例程序 -- index属性指定参数的位置

    实验4:通过index属性指定参数的位置

            <bean id="p4" class="com.webcode.pojo.Person">
    		
    			<!-- constructor-arg 是按构造器参数赋值
    				name	给哪个属性赋值
    				value	传递的参数值 -->
    		
    		<constructor-arg index="1" value="大汉光武" />
    		<constructor-arg index="0" value="4" />
    		<constructor-arg index="2" value="26" />
    		<constructor-arg index="3" value="1888951233" />
    	</bean> 

    测试代码:

            @Test
    	public void test4()throws Exception{
    		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    		System.out.println(applicationContext.getBean("p4"));
    	}

    打印结果:

    7、IOC示例程序 -- 根据参数类型注入

    实验5:根据参数类型注入

    
    	public Person(Integer id, String name, Integer age, String phone) {
    		super();
    		System.out.println("创建了Person==有参");
    		this.id = id;
    		this.name = name;
    		this.age = age;
    		this.phone = phone;
    	}
    	
    	public Person(Integer id, String name, String phone,Integer age) {
    		super();
    		System.out.println("创建了Person==有参");
    		this.id = id;
    		this.name = name;
    		this.age = age;
    		this.phone = phone;
    	}

    配置信息:

            <bean id="p5" class="com.webcode.pojo.Person">
    		<!-- Integer id, String name, Integer age, String phone
    		
    			constructor-arg 是按构造器参数赋值
    				index	构造参数的索引
    				value	传递的参数值 -->
    		
    		 <constructor-arg index="0" value="4" type="java.lang.Integer"></constructor-arg>
    		 <constructor-arg index="1" value="帅才" type="java.lang.String"></constructor-arg>
    		 <constructor-arg index="2" value="19" type="java.lang.Integer"></constructor-arg>
    		 <constructor-arg index="3" value="18" type="java.lang.String"></constructor-arg>
    		
    	</bean> 

    测试代码:

            @Test
    	public void test5()throws Exception{
    		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    		System.out.println(applicationContext.getBean("p5"));
    	}

    打印结果:

    8、IOC之 P名称空间

    实验6:通过p名称空间为bean赋值

    配置信息:

    		<!-- p名称空间是同过set方法复制 -->
    	
    	<bean id="p6" class="com.webcode.pojo.Person"
    		p:id="6"  p:age="25" p:name="旻"  p:phone="145665389">
    				
    	</bean>

    测试代码:

            @Test
    	public void test6()throws Exception{
    		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    		System.out.println(applicationContext.getBean("p6"));
    	}

    打印结果:

    9、测试null值的使用

    实验7:测试使用null值

    配置信息:

            <!-- 测试null值的应用 -->
    	<bean id="p7 " class="com.webcode.pojo.Person">
    		<property name="id" value="7"></property>
    		<property name="name"><null></null></property>
    	</bean>

    测试代码:

    	@Test
    	public void test7() throws Exception {
    		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    		Person person = (Person) applicationContext.getBean("p7");
    		System.out.println( person.getName().length() );
    	}

    10、IOC之子对象的赋值测试(重点)

    实验8:引用其他bean★

    创建个新的工程。测试Spring的开发环境。此不重复。请参阅前面,环境搭建。

    Car对象

    public class Car {
    
    	private String name;
    	private String carNo;
    
    public class Person {
    
    	private Integer id;
    	private String name;
    	private Integer age;
    	private String phone;
    	private Car car;

    配置信息:

            <bean id="car" class="com.webcode.pojo.Car" p:name="宝马" p:carNo="京B123412"/>
    
    	<bean id="p8" class="com.webcode.pojo.Person">
    		<property name="id" value="8" />
    		<!-- 
    			car属性,可以通过ref(引用的意思)某个指定id值的对象
    		 -->
    		<property name="car" ref="car" />
    	</bean>

    测试代码:

    	@Test
    	public void test8() throws Exception {
    		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    		Person person = (Person) applicationContext.getBean("p8");
    		System.out.println( person );
    	}

    打印结果:

    11、IOC之内部Bean的使用

    实验9:引用内部bean

    配置信息:

            <!--  引用内部bean -->
    	<bean id="p9" class="com.webcode.pojo.Person">
    		<property name="id" value="9"></property>
    		<property name="car">
    			<!-- 内部bean ,不能被外部使用 -->
    			<bean id="car02" class="com.webcode.pojo.Car"  p:name="内部car" p:carNo="京B123422" />
    		</property>
    	</bean>

    测试代码:

            @Test
    	public void test9() throws Exception {
    		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    		Person person = (Person) applicationContext.getBean("p9");
    		System.out.println( person );
    		System.out.println( applicationContext.getBean("car02") );
    	}

    打印结果:

    常见错误:内部的Bean不能被外部使用

    12、IOC之List属性的赋值

    实验10:使用list子元素为List类型的属性赋值

    Person对象

    配置的信息:

            <bean id="p10" class="com.webcode.pojo.Person">
    		<property name="id" value="9"></property>
    		<property name="list">
    			<!-- list标签,表示当前配置一个list集合 -->
    			<list>
    				<value>文</value>
    				<value>星</value>
    				<value>念</value>
    			</list>
    		</property>
    	</bean>

    ------------------------------------------  此处省略测试代码!

    打印结果

    13、IOC之Map属性的赋值

    实验11:使用map子元素为Map类型的属性赋值

    配置信息:

            <!-- 实验11:使用map子元素为Map类型的属性赋值 -->
    	<bean id="p11" class="com.webcode.pojo.Person">
    		<property name="id" value="9"></property>
    		<property name="map">
    			<!-- map标签,表示当前配置一个map集合 -->
    			<map>
    				<entry key="key1" value="远方"></entry>
    				<entry key="key2" value="流星"></entry>
    				<entry key="key3" value-ref="car"></entry>			
    			</map>
    		</property>
    	</bean>

    ------------------------------------------  此处省略测试代码!

    打印结果:

    14、IOC之Properties属性的赋值

    实验12:使用prop子元素为Properties类型的属性赋值

    配置信息:

            <!-- 实验12:使用prop子元素为Properties类型的属性赋值 -->
    	<bean id="p12" class="com.webcode.pojo.Person">
    		<property name="id" value="9"></property>
    		<property name="map">
    			<!-- props标签,表示当前配置一个Properties -->
    			<props>
    				<prop key="user">root</prop>
    				<prop key="password">123456</prop>
    			</props>
    		</property>
    	</bean>

    ------------------------------------------  此处省略测试代码!

    打印结果:

    15、IOC之util 名称空间

    util名称空间,可以定义

    实验13:通过util名称空间创建集合类型的bean

    配置信息:

            <!--  util名称空间引用,可以定义
    		实验13:通过util名称空间创建集合类型的bean-->
    		<!-- 定义一个list集合 -->
    	<util:list id="list1">
    		<value>string1</value>
    		<value>string2</value>
    		<value>string3</value>	
    	</util:list>	
    	<bean id="p13" class="com.webcode.pojo.Person">
    		<property name="id" value="13"></property>
    		<property name="name" value="旻"></property>
    		<property name="age" value="24"></property>
    		<property name="phone" value="1722235896"></property>
    		<!-- list对象 ref表示引用 -->
    		<property name="phones" ref="list1"></property>
    	</bean>

    测试代码:

            @Test
    	public void test13()throws Exception{
    		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    		Person person = (Person) applicationContext.getBean("p13");
    		System.out.println( person );
    		
    		List<String> list = (List<String>) applicationContext.getBean("list1");
    		System.out.println(list);
    	}

    打印结果:

    图解:

    16、IOC之级联属性赋值

    实验14:给bean的级联属性赋值

    配置:

            <!-- 实验14:给bean的级联属性赋值	 
    			常见错误:
    		级联属性一定要先注入对象。再注入对象的属性
    	-->
    	<bean id="p14" class="com.webcode.pojo.Person">
    	 	<property name="id" value="14"></property>
    	 	<property name="name" value="星"></property>
    	 	<property name="age" value="27"></property>
    	 	<property name="phone" value="17889652345"></property>
    	 	<!-- list对象 ref 表示引用 -->
    	 	<property name="car" ref="car"></property>
    	 	<!-- -级联属性 -->
    	 	<property name="car.name" value="凯迪拉克"></property>
    	</bean>

    ------------------------------------------  此处省略测试代码!

    打印结果:

    常见错误:

    级联属性一定要先注入对象。再注入对象的属性

    图解:

    17、IOC之静态工厂方法创建Bean

    实验15:配置通过静态工厂方法创建的bean

    代码:

        public class PersonFactory {
    	public static Person createPerson() {
    		return new Person(1, "我是静态工厂方法创建出来的", 18, "18688886666");
    	}
        }

    配置信息:

            <!-- 静态工厂方法调用创建对象	
    			factory-method 是指调用哪个方法返回对象 -->
    	
    	<bean id="p15" class="com.webcode.pojo.factory.PersonFactory"
    		factory-method="createPerson"/>

    ------------------------------------------  此处省略测试代码!

    图解:

    不重写toString方法的情况下,地址值相同,调用的是同一个对象,从工厂中的方法获取

    创建对象流程:

    18、IOC之工厂实例方法创建Bean

    实验16:配置通过实例工厂方法创建的bean

        public class PersonFactory {
    
    	public Person createPerson2() {
    		return new Person(1, "我是工厂实例方法创建出来的", 18, "18688886666");
    	}
    	
        }

    配置信息:

            <!-- 配置工厂实例 -->
    	<bean id="personFactory" class="com.webcode.pojo.factory.PersonFactory"/>
    	<!-- 
    		factory-bean="personFactory" 	表示准备调用哪个实例的方法
    		factory-method="createFacroty2"  是指调用哪个方法  	
    	 -->
    	 <bean id="p16" factory-bean="personFactory" factory-method="createPerson2">            </bean>
    	

    ------------------------------------------  此处省略测试代码!

    打印结果:

    流程图解:

    19、IOC之FactoryBean接口方式创建对象

    实验17:配置FactoryBean接口创建Bean对象

    FactoryBean接口方式

    package com.webcode.pojo.factory;
    import org.springframework.beans.factory.FactoryBean;
    import com.webcode.pojo.Person;
        public class PersonFactoryBean implements FactoryBean<Person> {	
    	/*
    	 * 创建对象实例的适合,调用的方法
    	 * */
    	@Override
    	public Person getObject() throws Exception {		
    		return new Person(1,"我是PersonFactoryBean类",18,"14568526666");
    	}	
    	/*
    	 * 返回对象的类型,相当于class属性
    	 * */
    	@Override
    	public Class<?> getObjectType() {		
    		return Person.class;
    	}	
    	/*
    	 * 是否是单例
    	 * */
    	@Override
    	public boolean isSingleton() {
    		return true;
    	}		
    }
    

    配置信息:

            <!-- 
    		创建一个工厂实例对象FactoryBean接口的实现类
    	 -->
    	<bean id="p17" class="com.webcode.pojo.factory.PersonFactoryBean"/>

    ------------------------------------------  此处省略测试代码!

    打印结果:

    图解流程:

    20、IOC之继承Bean配置

    实验18:通过继承实现bean配置信息的重用

    配置信息:

            <!-- 实验18:通过继承实现bean配置信息的重用 -->
    		<bean id="parent" class="com.webcode.pojo.Person">
    		<property name="id" value="100"></property>
    		<property name="name" value="我思念的人啊"></property>
    		<property name="age" value="24"></property>
    		<property name="phone" value="1477888999"></property>	
    	</bean>
    	<!-- parent="parent" 继承指定的parentid的bean对象的配置信息-->
    	<bean id="p18" class="com.webcode.pojo.Person" parent="parent">
    		<property name="id" value="18"></property>
    	</bean>

    ------------------------------------------  此处省略测试代码!

    打印结果:

    图解:先比较parent与id是否相同,再拿class进行比较,

    注意:当有两个id相同,而类型不同的bean存在时,会出现ReaderContext.error读取异常

    21、IOC之abstract抽象Bean定义(配置)

    实验19:通过abstract属性创建一个模板bean

            <!-- 
    		abstract="true"表示这是一个抽象的配置,抽象的就不能被实例化
    	 -->
    	<bean id="parent" class="com.webcode.pojo.Person" abstract="true">
    		<property name="id" value="100"></property>
    		<property name="name" value="这是父亲的名称"/>
    		<property name="age" value="30" />
    		<property name="phone" value="父亲的电话" />
    	</bean>

          

    22、IOC之组件创建顺序

    实验20:bean之间的依赖  depends-on 属性

    public class A {
    	public A() {
    		System.out.println("创建了A对象");
    	}
    }
    public class B {
    	public B() {
    		System.out.println("创建了B对象");
    	}
    }
    public class C {
    	public C() {
    		System.out.println("创建了C对象");
    	}
    }

    配置信息:

            <!-- 
    		depends-on="b"	依赖b
    		如果你要创建a,要先有b
    	 -->
    	<bean id="a" class="com.webcode.pojo.A" depends-on="b,c"/>
    	<bean id="b" class="com.webcode.pojo.B"/>
    	<bean id="c" class="com.webcode.pojo.C"/>

    测试代码:

            @Test
    	public void test1() throws Exception {
    		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    //		System.out.println( applicationContext.getBean("a") );
    	}

    打印结果:

    23、IOC之Bean的单例和多例(重点)

    实验21:测试bean的作用域,分别创建单实例和多实例的bean★

    <!-- 
    	scope配置作用域	分别是四个值:singleton、prototype、request、session
    	singleton	这是默认值	表示单例
    			1、当Spring容器创建的时候,单例的对象就会被创建出来。
    			2、单例的对象,在每次调用getBean的时候都返回同一个对象
    	prototype	表示多例
    			1、当创建Spring容器的时候,不会创建出多例的对象
    			2、当调用getBaen方法时,会创建一个对象
    			3、每次调用getBean,都会创建一个实例
           ===============request和Session了解======================				
    	request		    表示一次请求内,多次调用getBean都只会返回同一个对象
    			当调用getBean方法时内部原理类似如:
            		    Object bean = request.getAttribute(id);
    			    if (bean == null) {
                			 bean = 创建一个实例;
            			 request.setAttribute(id,bean);
    			    }
    			    return bean;
    	session		    表示同一个会话,多次调用getBean都只会返回同一个对象
    			当调用getBean方法时内部原理类似如:
    			    Object bean = session.getAttribute(id);
    	        	    if (bean == null) {
    				bean = 创建一个实例;
    				session.setAttribute(id,bean);
             		    }
    			    return bean;
    	 -->
    	<bean id="a" class="com.webcode.pojo.A" scope="request"></bean>

    单例——singleton 打印结果:

    多例——prototype打印结果:

    24、基于xml配置文件的自动注入

    先创建Person类和Car类

    public class Car {
    
    	private String name;
    private String carNo;
    public class Person {
    private Integer id;
    	private Car car;
    
    	public Person(Car car) {
    		this.car = car;
    	}
    
    	<!-- 
    	<bean id="car" class="com.webcode.pojo.Car">
    		<property name="name" value="海南马自达car" />
    		<property name="carNo" value="琼A123412"/>
    	</bean>
    	<bean id="car1" class="com.webcode.pojo.Car">
    		<property name="name" value="海南马自达car1" />
    		<property name="carNo" value="琼A123412"/>
    	</bean>
    
    		default和no就是不配置就没值
    		byName	按属性名做为id名称查找bean对象,并自动注入
    			1、找到就自动注入
    			2、找不到就null
    		byType	按子对象的类型查找bean对象,并自动注入
    			1、找到一个就自动注入
    			2、找到多个就报错。
    			3、没有找到就null
    		constructor	表示按构造器参数查找并自动注入
    			1、会先按类型查找
    				1.1、查找一个就自动注入
    				1.2、查找到多个,就继续以参数名做为id接着查找,然后注入
    				1.3、查找到多个,就继续以参数名做为id接着查找,没有找到就为null值
    			2、没有找到就是null
    				先按类型==>>再按参数名做为id===>>最后是null
    	 -->
    	<bean id="p20" class="com.webcode.pojo.Person" autowire="constructor">
    		<property name="id" value="20"></property>
    <!-- 		<property name="car" ref="car" /> -->
    	</bean>

    测试代码:

    	@Test
    	public void test2() throws Exception {
    		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    		System.out.println( applicationContext.getBean("p20") );
    	}

    手动配置引用注入:图解

    Default指令效果图解

          

    byType 指令效果图解

    匹配的子对象为class中的Car

          

    constructor按构造器参数查找并自动注入 图解

    4~6步执行setget和toString方法


  • 相关阅读:
    小白日记33:kali渗透测试之Web渗透-扫描工具-Burpsuite(一)
    小白日记31:kali渗透测试之Web渗透-扫描工具-Arachni
    小白日记30:kali渗透测试之Web渗透-扫描工具-Skipfish
    小白日记29:kali渗透测试之Web渗透-扫描工具-Vega
    小白日记28:kali渗透测试之Web渗透-扫描工具-Nikto
    小白日记27:kali渗透测试之Web渗透-Http协议基础,WEB
    小白日记26:kali渗透测试之提权(六)--收集敏感信息,隐藏痕迹
    小白日记24:kali渗透测试之提权(四)--利用漏洞提权
    小白日记25:kali渗透测试之提权(五)--利用配置不当提权
    小白日记23:kali渗透测试之提权(三)--WCE、fgdump、mimikatz
  • 原文地址:https://www.cnblogs.com/wushaopei/p/11762934.html
Copyright © 2011-2022 走看看