SSM學習—Spring(第四天學習記錄)

- 作用域
在這裏插入圖片描述

 <!--
        bean的作用域:
            singleton:單例(默認)
                 在整個IOC容器中只能存在一個bean對象
                 容器被創建的時候,就創建單例的bean對象,
                 後續每次通過getBean方法獲取Bean的時候,
                 都是同一個bean對象
            單例的bean和單例的類不同
    -->
    <bean id="car" class="Scope.Car"  scope="singleton">
        <property name="brand" value="寶馬"/>
        <property name="price" value="2111112123"/>
    </bean>
      <!--
      prototype:多例
        整個IOC容器中有多個可用的bean對象,在IOC被創建時不會
        創建原型的bean對象,而是等到每次通過getBean的方法纔會
        創建bean對象
    -->
    <bean id="cars" class="Scope.Car" scope="prototype">
        <property name="brand" value="寶馬1"/>
        <property name="price" value="21111121231"/>
    </bean>

測試代碼如下:

 @Test
    public void  testS(){
        ApplicationContext applicationContext=new
                ClassPathXmlApplicationContext("Spring_Scope.xml");
        Car car1=applicationContext.getBean("car" ,Car.class);
        Car car2=applicationContext.getBean("car" ,Car.class);
        System.out.println(car1.equals(car2));
        Car car3=applicationContext.getBean("cars",Car.class);
        Car car4=applicationContext.getBean("cars",Car.class);
        System.out.println(car3.equals(car4));
    }

測試結果(測試階段,重寫了Car裏面的構造方法和set方法)
在這裏插入圖片描述

- SpringIOC的管理
① 通過構造器或工廠方法創建bean實例
② 爲bean的屬性設置值和對其他bean的引用
③ 調用bean的初始化方法
④ bean可以使用了
⑤ 當容器關閉時,調用bean的銷燬方法(在配置bean時,通過init-method和destroy-method 屬性爲bean指定初始化和銷燬方法)
後置處理器
① bean後置處理器允許在調用初始化方法前後對bean進行額外的處理
② bean後置處理器對IOC容器裏的所有bean實例逐一處理,而非單一實例。其典型 應用是:檢查bean屬性的正確性或根據特定的標準更改bean的屬性。
③ bean後置處理器時需要實現接口:
org.springframework.beans.factory.config.BeanPostProcessor。在初始化方法被調用前後,Spring將把每個bean實例分別傳遞給上述接口的以下兩個方法:
●postProcessBeforeInitialization(Object, String)
●postProcessAfterInitialization(Object, String)
添加bean後置處理器後bean的生命週期
①通過構造器或工廠方法創建bean實例
②爲bean的屬性設置值和對其他bean的引用
③將bean實例傳遞給bean後置處理器的postProcessBeforeInitialization()方法
④調用bean的初始化方法
⑤將bean實例傳遞給bean後置處理器的postProcessAfterInitialization()方法
⑥bean可以使用了
⑦當容器關閉時調用bean的銷燬方法

    <bean id="car2" class="Scope.Car" init-method="init" destroy-method="destroy">
        <property name="brand" value="寶馬1"/>
        <property name="price" value="21111121231"/>
    </bean>
    <!--配置處理器,Spring能自動識別是一個後置處理器,所有的該XML文件裏面的Bean都會被該後置處理器進行管理-->
    <bean class="Scope.MyBeanPost"></bean>

測試代碼:
    @Test
    public void  test(){
        ConfigurableApplicationContext applicationContext=new
                ClassPathXmlApplicationContext("Spring_Scope.xml");
        Car car=applicationContext.getBean("car2",Car.class);
        System.out.println("第四個階段,使用bean對象"+car.toString());
        applicationContext.close();
    }

接口實現類:

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

/**
 * bean的後置處理器,對所有的bean都起作用
 */

public class MyBeanPost implements BeanPostProcessor {

