IOC之abstract抽象Bean

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

abstract="true"属性可以设置一个bean对象的配置只是配置信息,而不能被初始化。给其他bean做继承之用。

修改applicationContext.xml配置中的内容

   <!-- 先定义一个base的 person对象 -->   <bean id="base" class="com.xypuxing.pojo.Person" p:name="basePerson"p:age="18"p:id="12312"abstract="true"/>

   <!-- 然后在另一个bean中。使用parent继承所有的 -->

   <bean id="person20" class="com.xypuxing.pojo.Person" parent="base"p:id="20"/>

常见错误:abstract="true"bean不能被创建

Spring笔记本(2)

IOC之组件创建顺序

实验20:bean之间的依赖

创建三个Bean

publicclass A {

   public A() {

      System.out.println("创建A");

   }

}

publicclass B {

   public B() {

      System.out.println("创建B");

   }

}

publicclass C {

   public C() {

      System.out.println("创建C");

   }

}

applicationContext.xml中的配置

   <beanid="a"class="com.xypuxing.pojo.A"/>

   <beanid="b"class="com.xypuxing.pojo.B"/>

   <beanid="c"class="com.xypuxing.pojo.C"/>

执行ApplicationContextapplicationContext = newClassPathXmlApplicationContext("applicationContext.xml");代码

执行结果,会发现。顺序情况下。Bean的创建顺序是他们在applicationContext.xml中从上到下的配置顺序。

运行结果:

Spring笔记本(2)

我们可以在bean中添加depends-on来修改Bean的依赖。从而修改他们创建的顺序。

   <!-- depends-on 表示依赖顺序,就是说,在创建a之前,要先有b和c。所以使得bean的创建顺序是先创建b和c之后再创建a -->

   <beanid="a"class="com.xypuxing.pojo.A"depends-on="b,c"/>

   <beanid="b"class="com.xypuxing.pojo.B"/>

   <bean id="c" class="com.xypuxing.pojo.C" />

 

这个时候,再执行上面的测试,bean的创建顺序会发生变化

Spring笔记本(2)

IOCBean的单例和多例(重点)

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

前面我们讲到的bean对象都是单例,且在ApplicationContext创建的时候,就会被初始化实例。

其实我们可以通过修改Bean标签中的scope=""属性来修改对象的单例多例(生命范围)

scope的值可以有

singleton    单例   applicationContext对象创建的时候都创建好。

prototype    多例

request     一次请求,一个对象实例(保存到Request域对象中)

session     一个Session,一个对象实例(保存到Session域对象中)

修改4.22实例中的三个bean配置

 <!--

      scope 属性,修改对象的存活范围

         singleton表示全局只有一个 对象实例,并且在ApplicationContext对象创建的时候创建好。

         prototype表示每次调用getBean的时候创建。

         request表示一次请求,就会创建一个对象实例。

         session表示一个会话,就会创建一个对象实例。

    -->

   <bean id="a" class="com.xypuxing.pojo.A" scope="singleton"/>

   <bean id="b" class="com.xypuxing.pojo.B" scope="singleton"/>

    <bean id="c" class="com.xypuxing.pojo.C" scope="prototype"/>


测试代码

   @Test

   publicvoid test21() {

      ApplicationContext applicationContext = newClassPathXmlApplicationContext(

            "applicationContext.xml");

      System.out.println("application创建好之后*************");

      System.out.println( applicationContext.getBean("c") );

      System.out.println( applicationContext.getBean("c") );

   }

 

运行的结果

Spring笔记本(2)

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

自动装配是根据autowire配置的值决定有,byName根据名称装配。byType根据类型装配。constructor根据构造方法装配

 

 

先创建Person类和Car类

