1. 課程介紹
- 1. 依賴注入;(掌握)
- 2. XML自動注入;(掌握)
- 3. 全注解配置;(掌握)
- 4. 代理模式;(掌握)
- 5. AOP;(掌握)
- 依賴注入;(掌握)
2.1. 構造參數注入
自己用得不多,除非是其他框架提供的類可能會用到
常用的是方案一、二
2.1.1. 方案一:根據構造器參數的順序(索引)
<!-- 按照索引注入,索引開始為0 -->
<bean id="MyBean" class="cn.itsource._01_.MyBean">
<constructor-arg index="0" value="666" />
<constructor-arg index="1" value="張二娃" />
</bean>
2.1.2. 方案二:根據構造器參數的名稱
<!-- 按照名稱注入,名稱必須一致,類似set注入類似 -->
<bean id="MyBean" class="cn.itsource._01_.MyBean">
<constructor-arg name="id" value="1" />
<constructor-arg name="name" value="張三娃" />
</bean>
2.1.3. 方案三:根據構造器的類型注入
<!-- 按照類型注入,必須一一對應,不能有重復的類型-->
<bean id="MyBean" class="cn.itsource._01_.MyBean">
<constructor-arg type="java.lang.Long" value="1" />
<constructor-arg type="java.lang.String" value="張四娃" />
</bean>
2.2. 如果有一個參數是我們自己的一個對象,怎么解決?
2.2.1. 方案一:先在外面定義好
<bean id="otherBean" class="cn.itsource._01_.OtherBean"/>
<bean id="MyBean" class="cn.itsource._01_.MyBean">
<constructor-arg value="1" />
<constructor-arg value="張五娃" />
<constructor-arg ref="otherBean"/>
</bean>
2.2.2. 方案二: 使用一個內部的Bean完成(不需要加id)
<bean id="MyBean" class="cn.itsource._01_.MyBean">
<constructor-arg value="1" />
<constructor-arg value="張六娃" />
<constructor-arg>
<bean class="cn.itsource._01_.OtherBean"/>
</constructor-arg>
</bean>
2.3. 其它簡單、集合屬性注入
2.3.1. 准備好相應的類屬性
// 簡單屬性
private Long id;
private String name;
private Boolean sex;
private BigDecimal salary;
// 對象屬性
private List<OtherBean> otherBeanList;
private Set<String> set;
private Set<OtherBean> otherBeanSet;
private Map<String,Object> map;
//下面這個是重點
private Properties props1;
private Properties props2;
private String[] arrays;
private List<String> list;
下面的都看一下,大概了解一下就行了
2.4. 數組(兩種方案-掌握):
2.4.1. 簡寫
<property name="arrays" value="A,B,C" />
2.4.2. 完整寫法
<property name="arrays">
<array>
<value>xxx</value>
<value>yyy</value>
<value>zzz</value>
</array>
</property>
2.5. List<String>(了解)
<property name="list">
<list>
<value>xxx</value>
<value>aaa</value>
<value>bbbb</value>
</list>
</property>
2.6. Set<String>(了解)
<property name="set">
<set>
<value>xxx</value>
<value>aaa</value>
<value>bbbb</value>
</set>
</property>
2.7. List<OtherBean>(了解)
<property name="otherBeanList">
<list>
<bean class="cn.itsource._01_.OtherBean" />
<bean class="cn.itsource._01_.OtherBean" />
<ref bean="otherBean" />
<ref bean="otherBean" />
</list>
</property>
2.8. Set<OtherBean>(了解)
<property name="otherBeanSet">
<set>
<bean class="cn.itsource._01_.OtherBean" />
<bean class="cn.itsource._01_.OtherBean" />
<ref bean="otherBean" />
<ref bean="otherBean" />
</set>
</property>
2.9. Map(了解)
<property name="map">
<map>
<entry key="xx" value="value1"></entry>
<entry key="yy" value="value2"></entry>
</map>
</property>
2.10. 這里是咱們的重點部分,怎么配置一個Properties對象:
2.10.1. 方案一:簡單,不支持中文
<property name="props1">
<value>
Jpa.dialect=org.Jpa.dialect.HSQLDialect
Jpa.driverClassName=com.mysql.jdbc.Driver
</value>
</property>
2.10.2. 方案二:支持中文
<property name="props2">
<props>
<prop key="Jpa.dialect">org.Jpa.dialect.HSQLDialect</prop>
<prop key="Jpa.driverClassName">com.mysql.jdbc.Driver中文 </prop>
</props>
</property>
- XML自動注入
使用XML自動注入,可以簡化我們XML的配置。
不過對於學習階段,並不建議大家這樣來使用。
3.1. 簡化spring的配置文件
3.1.1. byName 按照屬性的名稱 setXxx方法
bean.id的名稱
3.1.2. byType 按照注入對象的類型,要求:類型只能配置一個實例
setXxx方法 注入類的類型(Class)
和配置文件里面的類型進行比較
配置文件里面的類型只能是1個
3.2. 配置方案
根節點beans default-autowire="byName" 對當前配置文件的所有bean都生效
子節點bean autowire="byType"只對當前bean生效
- 全注解配置
在Java中寫Xml配置Bean還是比較麻煩,因此,Spring還提供了使用注解來配置的文件。我們可以來看一下,注解是怎么來配置這個Xml的
配置使用注解流程步驟
4.1. 配置context命名空間
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
4.2. 第一步:配置讓Spring掃描類與支持注解
<!--
@Component 普通倉庫
@Repository 倉庫(其實就是dao層)
@Service service層
@Controller 控制層(servlet、admin)
-->
<!-- 進行包的掃描,去看類上面是否有相應的標簽配置 -->
<context:component-scan base-package="cn.itsource._03_anno" />
<!-- 這個不是必須的(spring3.2版本前使用) 配上后兼容性好 -->
<context:annotation-config />
4.3. 第二步:在類里面加上注解
4.3.1. Dao
@Repository
public class UserDao {
public void save(){
System.out.println("保存數據xxxx....");
}
}
4.3.2. Service
@Service
public class UserService {
@Autowired
private UserDao userDao;
public void save(){
userDao.save();
}
}
4.3.3. Action
@Controller
@Scope(“prototype”) 多例
public class UserAction {
@Autowired
private UserService userService;
public String save(){
userService.save();
return "success";
}
}
4.4. 注解配置bean的名稱
4.4.1. 接口有兩個實現(可能性比較少)
完成之后,大家注意,現在的配置還有一個問題,比如說我按真實情況來一個Dao接口,然后這個接口有兩個實現,現在就會出問題
IUserDao (UserJdbcDaoImpl/UserJpaDaoImpl)
而我們聲明的時候就是使用了IUserDao
@Service
public class UserService {
@Autowired
private IUserDao userDao;
public void save(){
userDao.save();
}
}
此時會就出錯:因為Spring不知道你用的是哪一個dao的實現
4.4.2. 解決的方案:為dao生成的bean加上名稱,我們在調用的時候確定名稱即可。
@Repository("userJdbcDao")
public class UserJdbcDaoImpl implements IUserDao{
public void save(){
System.out.println("保存數據xxxx....");
}
}
@Repository("userJpaDao")
public class UserJpaDaoImpl implements IUserDao{
public void save(){
System.out.println("保存數據xxxx....");
}
}
4.5. 調用名稱兩套方案:
4.5.1. 方案一:使用@Autowired
@Service
public class UserService {
@Autowired
@Qualifier("userJdbcDao")
private IUserDao userDao;
public void save(){
userDao.save();
}
}
4.5.2. 方案二:使用@Resource
@Service
public class UserService {
@Resource(name="userJpaDao")
private IUserDao userDao;
public void save(){
userDao.save();
}
}
4.6. 問題:使用哪一種注解來解決比較好?
如果你用的是Spring的注解,盡量全部使用Spring的注解標簽
- 使用xml版手動注入,xml自動注入還是注解版?
初學使用xml版,手動注入
熟練之后可以使用xml自動注入
以后趨勢:注解版
如果是注解版,就全部使用注解(自己寫的類),不要混用,其它框架已經寫好的類仍然使用xml進行配置
如果是xml版,在測試的使用必須使用注解注入(因為測試框架使用注解版)
只有自己寫的類,才可以全部用注解,別人寫的類使用注解必須去修改別人的源碼,添加相應的注解標志(不建議這樣搞)
- 代理模式
Aop利用代理模式實現功能增強
Aop能夠做什么?日志管理,事務管理,權限控制
6.1. 定義
代理模式的英文叫做Proxy或Surrogate,中文都可譯為”代理“,所謂代理,就是一個人或者一個機構代表另一個人或者另一個機構采取行動。在一些情況下,一個客戶不想或者不能夠直接引用一個對象,而代理對象可以在客戶端和目標對象之間起到中介的作用
6.2. 三種角色
6.2.1. 抽象主題角色:
聲明了真實主題和代理主題的共同接口,這樣一來在任何可以使用真實主題的地方都可以是使用代理主題
6.2.2. 代理主題(Proxy)角色:
代理主題角色內部含有對真實主題的引用,從而可以在任何時候操作真實主題對象;
代理主題角色提供一個與真實主題角色相同的接口,以便可以在任何時候都可以替代真實主題控制對真實主題的引用,負責在需要的時候創建真實主題對象(和刪除真實主題對象);
代理角色通常在將客戶端調用傳遞給真實的主題之前或之后(前置增強/通知,后置增強/通知),都要執行某個操作,而不是單純地將調用傳遞給真實主題對象。
6.2.3. 真實主題角色:
定義了代理角色所代表地真實對象
6.3. 代理模式分類
靜態代理/動態代理
6.4. 靜態代理
6.4.1. 抽象主題角色
6.4.2. 真實主題角色
6.4.3. 代理主題角色:中介
代理主題角色內部含有對真實主題的引用
6.4.4. 調用方
如果有代理主題角色存在,必須修改調用方才能實現代理
6.4.5. 靜態代理的小結
如果有n個接口,必然有n個實現,n個代理類:代碼非常多
6.5. jdk動態代理
和靜態代理有相同的抽象主題角色,真實主題角色
JDK動態代理要求它代理的這個真實對象必須要實現某一個接口
CGLIB 動態代理,真實對象可以不實現接口
Spring中使用代理,如果這個類有接口,默認使用JDK的動態代理,如果這個類沒有接口,會使用CGLIB的動態代理
6.5.1. 代理主題角色
6.5.2. 調用方
6.5.3. jdk動態代理小結
如果有n個接口,必然有n個實現,只用寫1個代理類JDKProxy就可以對所有有接口進行處理
如果有代理主題角色存在,必須修改調用方才能實現代理
6.6. Cglib動態代理
Cglib類似於javassist-3.18.1-GA.jar功能字節碼增強,
原來Hibernate3.2之前就是使用cglib來進行字節碼增強
6.6.1. 代理主題角色
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
6.6.2. cglib動態代理小結
只用寫1個代理類CglibProxy就可以對所有沒有接口的並且不能是final類都進行處理
如果有代理主題角色存在,必須修改調用方才能實現代理
- Spring的AOP
7.1. 早期aop都是spring自己實現,后來還是用的標准aspects
AOP:面向切面編程
配置的三個元素(何時,何地,執行什么功能)
何時:在執行方法之前/之后/有異常... 前置還是后置,異常
何地:在哪一個包中的哪一個類的哪一個方法上面執行 切入點:哪個包哪個類哪個方法
做什么事: 在UserServie中執行update方法之前添加日志 增強/通知
7.2. Spring有兩種代理方案:
7.2.1. 若目標對象實現了若干接口
spring使用JDK的java.lang.reflect.Proxy類代理。
7.2.2. 若目標對象沒有實現任何接口,
spring使用CGLIB庫生成目標對象的子類。
7.2.3. 使用該方案時需要注意:
1.對接口創建代理優於對類創建代理,因為會產生更加松耦合的系統。
對類代理是讓遺留系統或無法實現接口的第三方類庫同樣可以得到通知,
這種方案應該是備用方案。
2.標記為final的方法不能夠被通知。spring是為目標類產生子類。任何需要
被通知的方法都被復寫,將通知織入。final方法是不允許重寫的。
7.3. Xml版
7.3.1. 添加jar文件
aspects
spring-framework-4.1.2.RELEASE-dependencies\org.aopalliance\com.springsource.org.aopalliance\1.0.0\com.springsource.org.aopalliance-1.0.0.jar
spring-framework-4.1.2.RELEASE-dependencies\org.aspectj\com.springsource.org.aspectj.weaver\1.6.8.RELEASE\com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
7.3.2. 添加aop命名空間
xmlns:aop="http://www.springframework.org/schema/aop"
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
7.3.3. 前置增強(通知)
7.3.4. 后置增強,異常增強,最終增強
7.3.5. 環繞增強(前面的4個增強就不用了)
7.3.6. 環繞方法
import org.aspectj.lang.ProceedingJoinPoint;
7.4. 注解版
7.4.1. 配置文件
7.4.2. 事務管理器
7.4.3. AOP中的概念
什么叫做AOP:Aspect oritention programming(面向切面編程)
AOP當中的概念:
1,切入點Pointcut:在哪些類,哪些方法上面切(where);
2,增強,通知Advice(對應到一個方法):在方法的什么時機(when)做什么(what);
3,切面Aspect:切入點+通知
4,織入Weaving:把切面加入到對象,並創建出代理對象的過程.