    /**
     * 在初始化之前執行
     * @param bean  正在被創建的bean對象
     * @param beanName bean對象的id值
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("後置處理器加1");
        return bean;
    }

    /**
     * 在bean的生命週期的初始化方法之後執行
     * @param bean  正在被創建的bean對象
     * @param beanName bean對象的id值
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("後置處理器加2");
        return bean;
    }
} 


配置數據庫連接池

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
	<property name="user" value="root"/>
	<property name="password" value="root"/>
	<property name="jdbcUrl" value="jdbc:mysql:///test"/>
	<property name="driverClass" value="com.mysql.jdbc.Driver"/>
</bean>

引用外部的屬性文件(properties)

#K-V
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring
jdbc.username=root
jdbc.password=qwsa1234
//之後要導入context的命名空間,這點上,eclipse的體驗的確要遠超於idea,
//在下面的source裏面把context打上對勾即可,而idea只能自己補全
<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/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context
		 http://www.springframework.org/schema/context/spring-context-4.0.xsd">
//導入外部的屬性配置文件
 <context:property-placeholder location="classpath*:db.properties"/>
        <!--配置C3p0連接池-->
        <bean id="DataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
                <property name="driverClass" value="${jdbc.driver}"></property>
                <property name="jdbcUrl" value="${jdbc.url}"></property>
                <property name="user" value="${jdbc.username}"></property>
                <property name="password" value="${jdbc.password}"></property>

        </bean>


1)手動裝配:以value或ref的方式明確指定屬性值都是手動裝配。
2)自動裝配:根據指定的裝配規則,不需要明確指定,Spring自動將匹配的屬性值注入bean中。

    <bean id="car" class="Auto.Car">
        <property name="brand" value="寶馬"/>
        <property name="price" value="288811"/>
    </bean>
    <bean id="address" class="Auto.Address">
           <property name="city" value="鄭州"/>
        <property name="province" value="河南"/>
    </bean>
    <!--對person進行自動裝配
       byName: 使用bean的屬性名與在IOC容器中找到一個id匹配的bean,匹配成功則裝配成功
       bytype: 使用bean的屬性的類型與IOC容器中<bean>的class進行匹配
                若唯一匹配則裝配成功,否則拋出異常
        代碼重合度極高,只需要修改下autowire的屬性值就好了,就不一一列舉
    -->
    <bean id="person" class="Auto.Person" autowire="byName">
        <property name="name" value="Tom"/>

    </bean>
//對象類

public class Person {
	
	private String name ; 
	
	private Car car ; 
	
	private Address address ;
	//set和get還有toString就省略了,大家明白就好,Car和address的屬性一目了之
	}

//測試代碼
@Test
	public void testAutoWire() {
		
		ApplicationContext ctx = 
				new ClassPathXmlApplicationContext("spring-autowire.xml");
		
		Person person = ctx.getBean("person",Person.class);
		System.out.println(person);
	}

測試結果


(必須有aop的jar包)
有一說一熬,XML只是便於理解,用起來屬實憨批,推薦用註解的方式來進行代碼實現

常用註解(MVC就不用再說了吧)

  1. 普通組件:@Component 標識一個受Spring IOC容器管理的組件
  2. 持久化層組件:@Repository 標識一個受Spring IOC容器管理的持久化層組件
  3. 業務邏輯層組件:@Service 標識一個受Spring IOC容器管理的業務邏輯層組件
  4. 表述層控制器組件:@Controller 標識一個受Spring IOC容器管理的表述層控制器組件

組件命名規則

  • 默認情況:使用組件的簡單類名首字母小寫後得到的字符串作爲bean的id
  • 使用組件註解的value屬性指定bean的id
    注意:事實上Spring並沒有能力識別一個組件到底是不是它所標記的類型,即使將@Respository註解用在一個表述層控制器組件上面也不會產生任何錯誤,所以@Respository、@Service、@Controller這幾個註解僅僅是爲了讓開發人員自己明確當前的組件扮演的角色。

掃描

-組件被上述註解標識後還需要通過Spring進行掃描才能夠偵測到。

<!--base-package屬性指定一個需要掃描的基類包,Spring容器將會掃描這個基類包及其子包中的所有類。
	當需要掃描多個包時可以使用逗號分隔。
	如果僅希望掃描特定的類而非基包下的所有類,可使用resource-pattern屬性過濾特定的類 -->
<context:component-scan base-package="MVCt"/>
<context:component-scan 
	base-package="MVC" 
	resource-pattern="Dao/*.class"/>
<!--包含與排除-->
 <context:component-scan base-package="MVC" >
        <!--指定掃描
            type=annotation:表示只包含帶有expression的註解
			當使用include-filter的時候,需要將context:component裏面的
			 use-default-filters="false"
			 掃描的就只是include-filter中的規則指定的	組件
-->
                <context:include-filter type="assignable" expression="MVC.controller.UserController"/>

   <!--  排除掃描
   子節點表示要排除在外的目標類-->
       <context:exclude-filter type="assignable" expression="MVC.controller.UserController"/>
    </context:component-scan>

引用尚硅谷的過濾表達式
過濾表達式

組件裝配

在指定要掃描的包時,context:component-scan 元素會自動註冊一個bean的後置處理器:AutowiredAnnotationBeanPostProcessor的實例。該後置處理器可以 自動裝配標記 了@Autowired、@Resource或@Inject註解的屬性。
在這裏插入圖片描述

package MVC.controller;

import MVC.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

/**
 * @Cotroller 註解的作用: 
 * 相當於在xml文件中: 
 * <bean id="userController" class="com.atguigu.spring.annotation.controller.UserController">
 * 
 * 註解默認的id值 就是類名首字母小寫, 可以在註解中手動指定id值:@Controller(value="id值")
 * 可以簡寫爲:@Controller("id值")
 * 
 *
 */
@Controller
public class UserController {
	
