spring6之容器:IOC

avatar
作者
筋斗云
阅读量:2

 容器:IOC

控制反转(Ioc)

                                                                

IoC容器在Spring的实现

Spring 的 IoC 容器就是 IoC思想的一个落地的产品实现。IoC容器中管理的组件也叫做 bean。在创建 bean 之前,首先需要创建IoC 容器。Spring 提供了IoC 容器的两种实现方式:

**①BeanFactory**

这是 IoC 容器的基本实现,是 Spring 内部使用的接口。面向 Spring 本身,不提供给开发人员使用。

**②ApplicationContext**

BeanFactory 的子接口,提供了更多高级特性。面向 Spring 的使用者,几乎所有场合都使用 ApplicationContext 而不是底层的 BeanFactory。

**③ApplicationContext的主要实现类**

获取bean的三种方式:

package com.zzq.spring6.iocxml;  import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;  public class TestUser {     public static void main(String[] args) {         ApplicationContext context=new                 ClassPathXmlApplicationContext("bean.xml");         //根据id获取bean         User user1=(User) context.getBean("user1");         System.out.println(""+user1);         //根据类型获取bean         User user2=context.getBean(User.class);         System.out.println(""+user2);         //根据id和类型获取bean         User user3=context.getBean("user",User.class);         System.out.println(""+user3);     } } 

如果组件类实现了接口,根据接口类型可以获取 bean 吗?

> 可以,前提是bean唯一

如果一个接口有多个实现类,这些实现类都配置了 bean,根据接口类型可以获取 bean 吗?

> 不行,因为bean不唯一
依赖注入:

1、类有属性,创建对象过程中,向属性设置值

第一种方式:基于set方法完成

package com.zzq.spring6.iocxml.di;  import org.junit.jupiter.api.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;  public class TestBook {     @Test     public void testSetter(){         ApplicationContext context=new                 ClassPathXmlApplicationContext("bean-di.xml");         Book book = context.getBean("book", Book.class);         System.out.println(book);     } } 

 book.java

package com.zzq.spring6.iocxml.di;  public class Book {     private String bname;     private  String author;      @Override     public String toString() {         return "Book{" +                 "bname='" + bname + '\'' +                 ", author='" + author + '\'' +                 '}';     }      public String getBname() {         return bname;     }      public void setBname(String bname) {         this.bname = bname;     }      public String getAuthor() {         return author;     }      public void setAuthor(String author) {         this.author = author;     }      public Book(String bname, String author) {         this.bname = bname;         this.author = author;     }      public Book() {     } } 

bean-di.xml

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="book" class="com.zzq.spring6.iocxml.di.Book">     <property name="author" value="后端"></property>     <property name="bname" value="java"></property> </bean> </beans>

第二种方式:基于构造器完成

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--1、set方法注入-->     <bean id="book" class="com.zzq.spring6.iocxml.di.Book">         <property name="author" value="后端"></property>         <property name="bname" value="java"></property>     </bean>     <!--    2、构造器注入-->     <bean id="bookCon" class="com.zzq.spring6.iocxml.di.Book">         <constructor-arg name="author" value="java开发"></constructor-arg>         <constructor-arg name="bname" value="spring"></constructor-arg>     </bean> </beans>
package com.zzq.spring6.iocxml.di;  import org.junit.jupiter.api.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;  public class TestBook {        @Test     public void testConstructor(){         ApplicationContext context=new                 ClassPathXmlApplicationContext("bean-di.xml");         Book book = context.getBean("bookCon", Book.class);         System.out.println(book);     } } 

特殊值处理

##### ①字面量赋值

> 什么是字面量?
>
> int a = 10;
>
> 声明一个变量a,初始化为10,此时a就不代表字母a了,而是作为一个变量的名字。当我们引用a的时候,我们实际上拿到的值是10。
>
> 而如果a是带引号的:'a',那么它现在不是一个变量,它就是代表a这个字母本身,这就是字面量。所以字面量没有引申含义,就是我们看到的这个数据本身。

```xml
<!-- 使用value属性给bean的属性赋值时,Spring会把value属性的值看做字面量 -->
<property name="name" value="张三"/>
```

##### ②null值

```xml
<property name="name">
    <null />
</property>
```

> 注意:
>
> ```xml
> <property name="name" value="null"></property>
> ```
>
> 以上写法,为name所赋的值是字符串null

##### ③xml实体

```xml
<!-- 小于号在XML文档中用来定义标签的开始,不能随便使用 -->
<!-- 解决方案一:使用XML实体来代替 -->
<property name="expression" value="a &lt; b"/>
```

##### ④CDATA节

```xml
<property name="expression">
    <!-- 解决方案二:使用CDATA节 -->
    <!-- CDATA中的C代表Character,是文本、字符的含义,CDATA就表示纯文本数据 -->
    <!-- XML解析器看到CDATA节就知道这里是纯文本,就不会当作XML标签或属性来解析 -->
    <!-- 所以CDATA节中写什么符号都随意 -->
    <value><![CDATA[a < b]]></value>
</property>
```


为对象类型属性赋值:

第一种方式:

引入外部bean

1、创建两个类对象:dept和emp

2、在emp的bean标签里面,使用property引入dept的bean

package com.zzq.spring6.iocxml.ditest; //部门类 public class Dept {      private  String dname;      public void setDname(String dname) {         this.dname = dname;     }      public  void info(){         System.out.println("部门名称:"+dname);     } } 
package com.zzq.spring6.iocxml.ditest; //员工类 public class Emp {     //对象类型属性:员工属于某个部门     private Dept dept;     private  String ename;     private Integer age;      public Dept getDept() {         return dept;     }     public  void  work(){         System.out.println(ename+"emp work...."+age);         dept.info();     }     public void setDept(Dept dept) {         this.dept = dept;     }      public String getEname() {         return ename;     }      public void setEname(String ename) {         this.ename = ename;     }      public Integer getAge() {         return age;     }      public void setAge(Integer age) {         this.age = age;     }   } 
package com.zzq.spring6.iocxml.ditest;  import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;  public class TestEmp {     public static void main(String[] args) {       ApplicationContext context=new             ClassPathXmlApplicationContext("bean-ditest.xml");         Emp emp = context.getBean("emp", Emp.class);         emp.work();     } }
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">     <bean id="dept" class="com.zzq.spring6.iocxml.ditest.Dept">         <property name="dname" value="维和部"></property>     </bean>     <bean id="emp" class="com.zzq.spring6.iocxml.ditest.Emp">         <!--普通属性注入-->         <property name="age" value="23"></property>         <property name="ename" value="aa"></property> <!--        注入对象类型属性-->         <property name="dept" ref="dept"></property>     </bean> </beans>

第二种方式:

内部bean的注入

<!--    内部bean注入-->     <bean id="emp2" class="com.zzq.spring6.iocxml.ditest.Emp">         <!--普通属性注入-->         <property name="age" value="2344"></property>         <property name="ename" value="aabbb"></property>         <!--        注入对象类型属性-->         <property name="dept" >             <bean id="dept2" class="com.zzq.spring6.iocxml.ditest.Dept">                 <property name="dname" value="维和部111"></property>             </bean>         </property>     </bean>

 第三种方式:

级联赋值

<!--    第三种方式  级联赋值-->     <bean id="dept3" class="com.zzq.spring6.iocxml.ditest.Dept">         <property name="dname" value="技术研发部"></property>     </bean>     <bean id="emp3" class="com.zzq.spring6.iocxml.ditest.Emp">         <property name="ename" value="Tom"></property>         <property name="age" value="22"></property>         <property name="dept" ref="dept3"></property>         <property name="dept.dname" value="测试部"></property>     </bean>

注入数组类型的属性 

package com.zzq.spring6.iocxml.ditest;  import java.lang.reflect.Array; import java.util.Arrays;  //员工类 public class Emp {     //对象类型属性:员工属于某个部门     private Dept dept;     private String ename;     private Integer age;     private String[] loves;      public void work() {         System.out.println(ename + "emp work...." + age);         dept.info();         System.out.println(Arrays.toString(loves));     }     public void setLoves(String[] loves) {         this.loves = loves;     }      public Dept getDept() {         return dept;     }     public void setDept(Dept dept) {         this.dept = dept;     }      public String getEname() {         return ename;     }      public void setEname(String ename) {         this.ename = ename;     }      public Integer getAge() {         return age;     }      public void setAge(Integer age) {         this.age = age;     }   } 
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--注入数组类型的属性-->     <bean id="dept" class="com.zzq.spring6.iocxml.ditest.Dept">         <property name="dname" value="维和部"></property>     </bean>     <bean id="emp" class="com.zzq.spring6.iocxml.ditest.Emp">         <!--普通属性注入-->         <property name="age" value="23"></property>         <property name="ename" value="aa"></property>         <!--        注入对象类型属性-->         <property name="dept" ref="dept"></property> <!--        数组类型属性-->         <property name="loves">             <array>                 <value>睡觉</value>                 <value>听歌</value>                 <value>追剧</value>             </array>         </property>     </bean> </beans>

为集合类型属性赋值

List集合属性的注入

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">     <bean id="empone" class="com.zzq.spring6.iocxml.ditest.Emp">     <!--普通属性注入-->     <property name="age" value="23"></property>     <property name="ename" value="aa"></property>     </bean>     <bean id="emptwo" class="com.zzq.spring6.iocxml.ditest.Emp">         <!--普通属性注入-->         <property name="age" value="33"></property>         <property name="ename" value="agga"></property>     </bean> <bean id="dept" class="com.zzq.spring6.iocxml.ditest.Dept">     <property name="dname" value="技术部"></property>     <property name="empList">         <list>             <ref bean="empone"></ref>             <ref bean="emptwo"></ref>         </list>     </property> </bean>   </beans>
package com.zzq.spring6.iocxml.ditest;  import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;  public class TestDept {     public static void main(String[] args) {       ApplicationContext context=new             ClassPathXmlApplicationContext("bean-dilist.xml");        Dept dept = context.getBean("dept", Dept.class);         dept.info();     } }
package com.zzq.spring6.iocxml.ditest;  import java.util.List;  //部门类 public class Dept { //一个部门有很多员工     private List<Emp> empList;      public List<Emp> getEmpList() {         return empList;     }      public void setEmpList(List<Emp> empList) {         this.empList = empList;     }      public String getDname() {         return dname;     }      private  String dname;      public void setDname(String dname) {         this.dname = dname;     }      public  void info(){         System.out.println("部门名称:"+dname);         for (Emp emp:empList) {             System.out.println(emp.getEname());         }     } } 

map集合属性的注入

Student类

package com.zzq.spring6.iocxml.dimap;  import java.util.Map;  public class Student {     private String sid;     private String name;     private Map<String, Teacher> teacherMap;      public void run() {         System.out.println("学生编号: " + sid +                 "学生名称: " + name);         System.out.println(teacherMap);     }      @Override     public String toString() {         return "Student{" +                 "sid='" + sid + '\'' +                 ", name='" + name + '\'' +                 ", teacherMap=" + teacherMap +                 '}';     }      public Map<String, Teacher> getTeacherMap() {         return teacherMap;     }      public void setTeacherMap(Map<String, Teacher> teacherMap) {         this.teacherMap = teacherMap;     }      public String getSid() {         return sid;     }      public void setSid(String sid) {         this.sid = sid;     }      public String getName() {         return name;     }      public void setName(String name) {         this.name = name;     } } 

Teacher类

package com.zzq.spring6.iocxml.dimap;  public class Teacher {     private String teacherId;     private String teacherName;      @Override     public String toString() {         return "Teacher{" +                 "teacherId='" + teacherId + '\'' +                 ", teacherName='" + teacherName + '\'' +                 '}';     }      public String getTeacherId() {         return teacherId;     }      public void setTeacherId(String teacherId) {         this.teacherId = teacherId;     }      public String getTeacherName() {         return teacherName;     }      public void setTeacherName(String teacherName) {         this.teacherName = teacherName;     } } 

package com.zzq.spring6.iocxml.dimap;  import org.junit.jupiter.api.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;  public class TestStu {     @Test     public void testStu(){         ApplicationContext context=new                 ClassPathXmlApplicationContext("bean-dimap.xml");         Student student = context.getBean("student", Student.class);         student.run();     } } 
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="student" class="com.zzq.spring6.iocxml.dimap.Student">     <property name="name" value="aa"></property>     <property name="sid" value="111"></property>     <property name="teacherMap">         <map>             <entry>                 <key>                     <value>10001</value>                 </key>                 <ref bean="teacherone"></ref>             </entry>             <entry>                 <key>                     <value>10099</value>                 </key>                 <ref bean="teachertwo"></ref>             </entry>         </map>     </property> </bean>     <bean id="teacherone" class="com.zzq.spring6.iocxml.dimap.Teacher">         <property name="teacherId" value="22"></property>         <property name="teacherName" value="王五"></property>     </bean>     <bean id="teachertwo" class="com.zzq.spring6.iocxml.dimap.Teacher">         <property name="teacherId" value="22"></property>         <property name="teacherName" value="王五"></property>     </bean> </beans>

引入集合类型的bean

1、创建三个对象

2、注入普通类型属性

3、使用util:类型 定义

4、在学生bean引入util:类型定义bean,完成list、map类型属性注入

lesson

package com.zzq.spring6.iocxml.dimap;  public class Lesson {     private String lessonName;      @Override     public String toString() {         return "Lesson{" +                 "lessonName='" + lessonName + '\'' +                 '}';     }      public String getLessonName() {         return lessonName;     }      public void setLessonName(String lessonName) {         this.lessonName = lessonName;     } } 
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"        xmlns:util="http://www.springframework.org/schema/util"        xsi:schemaLocation="http://www.springframework.org/schema/util         http://www.springframework.org/schema/util/spring-util.xsd                http://www.springframework.org/schema/beans     http://www.springframework.org/schema/beans/spring-beans.xsd">       <bean id="student" class="com.zzq.spring6.iocxml.dimap.Student">         <property name="name" value="lucy"></property>         <property name="sid" value="111"></property> <!--        注入list map类型属性-->         <property name="lessonList" ref="lessonList"></property>         <property name="teacherMap" ref="teacherMap"></property>     </bean> <util:list id="lessonList">     <ref bean="lessonone"></ref>     <ref bean="lessontwo"></ref> </util:list>     <util:map id="teacherMap">         <entry>             <key>                 <value>10001</value>             </key>             <ref bean="teacherone"></ref>         </entry>         <entry>             <key>                 <value>1208</value>             </key>             <ref bean="teachertwo"></ref>         </entry>     </util:map>      <bean id="lessonone" class="com.zzq.spring6.iocxml.dimap.Lesson">         <property name="lessonName" value="java开发"></property>     </bean>     <bean id="lessontwo" class="com.zzq.spring6.iocxml.dimap.Lesson">         <property name="lessonName" value="前端开发"></property>     </bean>     <bean id="teacherone" class="com.zzq.spring6.iocxml.dimap.Teacher">         <property name="teacherId" value="2201"></property>         <property name="teacherName" value="王五"></property>     </bean>     <bean id="teachertwo" class="com.zzq.spring6.iocxml.dimap.Teacher">         <property name="teacherId" value="2200"></property>         <property name="teacherName" value="刘五"></property>     </bean> </beans>

引入p命名空间

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"        xmlns:util="http://www.springframework.org/schema/util"        xmlns:p="http://www.springframework.org/schema/p"        xsi:schemaLocation="http://www.springframework.org/schema/util         http://www.springframework.org/schema/util/spring-util.xsd                http://www.springframework.org/schema/beans     http://www.springframework.org/schema/beans/spring-beans.xsd">     <!--p命名空间得到注入-->     <bean id="studentp" class="com.zzq.spring6.iocxml.dimap.Student"           p:sid="111" p:name="流水" p:lessonList-ref="lessonList" p:teacherMap-ref="teacherMap">      </bean>      <bean id="student" class="com.zzq.spring6.iocxml.dimap.Student">         <property name="name" value="lucy"></property>         <property name="sid" value="111"></property>         <!--        注入list map类型属性-->         <property name="lessonList" ref="lessonList"></property>         <property name="teacherMap" ref="teacherMap"></property>     </bean>     <util:list id="lessonList">         <ref bean="lessonone"></ref>         <ref bean="lessontwo"></ref>     </util:list>     <util:map id="teacherMap">         <entry>             <key>                 <value>10001</value>             </key>             <ref bean="teacherone"></ref>         </entry>         <entry>             <key>                 <value>1208</value>             </key>             <ref bean="teachertwo"></ref>         </entry>     </util:map>      <bean id="lessonone" class="com.zzq.spring6.iocxml.dimap.Lesson">         <property name="lessonName" value="java开发"></property>     </bean>     <bean id="lessontwo" class="com.zzq.spring6.iocxml.dimap.Lesson">         <property name="lessonName" value="前端开发"></property>     </bean>     <bean id="teacherone" class="com.zzq.spring6.iocxml.dimap.Teacher">         <property name="teacherId" value="2201"></property>         <property name="teacherName" value="王五"></property>     </bean>     <bean id="teachertwo" class="com.zzq.spring6.iocxml.dimap.Teacher">         <property name="teacherId" value="2200"></property>         <property name="teacherName" value="刘五"></property>     </bean> </beans>
package com.zzq.spring6.iocxml.dimap;  import org.junit.jupiter.api.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;  public class TestStu {     @Test     public void testStu(){         ApplicationContext context=new                 ClassPathXmlApplicationContext("bean-diref.xml");         Student student = context.getBean("studentp", Student.class);         student.run();     } } 

引入外部属性文件

引入依赖

 <!-- MySQL驱动 --> <dependency>     <groupId>mysql</groupId>     <artifactId>mysql-connector-java</artifactId>     <version>8.0.30</version> </dependency>  <!-- 数据源 --> <dependency>     <groupId>com.alibaba</groupId>     <artifactId>druid</artifactId>     <version>1.2.15</version> </dependency>

创建外部属性文件

jdbc.user=root jdbc.password=root jdbc.url=jdbc:mysql://localhost:3306/spring?serverTimezone=UTC jdbc.driver=com.mysql.cj.jdbc.Driver 

配置bean

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"        xmlns:context="http://www.springframework.org/schema/context"        xsi:schemaLocation="http://www.springframework.org/schema/context        http://www.springframework.org/schema/context/spring-context.xsd        http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--引入外部属性文件-->     <context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder> <!--    完成数据库信息的注入-->     <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">         <property name="url" value="${jdbc.url}"></property>         <property name="username" value="${jdbc.user}"></property>         <property name="password" value="${jdbc.password}"></property>         <property name="driverClassName" value="${jdbc.driver}"></property>     </bean> </beans>

测试

package com.zzq.spring6.iocxml.jdbc;  import com.alibaba.druid.pool.DruidDataSource; import org.junit.jupiter.api.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;  public class TestJdbc {     @Test     public void demo1() {         DruidDataSource dataSource = new DruidDataSource();         dataSource.setUrl("jdbc:mysql://localhost:3306/spring?serverTimezone=UTC");         dataSource.setUsername("root");         dataSource.setPassword("root");         dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");      }     @Test     public void  demo2(){         ApplicationContext context=new                 ClassPathXmlApplicationContext("bean-jdbc.xml");         DruidDataSource dataSource = context.getBean(DruidDataSource.class);         System.out.println(dataSource.getUrl());     } } 

bean的作用域

bean的生命周期

package com.zzq.spring6.iocxml.life;  public class User {     private String name; //无参构造     public User() {         System.out.println("1 bean对象创建,调用无参构造");     } //初始化方法     public void  initMethod(){         System.out.println("4、bean对象初始化,调用指定的初始化方法");     }     //销毁的方法     public void destroyMethod(){         System.out.println("7、bean对象销毁,调用指定的销毁方法");     }     public String getName() {         return name;     }      public void setName(String name) {         System.out.println("2 给bean对象设置属性值");         this.name = name;     } } 
package com.zzq.spring6.iocxml.life;  import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.lang.Nullable;  public class MyBeanPost implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {     System.out.println("3、bean后置处理器,初始化之前执行");     System.out.println(beanName+"::"+bean);         return bean;     } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {     System.out.println("5、bean后置处理器,初始化之后执行");     System.out.println(beanName+"::"+bean);     return bean;     } } 
package com.zzq.spring6.iocxml.life;  import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;  public class TestUser {     public static void main(String[] args) {         ClassPathXmlApplicationContext context=new                 ClassPathXmlApplicationContext("bean-life.xml");         User user = context.getBean("user", User.class);         System.out.println("6  bean对象创建完成,可以使用");         System.out.println(user);         context.close();//销毁对象     } } 
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="user" class="com.zzq.spring6.iocxml.life.User" scope="singleton" init-method="initMethod" destroy-method="destroyMethod" >     <property name="name" value="lucy"></property> </bean> <!--    bean的后置处理器要放入IOC容器才能生效-->     <bean id="myBeanPost" class="com.zzq.spring6.iocxml.life.MyBeanPost"></bean> </beans>

FactoryBean

 FactoryBean是Spring提供的一种整合第三方框架的常用机制。和普通的bean不同,配置一个FactoryBean类型的bean,在获取bean的时候得到的并不是class属性中配置的这个类的对象,而是getObject()方法的返回值。通过这种机制,Spring可以帮我们把复杂组件创建的详细过程和繁琐细节都屏蔽起来,只把最简洁的使用界面展示给我们。

将来我们整合Mybatis时,Spring就是通过FactoryBean机制来帮我们创建SqlSessionFactory对象的。

package com.zzq.spring6.iocxml.factorybean;  import org.springframework.beans.factory.FactoryBean;  public class MyFactoryBean implements FactoryBean<User> {     @Override     public User getObject() throws Exception {         return new User();     }      @Override     public Class<?> getObjectType() {         return User.class;     } } 
package com.zzq.spring6.iocxml.factorybean;  import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;  public class TestUser {     public static void main(String[] args) {         ApplicationContext context=new                 ClassPathXmlApplicationContext("bean-factorybean.xml");        User user =(User) context.getBean("user");         System.out.println(user);     } } 
package com.zzq.spring6.iocxml.factorybean;  public class User { } 
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="user" class="com.zzq.spring6.iocxml.factorybean.MyFactoryBean"></bean> </beans>

基于xml自动装配

package com.zzq.spring6.iocxml.auto.controller;  import com.zzq.spring6.iocxml.auto.service.UserService; import com.zzq.spring6.iocxml.auto.service.UserSeviceImpl;  public class UserController {     private UserService userService;      public void setUserService(UserService userService) {         this.userService = userService;     }      public void addUser(){         System.out.println("controller方法执行了");         //调用service的方法         userService.addUserService(); //        UserService userService=new UserSeviceImpl(); //        userService.addUserService();     } } 
package com.zzq.spring6.iocxml.auto.service;  public interface UserService {     public void addUserService(); } 
package com.zzq.spring6.iocxml.auto.service;  import com.zzq.spring6.iocxml.auto.dao.UserDao; import com.zzq.spring6.iocxml.auto.dao.UserDaoImpl;  public class UserSeviceImpl implements UserService {     private  UserDao userDao;      public void setUserDao(UserDao userDao) {         this.userDao = userDao;     }      @Override     public void addUserService() {         System.out.println("userService方法执行了");         userDao.addUserDao(); //        UserDao userDao=new UserDaoImpl(); //        userDao.addUserDao();     } } 
package com.zzq.spring6.iocxml.auto.dao;  public class UserDaoImpl implements UserDao {     @Override     public void addUserDao(){         System.out.println("userDao方法执行了");     } } 
package com.zzq.spring6.iocxml.auto.dao;  import com.zzq.spring6.iocxml.auto.service.UserService;  public interface UserDao { public void addUserDao();  } 
package com.zzq.spring6.iocxml.auto;  import com.zzq.spring6.iocxml.auto.controller.UserController; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;  public class TestUser {     public static void main(String[] args) {         ApplicationContext context=new                 ClassPathXmlApplicationContext("bean-auto.xml");         UserController controller = context.getBean("userController", UserController.class);         controller.addUser();     } } 
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">  <!--    根据类型自动装配-->  <!--    <bean id="userController" class="com.zzq.spring6.iocxml.auto.controller.UserController" autowire="byType"></bean>--> <!--<bean id="userService" class="com.zzq.spring6.iocxml.auto.service.UserSeviceImpl" autowire="byType"></bean>--> <!--<bean id="userDao" class="com.zzq.spring6.iocxml.auto.dao.UserDaoImpl"></bean>--> <!--    根据名称自动装配-->     <bean id="userController" class="com.zzq.spring6.iocxml.auto.controller.UserController" autowire="byName"></bean>     <bean id="userService" class="com.zzq.spring6.iocxml.auto.service.UserSeviceImpl" autowire="byName"></bean>     <bean id="userDao" class="com.zzq.spring6.iocxml.auto.dao.UserDaoImpl"></bean> </beans>

自动装配方式:byName
>
> byName:将自动装配的属性的属性名,作为bean的id在IOC容器中匹配相对应的bean进行赋值

基于注解管理Bean

开启组件扫描

<beans xmlns="http://www.springframework.org/schema/beans"        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"        xmlns:context="http://www.springframework.org/schema/context"        xsi:schemaLocation="         http://www.springframework.org/schema/context        http://www.springframework.org/schema/context/spring-context.xsd        http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--开启组件扫描--> <context:component-scan base-package="com.zzq"></context:component-scan> </beans>

情况一:最基本的扫描方式**

```xml
<context:component-scan base-package="com.atguigu.spring6">
</context:component-scan>
```

**情况二:指定要排除的组件**

```xml
<context:component-scan base-package="com.atguigu.spring6">
    <!-- context:exclude-filter标签:指定排除规则 -->
    <!-- 
         type:设置排除或包含的依据
        type="annotation",根据注解排除,expression中设置要排除的注解的全类名
        type="assignable",根据类型排除,expression中设置要排除的类型的全类名
    -->
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        <!--<context:exclude-filter type="assignable" expression="com.atguigu.spring6.controller.UserController"/>-->
</context:component-scan>
```

**情况三:仅扫描指定组件**

```xml
<context:component-scan base-package="com.atguigu" use-default-filters="false">
    <!-- context:include-filter标签:指定在原有扫描规则的基础上追加的规则 -->
    <!-- use-default-filters属性:取值false表示关闭默认扫描规则 -->
    <!-- 此时必须设置use-default-filters="false",因为默认规则即扫描指定包下所有类 -->
    <!-- 
         type:设置排除或包含的依据
        type="annotation",根据注解排除,expression中设置要排除的注解的全类名
        type="assignable",根据类型排除,expression中设置要排除的类型的全类名
    -->
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    <!--<context:include-filter type="assignable" expression="com.atguigu.spring6.controller.UserController"/>-->
</context:component-scan>
```

bean对象的创建

以上四个注解都可实现bean的创建

package com.zzq.bean;  import org.springframework.stereotype.Component; import org.springframework.stereotype.Controller; import org.springframework.stereotype.Repository; import org.springframework.stereotype.Service;  @Component(value = "user")//<bean id="user" class="...">属性可不写,默认为user //@Controller //@Repository //@Service public class User { } 

属性注入

单独使用@Autowired注解,**默认根据类型装配**。【默认是byType】

package com.zzq.autowired.controller;  import com.zzq.autowired.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller;  @Controller public class UserController {     //注入service     //第一种方式属性的注入     @Autowired//根据类型找到对应对象,完成注入     private UserService userService;      public  void add(){         System.out.println("controller...");         userService.add();     } } 
package com.zzq.autowired.service;  import com.zzq.autowired.dao.UserDao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service;  @Service public class UserServiceImpl implements UserService{     //注入dao      //第一种方式属性注入 //@Autowired //    private UserDao userDao;      //第二种方式set方法注入 //    @Autowired //    private UserDao userDao; // //    public void setUserDao(UserDao userDao) { //        this.userDao = userDao; //    }      //第三种方式:构造方法中注入   private UserDao userDao; @Autowired     public UserServiceImpl(UserDao userDao) {         this.userDao = userDao;     }      @Override     public void add() {         System.out.println("service...");         userDao.add();     } } 
package com.zzq.autowired.controller;  import com.zzq.autowired.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller;  @Controller public class UserController {     //注入service     //第一种方式属性的注入 //    @Autowired//根据类型找到对应对象,完成注入 //    private UserService userService;      //第二种方式set方法注入 //    private UserService userService; //@Autowired //    public void setUserService(UserService userService) { //        this.userService = userService; //    }     //第三种方式 构造方法的注入 //    private UserService userService; //@Autowired //    public UserController(UserService userService) { //        this.userService = userService; //    }      //第四种方式     private UserService userService;      public UserController( @Autowired UserService userService) {         this.userService = userService;     }      public  void add(){         System.out.println("controller...");         userService.add();     } } 

@Autowired注解可以出现在:属性上、构造方法上、构造方法的参数上、setter方法上。
- 当带参数的构造方法只有一个,@Autowired注解可以省略。()
- @Autowired注解默认根据类型注入。如果要根据名称注入的话,需要配合@Qualifier注解一起使用。

@Resource注入

@Resource注解也可以完成属性注入。那它和@Autowired注解有什么区别?

- @Resource注解是JDK扩展包中的,也就是说属于JDK的一部分。所以该注解是标准注解,更加具有通用性。(JSR-250标准中制定的注解类型。JSR是Java规范提案。)
- @Autowired注解是Spring框架自己的。
- **@Resource注解默认根据名称装配byName,未指定name时,使用属性名作为name。通过name找不到的话会自动启动通过类型byType装配。**
- **@Autowired注解默认根据类型装配byType,如果想根据名称装配,需要配合@Qualifier注解一起用。**
- @Resource注解用在属性上、setter方法上。
- @Autowired注解用在属性上、setter方法上、构造方法上、构造方法参数上。

@Resource注解属于JDK扩展包,所以不在JDK当中,需要额外引入以下依赖:【**如果是JDK8的话不需要额外引入依赖。高于JDK11或低于JDK8需要引入以下依赖。**】

<dependency>     <groupId>jakarta.annotation</groupId>     <artifactId>jakarta.annotation-api</artifactId>     <version>2.1.1</version> </dependency>

package com.zzq.resource.controller;  import com.zzq.resource.service.UserService; import jakarta.annotation.Resource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller;  @Controller("myUserController") public class UserController {     //根据名称进行注入 //@Resource(name = "myUserService") //private UserService userService;     //根据类型进行注入     @Resource     private UserService userService;      public  void add(){         System.out.println("controller...");        userService.add();     } } 

Spring全注解开发

package com.zzq.config;  import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration;  @Configuration//配置类 @ComponentScan("com.zzq")//开启组件扫描 public class SpringConfig { } 
package com.zzq.resource;  import com.zzq.config.SpringConfig; import com.zzq.resource.controller.UserController; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;  public class TestUserControllerAnno {     public static void main(String[] args) {         //加载配置类        ApplicationContext context=                new AnnotationConfigApplicationContext(SpringConfig.class);         UserController controller = context.getBean(UserController.class);         controller.add();     }  }

java反射机制

package com.zzq;  import org.junit.jupiter.api.Test;  import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method;  public class TestCar {     //1、获取clas对象多种方式      @Test     public void test01() throws Exception { //1、类名.class         Class clazz1 = Car.class;         //2、对象.getclass()         Class clazz2 = new Car().getClass();         //3、Class.forname("全路径")         Class clazz3 = Class.forName("com.zzq.Car"); //实例化         Car car = (Car) clazz3.getDeclaredConstructor().newInstance();         System.out.println(car);     }      //2、通过反射获取构造方法     @Test     public void test02() throws Exception {         Class clazz = Car.class;         //获取所有构造         Constructor[] constructors = clazz.getConstructors();         for (Constructor c : constructors) {             System.out.println("方法个数" + c.getName() + "参数个数" + c.getParameterCount());          }         //指定有参数构造创建对象         //1、构造public //    Constructor c1=clazz.getConstructor(String.class,int.class, String.class); //    Car car1 = (Car)c1.newInstance("本部", 10, "黄色"); //    System.out.println(car1);         //2、构造private         Constructor c2 = clazz.getDeclaredConstructor(String.class, int.class, String.class);         c2.setAccessible(true);         Car car2 = (Car) c2.newInstance("部", 11, "黄色");         System.out.println(car2);     }      //3、获取属性     @Test     public void test03() throws Exception {         Class clazz = Car.class;         //实例化         Car car = (Car) clazz.getDeclaredConstructor().newInstance();         //获取所有的public属性         //    Field[]fields=clazz.getFields();         //获取所有属性(包含私有属性)         Field[] fields = clazz.getDeclaredFields();         for (Field field : fields) {             if (field.getName().equals("name")) {                 field.setAccessible(true);                 field.set(car, "奥迪");             }             System.out.println(field.getName());             System.out.println(car);         }          }     //4、获取方法     @Test     public void test04() throws Exception { Car car=new Car("宝马",19,"黑色"); Class clazz=car.getClass(); //public方法         Method[]methods=clazz.getMethods();         for (Method m1:methods              ) {           //  System.out.println(m1.getName());             //执行方法toString             if (m1.getName().equals("toString")){                 String invoke=(String) m1.invoke(car);               //  System.out.println("toString执行了:"+invoke);         }             //private方法             Method[] methodsAll = clazz.getDeclaredMethods();             for (Method m:methodsAll){                 if (m.getName().equals("run")){                     m.setAccessible(true);                     m.invoke(car);                 }               }         }      }     } 

实现Spring的IoC

ApplicationContext.java

package com.zzq.Bean;  import com.zzq.anno.Bean;  public interface ApplicationContext {      Object getBean(Class clazz); } 

AnnotationApplicationContext.java

package com.zzq.Bean;  import com.zzq.anno.Bean; import com.zzq.anno.Di;  import java.io.File; import java.lang.reflect.Field; import java.net.URL; import java.net.URLDecoder; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import java.util.Set;  public class AnnotationApplicationContext implements ApplicationContext {     //创建map集合,放bean对象     private   Map<Class, Object> beanFactory = new HashMap<>();       private static String rootPath;      //返回对象     @Override     public Object getBean(Class clazz) {         return beanFactory.get(clazz);     }      //设置包扫描规则     //当前包及其子包,拿个类有@Bean注解,把这个类通过反射实例化      public AnnotationApplicationContext(String basePackage) {    // public static void pathdemo1(String basePackage) {         //把.替换成\         try {             String packagePath = basePackage.replaceAll("\\.", "\\\\");             //获取包绝对路径             Enumeration<URL> urls = Thread.currentThread().getContextClassLoader().getResources(packagePath);             while (urls.hasMoreElements()) {                 URL url = urls.nextElement();                 String filePath = URLDecoder.decode(url.getFile(), "utf-8");                 //获取包前面路径得到部分,字符串截取                   rootPath = filePath.substring(0, filePath.length() - packagePath.length());                 //包扫描                   loadBean(new File(filePath));             }         } catch (Exception e) {             throw new RuntimeException(e);         }         //属性得到注入          loadDi();     }       //    //包扫描的过程,实例化    private  void loadBean(File file) throws Exception {        //1、判断当前是否文件夹        if (file.isDirectory()) {            //2、获取文件夹里面所有内容            File[] childrenFiles = file.listFiles();            //3、判断文件夹里面为空,直接返回            if (childrenFiles == null || childrenFiles.length == 0) {                return;            }            //4、如果文件夹里面不为空,遍历文件夹所有内容            for (File child : childrenFiles) {                //4.1遍历得到某个File对象,继续判断,如果还是文件,                if (child.isDirectory()) {                    //递归                    loadBean(child);                } else {                    //4.2遍历得到File对象不是文件夹,是文件                    //4.3得到包路径+类名称部分-字符串截取                    String pathWithClass = child.getAbsolutePath().substring(rootPath.length() - 1);                    //4.4判断当前文件类型是否.class                    if (pathWithClass.contains(".class")) {                        //4.5如果是.class类型,把路径\替换. 把class去掉                        String allName = pathWithClass.replaceAll("\\\\", ".")                                .replace(".class", "");                        //4.6判断类上面是否有注解@Bean,如果有实例化过程                        //4.6.1获取类发class                        Class<?> clazz = Class.forName(allName);                        //4.6.2判断不是接口                        if (!clazz.isInterface()) {                            //4.6.3判断类上面是否有注解@Bean                            Bean annotation = clazz.getAnnotation(Bean.class);                            if ((annotation != null)) {                                //4.6.4实例化                                Object instance = clazz.getConstructor().newInstance();                                //4.7把对象实例化之后,放到map集合beanFactory                                //4.7.1判断当前类如果有接口,让接口class作为map的key                                if (clazz.getInterfaces().length > 0) {                                    beanFactory.put(clazz.getInterfaces()[0], instance);                                } else {                                    beanFactory.put(clazz, instance);                                }                            }                        }                    }                }            }         }     } //属性注入     private void loadDi()  {         //实例化对象在beanFactory的map集合里面         //1、遍历beanFactory的map集合         Set<Map.Entry<Class,Object>>entries=beanFactory.entrySet();         for (Map.Entry<Class,Object>entry:entries) { //2、获取map集合每个对象(value),每个对象属性获取到             Object obj=entry.getValue();             //获取对象Class                 Class<?> clazz=obj.getClass();         //获取每个对象的属性             Field[] declaredFields = clazz.getDeclaredFields();             //遍历得到每个对象属性数组,得到每个属性             for (Field field:declaredFields) {                 //4、判断属性上面是否有@Di注解                 Di annotation = field.getAnnotation(Di.class);                 if (annotation != null) {                     //如果私有属性,设置可以设置值                     field.setAccessible(true);                     //5、如果有@Di注解,把对象进行设置(注入)                     try {                         field.set(obj, beanFactory.get(field.getType()));                     }catch (IllegalAccessException e){                         throw new RuntimeException(e);                     }                 }             }         }     }  } 
package com.zzq.anno;  import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;  @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface Bean { } 
package com.zzq.anno;  import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;  @Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface Di { } 
package com.zzq;  import com.zzq.Bean.AnnotationApplicationContext; import com.zzq.Bean.ApplicationContext; import com.zzq.service.UserService;  public class TestUser {     public static void main(String[] args)  {       ApplicationContext context=               new AnnotationApplicationContext("com.zzq");         UserService userService  = (UserService)context.getBean(UserService.class);         System.out.println(userService);         userService.add();     } } 

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!