publicclass Car {

 

   private String name;

 

publicclass Person {

 

   private Car car;

 

   public Person(Car car) {

      this.car = car;

   }

 

 

 

在applicationContext.xml中配置如下:

   <bean id="car1" class="com.xypuxing.pojo.Car" p:name="这是Car实例1"/>

   <bean id="car" class="com.xypuxing.pojo.Car" p:name="这是Car实例"/>

   <!--

      autowire自动注入(自动装配)

         default 默认表示不装配

         no 也表示不装配

         byName 会自动的根据 属性名 找到 id跟属性名相同的 bean对象注入

         byType 会自动的根据 属性的类型找到 同类型的bean对象注入。但是如果有多个就会报错。

         constructor 会自动的先根据类型来查找。如果只有一个类型匹配就注入。

            如果有多个类型匹配。就再次按照id来查找。如果匹配就注入。

    -->

   <bean id="person" class="com.xypuxing.pojo.Person" autowire="constructor"/>

 

 

测试的代码

   @Test

   publicvoid test22() {

      ApplicationContext ctx= newClassPathXmlApplicationContext("applicationContext.xml");

      Person person = (Person)ctx.getBean("person");

      System.out.println( person );

   }

 

运行结果


Spring笔记本(2)

测试byName或byType可自行修改autowire的值进行测试。

 

如果在测试byType的时候,有多个相同的类型。就会报如下错误:


Spring笔记本(2)

IOC之Bean的生命周期

实验22:创建带有生命周期方法的bean

 

给B类添加初始化方法和销毁方法

publicclass B {

   public B() {

      System.out.println("创建B");

   }

  

   publicvoid initB() {

      System.out.println("初始化 B 对象……");

   }

  

   publicvoid destroyB() {

      System.out.println("销毁 B 对象……");

   }

}

 

applicationContext.xml中的配置

   <!--

      init-method="initB"表示当对象实例化之后,设置完属性值之后。就调用initB初始化方法

      destroy-method="destroyB"表示当applicationContext关闭的时候就调用 destroyB 销毁方法

    -->

   <bean id="b" class="com.xypuxing.pojo.B" scope="singleton"init-method="initB"destroy-method="destroyB"/>

 

测试的代码

   @Test

   publicvoid test21() {

      ConfigurableApplicationContextapplicationContext = newClassPathXmlApplicationContext(

            "applicationContext.xml");

      System.out.println("application创建好之后*************");

      applicationContext.close();

   }


Spring笔记本(2)

Bean的后置处理器BeanPostProcessor

实验23:测试bean的后置处理器

 

编写一个类去实现BeanPostProcessor接口

publicclass MyBeanPostProcessor implements BeanPostProcessor {

 

   /**

    * 这是初始化之前执行

    */

   @Override

   public ObjectpostProcessBeforeInitialization(Object bean, String beanName)

         throws BeansException {

      System.out.println("在对象初始化之前……执行 ===== bean的名称是:" + beanName);

      return bean;

   }

 

   /**

    * 这是初始化之后执行

    */

   @Override

   public Object postProcessAfterInitialization(Objectbean, String beanName)

         throws BeansException {

      System.out.println("在对象初始化之后……执行 ===== bean的名称是:" + beanName);

      return bean;

   }

}

 

B类的代码

publicclass B {

   public B() {

      System.out.println("创建B");

   }

  

   publicvoid initB() {

      System.out.println("初始化 B 对象……");

   }

  

   publicvoid destroyB() {

      System.out.println("销毁 B 对象……");

   }

}

 

新创建一个applicationContext.xml配置文件。

   <!-- 配置一个b对象,并配置初始化方法和销毁方法 -->

   <bean id="b" class="com.xypuxing.pojo.B" init-method="initB"destroy-method="destroyB"/>

   <!-- 配置后置处理器对象 -->

   <bean class="com.xypuxing.pojo.factory.MyBeanPostProcessor">

 

执行代码

   @Test

   publicvoid test22() {

      ApplicationContextapplicationContext = newClassPathXmlApplicationContext(

            "applicationContext.xml");

      B b =(B) applicationContext.getBean("b");

      System.out.println(b);

   }

 

执行结果


Spring笔记本(2)

Spring配置管理数据库连接池对象(重点)

首先在工程中导入jar包


Spring笔记本(2)

在applicationContext.xml中配置数据库连接池对象

   <!-- 配置C3p0数据库连接池 -->

   <bean id="c3p0DataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">

      <property name="user" value="root" />

      <property name="password" value="root" />

      <property name="driverClass" value="com.mysql.jdbc.Driver"/>

      <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/xypuxing"/>

   </bean>

 

测试获取数据库连接代码

   @Test

   publicvoid testDataSource() throws Exception {

      ApplicationContextapplicationContext = newClassPathXmlApplicationContext("applicationContext.xml");

      DataSourcedataSource = (DataSource) applicationContext.getBean("c3p0DataSource");

      System.out.println(dataSource.getConnection());

   }

 

运行结果


Spring笔记本(2)

Spring引入单独的jdbc.properties配置文件(重点)

实验24:引用外部属性配置文件★

 

在src目录下创建一个jdbc.properties属性配置文件

user=root

password=root

driverClass=com.mysql.jdbc.Driver

url=jdbc:mysql://localhost:3306/xypuxing

注意:一定要记得修改你自己的数据库连接参数

 

在applicationContext.xml配置文件中使用org.springframework.beans.factory.config.PropertyPlaceholderConfigurer进行加载配置

   <!-- 实际情况,记得根据自己的情况==修改jdbc.properties中的属性信息。 -->

   <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"p:location="classpath:jdbc.properties"/>

 

   <!-- 配置C3p0数据库连接池 -->

   <bean id="c3p0DataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"destroy-method="close">

      <property name="user" value="${user}" />

      <property name="password" value="${password}" />

      <property name="driverClass" value="${driverClass}"/>

      <property name="jdbcUrl" value="${url}" />

   </bean>

 

测试的代码

   @Test

   publicvoid testDataSource() throws Exception {

      ApplicationContext applicationContext= newClassPathXmlApplicationContext(

            "applicationContext.xml");

      DataSourcedataSource = (DataSource) applicationContext.getBean("c3p0DataSource");

      System.out.println(dataSource.getConnection());

   }

 

测试结果


Spring笔记本(2)

使用context名称空间加载jdbc.properties配置文件(重点)

在新的Spring版本中,都优先使用Context名称空间加载属性配置文件

 

修改applicationContext.xml中的名称空间,添加context名称空间


Spring笔记本(2)

修改原来的jdbc.properties配置文件,添加jdbc前缀

jdbc.username=root

jdbc.password=root

jdbc.driverClass=com.mysql.jdbc.Driver

jdbc.url=jdbc:mysql://localhost:3306/xypuxing

 

 

修改applicationContext.xml配置文件中的代码

   <!-- 使用context名称空间,加载jdbc.properties配置文件 -->

   <context:property-placeholder location="classpath:jdbc.properties"/>

 

   <!-- 配置C3p0数据库连接池 -->

   <bean id="c3p0DataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"destroy-method="close">

      <property name="user" value="${jdbc.username}" />

      <property name="password" value="${jdbc.password}" />

      <property name="driverClass" value="${jdbc.driverClass}"/>

      <property name="jdbcUrl" value="${jdbc.url}" />

   </bean>


6、Spring EL表达式(了解内容

 

 

创建java实体Bean对象

publicclass Person {

 

   privateintid;

   private String name;

   private String phone;

   privatedoublesalary;

   private Car car;

 

 

publicclass Car {

 

   private String name;

   private String carNo;

 

 

实验26:[SpEL测试I]在SpEL中使用字面量

 

使用格式:#{数值}                #{“字符串” || ‘字符串’}

 

实验27:[SpEL测试II]在SpEL中引用其他bean

 

使用格式:#{bean的id}

 

实验28:[SpEL测试III]在SpEL中引用其他bean的某个属性值

 

使用格式: #{bean.属性名}

 

实验29:[SpEL测试IV]在SpEL中调用非静态方法

 

使用格式: #{bean.方法名(参数)}

 

实验30:[SpEL测试V]在SpEL中调用静态方法

 

使用格式:#{T(全名类).方法名(参数)}

 

实验31:[SpEL测试VI]在SpEL中使用运算符

 

使用格式:#{表达式}

 

 

 

 

在applicationContext.xml配置文件中的内容:

   <bean id="car" class="com.xypuxing.pojo.Car">

      <property name="name" value="宝马"></property>

      <property name="carNo" value="京A8888"></property>

   </bean>

 

   <bean id="person" class="com.xypuxing.pojo.Person">

      <!-- 实验26:[SpEL测试I]在SpEL中使用字面量 -->

      <property name="id" value="#{88}" />

<!--    <propertyname="name" value="#{'这是Spring EL注入的值'}" /> -->

      <!-- 实验29:[SpEL测试IV]在SpEL中调用非静态方法

      <propertyname="name" value="#{person.getUUID()}" />

       -->

       <!-- 实验30:[SpEL测试V]在SpEL中调用静态方法-->

      <property name="name" value="#{T(com.xypuxing.pojo.Person).getUUID2()}"/>

      <!-- 实验28:[SpEL测试III]在SpEL中引用其他bean的某个属性值 -->

      <property name="phone" value="#{car.carNo}" />

      <!-- 实验31:[SpEL测试VI]在SpEL中使用运算符 -->

      <property name="salary" value="#{88 * 100}" />

      <!-- 实验27:[SpEL测试II]在SpEL中引用其他bean -->

      <property name="car" value="#{car}" />

   </bean>

 

 

测试的代码

   @Test

   publicvoid test22() {

      ApplicationContext ctx= newClassPathXmlApplicationContext("applicationContext.xml");

      Person person = (Person)ctx.getBean("person");

      System.out.println( person );

   }

 

运行结果


Spring笔记本(2)

注解配置Dao、Service、Controller组件

实验32:通过注解分别创建Dao、Service、Controller★

Spring配置bean的常用注解有

@Controller     专门用来配置web层的         Controller

@Service          专门用来配置Service层的 Service

@Repository    专门用来配置Dao层             Dao

@Component  可以用来配置任意层              但一般如果明确是Dao、Service、Controller都会使用对应层的注解来进行注释

 

而且以上注解只是配置了bean对象,Spring底层不会去检查这个注解的bean是否是真正的Dao,或Service或Controller。

默认的注解功能只是注册一个bean。bean的id就是首字母小写的类名。scope是单例。

 

在配置的bean上使用注解@Scope("singleton")表示单例

在配置的bean上使用注解@Scope("prototype")表示多例

 

如果要修改bean的默认id值。可以在注解中加入一个字符串参数。使用如下:


Spring笔记本(2)

使用的时候applicationContext.getBean(“id”); 即可以通过id查对象

 

在bean上使用注解,还需要使用一个aop的jar包。而且还需要使用Context名称空间进行扫描包

 

 

注解使用回顾:

1、使用@Service、@Controller、@Repository 在需要配置的bean上使用。

2、需要导入aop的jar包。

3、需要在applicationContext.xml配置文件中添加context的包扫描<context:component-scan base-package="com.xypuxing"/>

 

 

添加类和注解


Spring笔记本(2)

@Repository

publicclass BookDao {

 

}

//@Service中加参数。是Bean的id名。

@Scope("prototype") // 表示多例

@Service("bs")

publicclass BookService {

 

}

@Controller

publicclass BookServlet {

 

}

 

给applicationContext.xml添加context名称空间


Spring笔记本(2)

内容如下:

   <!-- context:component-scan 是组件扫描

      base-package是基础包,表示搜索指定包所有的类,以及子包下所有的类

      resource-pattern资源的搜索规则

         dao/*.class 表示搜索dao子包下的所有的类

         */*.class 表示搜索任意子包下的所有类

         */*Service.class 表示搜索任意子包下的某某Service.class

  

   <context:component-scanbase-package="com.xypuxing"resource-pattern="*/*Service.class"/>

 -->

   <context:component-scan base-package="com.xypuxing" />

 

 

测试的代码如下:

   @Test

   publicvoid test1() {

      ApplicationContext applicationContext= new ClassPathXmlApplicationContext("applicationContext.xml");

      BookService bookService =(BookService) applicationContext.getBean("bs");

      BookService bookService2 =(BookService) applicationContext.getBean("bs");

      System.out.println(bookService ==bookService2);

   }

 

 

测试代码如下:


Spring笔记本(2)

指定扫描包时的过滤内容(了解内容

实验33:使用context:include-filter指定扫描包时要包含的类

实验34:使用context:exclude-filter指定扫描包时不包含的类

 

   <context:include-filter />   设置包含的内容

注意:通常需要与use-default-filters属性配合使用才能够达到“仅包含某些组件”这样的效果。即:通过将use-default-filters属性设置为false

      <context:exclude-filter />   设置排除的内容

 

类别

示例

说明

annotation

com.xypuxing.XxxAnnotation

过滤所有标注了XxxAnnotation的类。这个规则根据目标组件是否标注了指定类型的注解进行过滤

assignable

com.xypuxing.BaseXxx

过滤所有BaseXxx类的子类。这个规则根据目标组件是否是指定类型的子类的方式进行过滤。

aspectj

com.xypuxing.*Service+

所有类名是以Service结束的,或这样的类的子类。这个规则根据AspectJ表达式进行过滤。

regex

com\.xypuxing\.anno\.*

所有com.xypuxing.anno包下的类。这个规则根据正则表达式匹配到的类名进行过滤。

custom

com.xypuxing.XxxTypeFilter

使用XxxTypeFilter类通过编码的方式自定义过滤规则。该类必须实现org.springframework.core.type.filter.TypeFilter接口

 

applicationContext.xml     中配置的内容如下

   <!--use-default-filters="false" 设置取消默认包含规则 -->

   <context:component-scan base-package="com.xypuxing" use-default-filters="false">

      <!-- context:include-filter 设置包含的内容-->

      <context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>

      <!-- context:exclude-filter 设置排除的内容-->

      <context:exclude-filter type="assignable" expression="com.xypuxing.service.BookService"/>

   </context:component-scan>

以上配置会包含所有@Service注解的类。排除com.xypuxing.service.BookService

使用注解@Autowired自动装配

实验35:使用@Autowired注解实现根据类型实现自动装配★

 

@Autowired 注解会自动的根据标注的对象类型在Spring容器中查找相对应的类。如果找到,就自动装配。

使用@Autowired注解,不需要get/set方法

 

使用注解的几个类

@Repository

publicclass BookDao {

 

}

@Service

publicclass BookService {

   @Autowired

   private BookDao bookDao;

 

   @Override

   public String toString(){

      return"BookService[bookDao=" + bookDao + "]";

   }

}

@Controller

publicclass BookServlet {

   @Autowired

   private BookService bookService;

 

   @Override

   public String toString(){

      return"BookServlet[bookService=" + bookService + "]";

   }

}

 

applicationContext.xml中的配置

   <context:component-scan base-package="com.xypuxing"/>

 

测试代码

   @Test

   publicvoid test3() {

      ApplicationContext applicationContext= newClassPathXmlApplicationContext("applicationContext.xml");

      System.out.println( applicationContext.getBean("bookServlet") );

   }

 

运行的结果:


Spring笔记本(2)

多个同类型的bean如何自动装配

实验36:如果资源类型的bean不止一个,默认根据@Autowired注解标记的成员变量名作为id查找bean,进行装配★

 

   // @Autowired会自动的根据类型进行装配。

   如果找到一个就直接装配,如果找不到,就报错

   如果找到多个。就根据变量名和bean对象的id进行匹配。匹配上的进行装配。没有匹配上,就报错。

 

 

添加一个BookDaoExt类

@Repository

publicclass BookDaoExt extends BookDao{

}

 

@Repository

publicclass BookDao {

}

 

@Service

publicclass BookService {

   // @Autowired会自动的根据类型进行装配。

   // 如果找到一个就直接装配,如果找不到,就报错

   // 如果找到多个。就根据变量名和bean对象的id进行匹配。匹配上的进行装配。没有匹配上,就报错。

   @Autowired

   private BookDao bookDaoExt;

 

   @Override

   public String toString(){

      return"BookService[bookDao=" + bookDaoExt + "]";

   }

}

 

测试的代码:

   @Test

   publicvoid test3() {

      ApplicationContext applicationContext= newClassPathXmlApplicationContext("applicationContext.xml");

      System.out.println(applicationContext.getBean("bookServlet") );

   }

 

运行的结果

Spring笔记本(2)

使用@Qualifier装配指定id的bean对象

实验37:如果根据成员变量名作为id还是找不到bean,可以使用@Qualifier注解明确指定目标bean的id★

 

修改两个BookDao的id名称

@Repository("bookDao1")

publicclass BookDao {

}

@Repository("bookDao2")

publicclass BookDaoExt extends BookDao {

}

 

@Service

publicclass BookService {

   // @Autowired会自动的根据类型进行装配。

   // 如果找到一个就直接装配,如果找不到,就报错

   // 如果找到多个。就根据变量名和bean对象的id进行匹配。匹配上的进行装配。没有匹配上,就报错。

   @Autowired

      //根据指定id进行查找装配

      @Qualifier("bookDao2")

   private BookDao bookDaoExt;

}

 

applicationContext.xml中扫描的配置不变

测试的代码也不代。自行修改进行测试。


@Autowired注解的required属性作用

实验39:@Autowired注解的required属性指定某个属性允许不被设置

 

   @Autowired(required=false)

   //根据指定id进行查找装配

   @Qualifier("bookDao2")

private BookDao bookDaoExt;

 

@Autowired注解中,有一个required属性。这个属性的默认值是true。表示必须装配上值。如果没有装配成功就会报错。

如果我们把required属性的值设置为false。表示不是必须装配。也就是说。

Spring按照类型查找没有装配成功。按照id查找也没有装配成功。则bookDaoExt的值为null


@Autowired和@Qualifier在方法上的使用。

实验38:在方法的形参位置使用@Qualifier注解

 

准备需要Spring容器管理的bean

@Repository

publicclass BookDao {

}

@Repository

publicclass BookDaoExt extends BookDao {

}

 

@Service

publicclass BookService {

   // @Autowired会自动的根据类型进行装配。

   // 如果找到一个就直接装配,如果找不到,就报错

   // 如果找到多个。就根据变量名和bean对象的id进行匹配。匹配上的进行装配。没有匹配上,就报错。

   @Autowired(required = false)

   // 根据指定id进行查找装配

   @Qualifier("bookDao211")

   private BookDao bookDaoExt;

 

   public BookService() {

   }

 

   @Autowired

   public BookService(BookDaobookDaoExt) {

      System.out.println("这是构造 方法的注入---" + bookDaoExt);

   }

 

   @Autowired(required = false)

   publicvoid setAAA(@Qualifier("bookDao") BookDaobookDaoExt) {

      System.out.println("这是set方法的注入----" + bookDaoExt);

   }

 

   @Override

   public String toString(){

      return"BookService[bookDao=" + bookDaoExt + "]";

   }

}

 

BookService类中注解说明

Spring笔记本(2)

测试代码:

   @Test

   publicvoid test3() {

      ApplicationContext applicationContext= newClassPathXmlApplicationContext("applicationContext.xml");

      System.out.println(applicationContext.getBean("bookServlet") );

   }

泛型注入(了解内容

实验40:测试泛型依赖注入★

 

准备好需要用的包

Spring核心jar包

spring-beans-4.0.0.RELEASE.jar

spring-context-4.0.0.RELEASE.jar

spring-core-4.0.0.RELEASE.jar

spring-expression-4.0.0.RELEASE.jar

Spring的扫描需要的jar包

spring-aop-4.0.0.RELEASE.jar

日记相关jar包

commons-logging-1.1.3.jar

log4j-1.2.17.jar

Spring的测试jar测试

spring-test-4.0.0.RELEASE.jar          新的测试需要用到

创建需要的类

Spring笔记本(2)

在applicationContext.xml配置文件中添加包的扫描

<context:component-scan base-package="com.xypuxing"/>

 

 

测试的代码

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(locations = "classpath:applicationContext.xml")

publicclass SpringTest {

   @Autowired

   BookService bookService;

   @Autowired

   UserService userService;

   @Test

   publicvoid test1() {

      bookService.save();

      System.out.println("==============");

      userService.save();

   }

}

泛型注入原理的分析图:

Spring笔记本(2)



相关文章:

  • 2022-12-23
  • 2021-03-30
  • 2021-11-28
  • 2022-12-23
  • 2022-12-23
  • 2021-08-20
  • 2021-09-29
  • 2022-02-13
猜你喜欢
  • 2021-06-01
  • 2022-12-23
  • 2021-05-15
  • 2021-06-19
  • 2021-07-03
  • 2021-12-23
  • 2021-11-06
相关资源
相似解决方案