	@Autowired
	private UserService userService;
	
	
	public void  regist() {
		
		userService.handleAddUser();
	}

}

import org.springframework.stereotype.Repository;

@Repository
public class UserDaoJdbcImpl  implements UserDao{
@Override
	public void addUser() {
		System.out.println("UserDao  Jdbc .....");
	}
}


import org.springframework.stereotype.Repository;
@Repository
public class UserDaoMybatisImpl implements UserDao {	
	@Override
	public void addUser() {
		System.out.println("UserDao  Mybatis .....");
	}
}

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;



@Service
public class UserServiceImpl implements UserService {
	
	/**
	 *  @Autowired 完成bean屬性的自動裝配
	 *  
	 *  工作機制:  首先會使用byType的方式進行自動裝配,如果能唯一匹配,則裝配成功, 
	 *           如果匹配到多個兼容類型的bean, 還會嘗試使用byName的方式進行唯一確定. 
	 *           如果能唯一確定,則裝配成功,如果不能唯一確定,則裝配失敗,拋出異常. 
	 *  
	 *  默認情況下, 使用@Autowired標註的屬性必須被裝配,如果裝配不了,也會拋出異常. 
	 *  可以使用required=false來設置不是必須要被裝配. 
	 *  
	 *  如果匹配到多個兼容類型的bean,可以使用@Qualifier來進一步指定要裝配的bean的id值 。
	 *  
	 *  @Autowired @Qualifier 註解即可在成員變量上,也可以加在對應的set方法上.. 
	 *  
	 */
	@Autowired(required=false)  
	@Qualifier("userDaoJdbcImpl")	//指定裝配的Bean的id
	private UserDao userDao ;
	
	
	
	
//	@Autowired(required=false)   // 自動裝配  byName  byType ?????
//	@Qualifier("userDaoJdbcImpl")
//	public void setUserDao(UserDao userDao) {
//		this.userDao = userDao;
//	}
	
	@Override
	public void handleAddUser() {
		//處理業務
		
		userDao.addUser();
	}
}

運行結果如下
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章