-
概念與代理課程主要內容
- Maven管理項目依賴
- 工廠方法
- 自動注入
- 註解
- Aop概念與代理
目錄
Maven方式創建Spring工程
工程創建
1.新建項目 選擇Maven Project
2.勾選 Create a simple project
3.添加項目信息
- Group id :包名
- Artifact id:標識名
- Name:項目名
依賴引入
Maven 中央倉庫
使用國內鏡像
創建一個maven的配置文件
參照:
http://maven.apache.org/settings.html
Pom.xml
<!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.1.7.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.7.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.1.7.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</dependency>
空值注入
Value標籤
標識空值 或空字符串 “”
<property name="name"><value></value></property>
Null標籤
標識Null
<property name="name"><null></null></property>
工廠方式注入
爲滿足更復雜的需求,Spring也提供了工廠方式來創建更加靈活的Bean。
留意觀察工廠類和實現類的創建次數
動態工廠
抽象接口 Car
public interface Car {
public String getName();
public String getPrice();
}
實現類 BMW車
public class Bmw implements Car{
public String getName() {
// TODO Auto-generated method stub
return "別摸我";
}
public String getPrice() {
// TODO Auto-generated method stub
return "500000RMB";
}
}
汽車工廠類 CarFactory
public class CarFactory {
public Car getCar(String name) throws Exception{
if (name.endsWith("bmw")) {
return new Bmw();
}else {
throw new Exception("car not fond");
}
}
}
Bean配置
<bean id="carFactory" class="com.msb.CarFactory"></bean>
<bean id="car" factory-bean="carFactory" factory-method="getCar" >
<constructor-arg value="bmw"></constructor-arg>
</bean>
靜態工廠
Bean配置
<bean id="carStatic" class="com.msb.CarFactoryStatic" factory-method="getCar">
<constructor-arg value="bmw"></constructor-arg>
</bean>
工廠類
public class CarFactoryStatic {
public static Car getCar(String name) throws Exception{
if (name.endsWith("bmw")) {
return new Bmw();
}else {
throw new Exception("car not fond");
}
}
}
autowire自動注入
使用自動需要在配置文件中bean上添加autowire
<bean id="person" class="com.msb.Person" autowire="byName">
</bean>
<bean id="pet" class="com.msb.Pet">
<property name="name" value="kele"></property>
</bean>
實體
public class Person {
private String name;
private Pet pet;
}
public class Pet {
private String name;
}
可選兩種類型
byName
byName方式自動注入:要求注入的bean的id必須和被注入的bean對象的屬性名一致
byType
byType方式自動注入:要求注入的bean的對象類型與被注入的bean對象類型一致,並且在配置文件中的Bean相同類型必須唯一
如果存在多個,會拋異常:
No qualifying bean of type 'com.msb.Pet' available: expected single matching bean but found 2: pet,pet2
全局空值自動注入
在首行Beans標籤下添加default-autowire屬性。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
default-autowire="byType"
>
annotation註解注入
使用註解需要導入AOP包
在配置文件中添加Context約束
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
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.xsd
"
>
<context:component-scan>
<context:component-scan base-package="com.msb"></context:component-scan>
component-scan可以自動掃描包內容,並註冊Bean到Spring容器
@Component
在需要註冊到容器的類上添加@Component標籤,標識這個類由Spring容器接管
約定大於配置
在一個類上添加@Component默認會使用首字母小寫的類名作爲ID註冊到Spring容器。
如果需要手動指定Bean Id可以使用@Component("p")
同屬@Component的額外三個註解
@Controller @Service @Repository
這三個注意在MVC開發中會經常用到,除了註解名字和Component不一樣之外,其餘功能都一樣。
Spring額外提供這三個註解的目的主要是爲了區分MVC中每個類的區別。
@Scope
使用註解註冊Bean 默認的作用域還是singleton,可以使用@Scope("prototype")改變對象作用域
@Value
在使用註解給對象注入值的時候,不再需要Get/Set方法
基礎類型
使用@Value註解
@Value("小明")
private String name;
對象引用
@Autowired
private Pet MyPet;
使用@Autowired註解
默認是ByType的,如果需要ByName需要配合@Qualifier註解
@Autowired()
@Qualifier("p2")
private Pet MyPet;
面向切面編程 代碼增強
AOP(Aspect Oriented Programming)面向切面編程。
面向切面,是與OOP(Object Oriented Programming)面向對象編程並列的編程思想。
Spring支持兩種方法,那麼我們在使用spring進行動態代理時究竟使用的哪一種方法呢?spring優先支持實現接口的方式,如果沒有接口則使用cglib方式
代理
通過代理可以隱藏目標類的具體實現;在不修改目標類代碼的情況下能夠對其功能進行增強。
- 委託類和代理類有相同的接口或者共同的父類
- 代理類爲委託類負責處理消息,並將消息轉發給委託類
- 委託類和代理類對象通常存在關聯關係
- 一個代理類對象與一個委託類對象關聯
- 代理類本身並不是真正的實現者!而是通過調用委託類的方法來實現功能!
靜態代理
使用硬編碼的方式增強原有方法
- 優點:可以做到不對目標對象進行修改的前提下,對目標對象進行功能的擴展和攔截。
- 缺點:因爲代理對象,需要實現與目標對象一樣的接口,會導致代理類十分繁多,不易維護,同時一旦接口增加方法,則目標對象和代理類都需要維護。
Girl -> 目標對象 -> 被包裝/增強的對象
public class Girl implements Human{
public void eat() {
System.out.println("Em mmm.. mm..");
}
}
抽象接口
interface Human {
public void eat();
}
ProxyGirl 代理對象,包含對原對象方法的增強,通過構造方法傳入原對象,並實現和原對象相同的接口,實現接口方法,便可以利用Java多態的特性,通過訪問代理方法同時能夠調起原對象的實現,並對其增強。
public class ProxyGirl implements Human {
private Human human;
public ProxyGirl() {
super();
}
public ProxyGirl(Human human) {
super();
this.human = human;
}
public void eat() {
System.out.println("chiqian");
human.eat();
System.out.println("chihou");
}
}
測試類
Girl girl = new Girl();
Human proxyGirl = new ProxyGirl(girl);
proxyGirl.eat();
動態代理
動態代理是指動態的在內存中構建代理對象(需要我們制定要代理的目標對象實現的接口類型),即利用JDK的API生成指定接口的對象,也稱之爲JDK代理或者接口代理。
- 目標對象實現了接口 JDK動態代理
- 目標對象沒有實現口CGLib
JDK動態代理
CGLIB動態代理
底層ASM