1.IOC和DI
IOC側重的是思想 ,DI實現
IOC側重構造對象:通過容器 DI對屬性值進行注入 (普通屬性和域屬性的注入)
2.aop
第一個案例
1.增強:前置和后置
MethodBeforeAdvice AfterReturningAdvice 接口
before() afterRetruing()
2.增強也需要再xml中進行配置
3.AOP操作在配置文件中
<!--dao層的配置-->
<bean id="someDAO" class="cn.happy.day03aop.dao.SomeDAOImpl"></bean>
<!--service層的配置-->
<bean id="someService" class="cn.happy.day03aop.service.SomeServiceImpl">
<property name="dao" ref="someDAO"></property>
</bean>
<!--增強:通知Advice-->
<bean id="beforeAdvice" class="cn.happy.day03aop.aop.MyBeforeAdvice"></bean>
切面
<aop:config>
<aop:pointcut id="mypointcut" expression="execution(public void doSome())">
<aop:advisor advice-ref="beforeAdvice" pointcut-ref="mypointcut">
</aop:advisor>
</aop:config>
3.切點表達式
* *..UserServiceImpl.*(..)
void 全名稱 cn.cn.cn.cn.cn.UserServiceImpl.*(..)
String
int
4.方法簽名
切入點表達式要匹配的對象就是目標方法的方法名。所以,execution表達式中明顯就是方法的簽名。
注意:表達式中加[]的部分表示可省略部分,各部分間用空格分開。在其中可以使用以下符號:
符號 意義
* 0至多個任意字符
.. 用在方法參數中,表示任意多個參數
用在包名后,表示當前包及其子包路徑
+ 用在類名后,表示當前類及其子類
用在接口后,表示當前接口及其實現類
案例:
execution(public * *(..)) 指定切入點為:任意公共方法
execution(* set*(..)) 指定切入點為:任何一個以"set"開始的方法
5. 注入方式
1.設值注入
2.構造注入
條件1:帶參構造 無參構造
條件2:
<bean id="stu">
<constructor-arg index="0" value="張三">
</bean>
3.p命名空間注入
1.copy一個p
2.<bean id="stu" p:name="張三" p:car-ref="car">
4.集合屬性注入
array set list map properties k=v
4.BeanFactory 延遲咱們bean初始化 ,使用的時候再做初始化和ApplicationConext.
ApplicationConext 是BeanFactory的孫子接口
ApplicationConext 容器創建,bean就做初始化
5.Servlet的初始化時機
解析:看情況:1.看xml中 load-on-startup 0或者正整數 容器啟動,bean已經初始化
2.沒有的話或者為負數,用戶第一次訪問Servlet
6.Spring中Bean作用域 scope="singleton/prototype"
7.域屬性自動注入
byName:要求:配置文件中可以有多個對象,但是默認只自動裝配和屬性同名的bean的id對象
byType:要求:相容類型的對象只能有一個
7個專業術語
增強處理/通知(Advice)
增強類中的方法
切入點(Pointcut)
符合切點表達式的方法才能稱為切入點
連接點(Join Point)
目標對象中的所有方法都是連接點
切面(Aspect)
增強類
目標對象(Target object)
等待被增強的對象
AOP代理(AOP proxy)
代理對象,內存中創建的。
織入(Weaving)
將切面和目標對象進行綁定的過程
注解的DI
1.什么是注解
有人說:@Override 在Java中,有小鼠標的就是注解
2.注解的用法
@Override 標識子類中的方法一定來源於父類
@Test 單測方法
@After 在單測后執行
@Before 前執行
@WebServlet(name="" urlpatterns="{"/"}") 對外公開訪問地址
@SuppressWarnings() 取消警告
3.注解主要含義
解析:注解的本質是接口
自定義注解
4.注解的方法
解析:注解是給誰看的,Java編譯器 Java編譯器會獲取到注解的類型元數據。對該類或者方法進行特殊的照顧處理
5.基於注解DI(有*和無*)
component-scan 組件掃描
base-package="cn.happy.day07annotationdi" 掃描本身和子包
base-package="cn.happy.day07annotationdi.*" 只掃描子包
@Component 標識一個類是被Spring容器管理的一個bean
分層的情況
@Repository dao
@Service service
@Controller 控制層
@Value 給類的普通屬性賦值
@Resource 給類的域屬性賦值
@AutoWired 給類的域屬性賦值
金牌結論:如果直接在域屬性上寫Resource。沒有指定名稱,先按照byName嘗試裝配,如果容器中
,沒有和成員變量同名的bean,那么繼續使用byType進行裝配。如果byType
檢測到相容的類型有多個,就報錯:expected single matching,but found 2;
代理
兩類:動態代理和靜態代理
靜態代理:代理模式
代理:
1.代理
招生的速度加快了
2.代理
房屋中介
3.對原有對象的行為進行增強
抽象主題:Subject:接口
目標對象(原始對象):RealSubject(要增強的對象) implements
代理對象:Proxy(植入目標對象) 實現了接口
before code block
business xxx.invoke()
after code block
動態代理 AOP底層實現:有接口自動應用的就是JDK動態代理
1)JDK 在運行時運行時注入
本質:在內存中構建出接口的實現類
特點:被代理對象,必須有接口
Proxy.newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
InvocationHandler調度處理器
public interface InvocationHandler {
}
ClassLoader loader, 類加載器(孫衛琴) 如何獲取到類加載器?
Class<?>[] interfaces,
InvocationHandler h 調度處理器
CGLIB動態代理: 編譯的時候
特點:再一個類型沒有接口的情況下進行代理
實質:內存中構建了出了目標類型的子類
對於不使用接口的業務類,無法使用JDK動態代理,cglib采用非常底層的字節碼技術,
可以為一個類創建子類
CGLIB動態代理 無接口代理 編譯已經增強
final SomeServiceImpl service=new SomeServiceImpl();
Enhancer enhancer=new Enhancer();
enhancer.setSuperClass(service.getClass());
enhancer.setCallBack(new MethodInterceptor(){
public Object intercept(Object o,Method method,Object[] objects,MethodProxy methodProxy){
sout("before=========");
Object resullt=methodProxy.invoke(service,objects);
return result;
}
});
SomeServiceImpl proxy=(SomeServiceImpl)enhancer.create();
proxy.doSome();