Spring框架的IOC功能之注解的方式
Spring框架的IOC之注解方式的快速入門
1. 步驟一:導入注解開發所有需要的jar包
* 引入IOC容器必須的6個jar包
* 多引入一個:Spring框架的AOP的jar包,spring-aop的jar包
2. 步驟二:創建對應的包結構,編寫Java的類
* UserService -- 接口
* UserServiceImpl -- 具體的實現類
3. 步驟三:在src的目錄下,創建applicationContext.xml的配置文件,然后引入約束。注意:因為現在想使用注解的方式,那么引入的約束發生了變化
* 需要引入context的約束,具體的約束如下
<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.xsd"> <!-- bean definitions here -->
</beans>
4. 步驟四:在applicationContext.xml配置文件中開啟組件掃描
* Spring的注解開發:組件掃描
<context:component-scan base-package="com.itheima.demo1"/>
* 注意:可以采用如下配置
<context:component-scan base-package="com.itheima"/> 這樣是掃描com.itheima包下所有的內容
5. 步驟五:在UserServiceImpl的實現類上添加注解
* @Component(value="userService") -- 相當于在XML的配置方式中 <bean id="userService" class="...">
6. 步驟六:編寫測試代碼
public class SpringDemo1 {
@Test
public void run1(){
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService us = (UserService) ac.getBean("userService");
us.save();
}
}
Spring框架中Bean管理的常用注解
1. @Component:組件.(作用在類上)
2. Spring中提供@Component的三個衍生注解:(功能目前來講是一致的)
* @Controller -- 作用在WEB層
* @Service -- 作用在業務層
* @Repository -- 作用在持久層
* 說明:這三個注解是為了讓標注類本身的用途清晰,Spring在后續版本會對其增強
3. 屬性注入的注解(說明:使用注解注入的方式,可以不用提供set方法)
* 如果是注入的普通類型,可以使用value注解
* @Value -- 用于注入普通類型
* 如果注入的是對象類型,使用如下注解
* @Autowired -- 默認按類型進行自動裝配
* 如果想按名稱注入
* @Qualifier -- 強制使用名稱注入
* @Resource -- 相當于@Autowired和@Qualifier一起使用
* 強調:Java提供的注解
* 屬性使用name屬性
Bean的作用范圍和生命周期的注解
1. Bean的作用范圍注解
* 注解為@Scope(value="prototype"),作用在類上。值如下:
* singleton -- 單例,默認值
* prototype -- 多例
2. Bean的生命周期的配置(了解)
* 注解如下:
* @PostConstruct -- 相當于init-method
* @PreDestroy -- 相當于destroy-method
Spring框架整合JUnit單元測試
1. 為了簡化了JUnit的測試,使用Spring框架也可以整合測試
2. 具體步驟
* 要求:必須先有JUnit的環境(即已經導入了JUnit4的開發環境)!!
* 步驟一:在程序中引入:spring-test.jar
* 步驟二:在具體的測試類上添加注解
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringDemo1 {
@Resource(name="userService")
private UserService userService;
@Test
public void demo2(){
userService.save();
}
}
案例一:使用AOP技術對DAO層操作進行增強功能
需求分析
1. 使用AOP技術對DAO層操作進行增強功能
Spring框架的核心功能之AOP技術
AOP的概述
1. 什么是AOP的技術?
* 在軟件業,AOP為Aspect Oriented Programming的縮寫,意為:面向切面編程
* AOP是一種編程范式,隸屬于軟工范疇,指導開發者如何組織程序結構
* AOP最早由AOP聯盟的組織提出的,制定了一套規范.Spring將AOP思想引入到框架中,必須遵守AOP聯盟的規范
* 通過預編譯方式和運行期動態代理實現程序功能的統一維護的一種技術
* AOP是OOP的延續,是軟件開發中的一個熱點,也是Spring框架中的一個重要內容,是函數式編程的一種衍生范型
* 利用AOP可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度降低,提高程序的可重用性,同時提高了開發的效率
2. AOP:面向切面編程.(思想.---解決OOP遇到一些問題)
3. AOP采取橫向抽取機制,取代了傳統縱向繼承體系重復性代碼(性能監視、事務管理、安全檢查、緩存)
4. 為什么要學習AOP
* 可以在不修改源代碼的前提下,對程序進行增強!!
Spring框架的AOP的底層實現
1. Srping框架的AOP技術底層也是采用的代理技術,代理的方式提供了兩種
1. 基于JDK的動態代理
* 必須是面向接口的,只有實現了具體接口的類才能生成代理對象
2. 基于CGLIB動態代理
* 對于沒有實現了接口的類,也可以產生代理,產生這個類的子類的方式
2. Spring的傳統AOP中根據類是否實現接口,來采用不同的代理方式
1. 如果實現類接口,使用JDK動態代理完成AOP
2. 如果沒有實現接口,采用CGLIB動態代理完成AOP
JDK的動態代理(代碼了解,理解原理)
1. 使用Proxy類來生成代理對象的一些代碼如下:
/**
* 使用JDK的方式生成代理對象
* @author Administrator
*/
public class MyProxyUtils {
public static UserDao getProxy(final UserDao dao) {
// 使用Proxy類生成代理對象
UserDao proxy = (UserDao) Proxy.newProxyInstance(dao.getClass().getClassLoader(),
dao.getClass().getInterfaces(), new InvocationHandler() {
// 代理對象方法一直線,invoke方法就會執行一次
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if("save".equals(method.getName())){
System.out.println("記錄日志...");
// 開啟事務
}
// 提交事務
// 讓dao類的save或者update方法正常的執行下去
return method.invoke(dao, args);
}
});
// 返回代理對象
return proxy;
}
}
CGLIB的代理技術(代碼了解)
1. 引入CBLIB的開發包
* 如果想使用CGLIB的技術來生成代理對象,那么需要引入CGLIB的開發的jar包,在Spring框架核心包中已經引入了CGLIB的開發包了。所以直接引入Spring核心開發包即可!
2. 編寫相關的代碼
public static OrderDaoImpl getProxy(){
// 創建CGLIB核心的類
Enhancer enhancer = new Enhancer();
// 設置父類
enhancer.setSuperclass(OrderDaoImpl.class);
// 設置回調函數
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
if("save".equals(method.getName())){
// 記錄日志
System.out.println("記錄日志了...");
}
return methodProxy.invokeSuper(obj, args);
}
});
// 生成代理對象
OrderDaoImpl proxy = (OrderDaoImpl) enhancer.create();
return proxy;
}
Spring基于AspectJ的AOP的開發
AOP的相關術語
1. Joinpoint(連接點) -- 所謂連接點是指那些被攔截到的點。在spring中,這些點指的是方法,因為spring只支持方法類型的連接點
2. Pointcut(切入點) -- 所謂切入點是指我們要對哪些Joinpoint進行攔截的定義
3. Advice(通知/增強) -- 所謂通知是指攔截到Joinpoint之后所要做的事情就是通知.通知分為前置通知,后置通知,異常通知,最終通知,環繞通知(切面要完成的功能)
4. Introduction(引介) -- 引介是一種特殊的通知在不修改類代碼的前提下, Introduction可以在運行期為類動態地添加一些方法或Field
5. Target(目標對象) -- 代理的目標對象
6. Weaving(織入) -- 是指把增強應用到目標對象來創建新的代理對象的過程
7. Proxy(代理) -- 一個類被AOP織入增強后,就產生一個結果代理類
8. Aspect(切面) -- 是切入點和通知的結合,以后咱們自己來編寫和配置的
AspectJ的XML方式完成AOP的開發
1. 步驟一:創建JavaWEB項目,引入具體的開發的jar包
* 先引入Spring框架開發的基本開發包
* 再引入Spring框架的AOP的開發包
* spring的傳統AOP的開發的包
* spring-aop-4.2.4.RELEASE.jar
* com.springsource.org.aopalliance-1.0.0.jar
* aspectJ的開發包
* com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
* spring-aspects-4.2.4.RELEASE.jar
2. 步驟二:創建Spring的配置文件,引入具體的AOP的schema約束
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
3. 步驟三:創建包結構,編寫具體的接口和實現類
* com.itheima.demo2
* CustomerDao -- 接口
* CustomerDaoImpl -- 實現類
4. 步驟四:將目標類配置到Spring中
<bean id="customerDao" class="com.itheima.demo3.CustomerDaoImpl"/>
5. 步驟五:定義切面類
public class MyAspectXml {
// 定義通知
public void log(){
System.out.println("記錄日志...");
}
}
6. 步驟六:在配置文件中定義切面類
<bean id="myAspectXml" class="com.itheima.demo3.MyAspectXml"/>
7. 步驟七:在配置文件中完成aop的配置
<aop:config>
<!-- 引入切面類 -->
<aop:aspect ref="myAspectXml">
<!-- 定義通知類型:切面類的方法和切入點的表達式 -->
<aop:before method="log" pointcut="execution(public * com.itheima.demo3.CustomerDaoImpl.save(..))"/>
</aop:aspect>
</aop:config>
8. 完成測試
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Demo3 {
@Resource(name="customerDao")
private CustomerDao customerDao;
@Test
public void run1(){
customerDao.save();
customerDao.update();
customerDao.delete();
}
}
切入點的表達式
1. 再配置切入點的時候,需要定義表達式,重點的格式如下:execution(public * *(..)),具體展開如下:
* 切入點表達式的格式如下:
* execution([修飾符] 返回值類型 包名.類名.方法名(參數))
* 修飾符可以省略不寫,不是必須要出現的。
* 返回值類型是不能省略不寫的,根據你的方法來編寫返回值。可以使用 * 代替。
* 包名例如:com.itheima.demo3.BookDaoImpl
* 首先com是不能省略不寫的,但是可以使用 * 代替
* 中間的包名可以使用 * 號代替
* 如果想省略中間的包名可以使用 ..
* 類名也可以使用 * 號代替,也有類似的寫法:*DaoImpl
* 方法也可以使用 * 號代替
* 參數如果是一個參數可以使用 * 號代替,如果想代表任意參數使用 ..
AOP的通知類型
1. 前置通知
* 在目標類的方法執行之前執行。
* 配置文件信息:<aop:after method="before" pointcut-ref="myPointcut3"/>
* 應用:可以對方法的參數來做校驗
2. 最終通知
* 在目標類的方法執行之后執行,如果程序出現了異常,最終通知也會執行。
* 在配置文件中編寫具體的配置:<aop:after method="after" pointcut-ref="myPointcut3"/>
* 應用:例如像釋放資源
3. 后置通知
* 方法正常執行后的通知。
* 在配置文件中編寫具體的配置:<aop:after-returning method="afterReturning" pointcut-ref="myPointcut2"/>
* 應用:可以修改方法的返回值
4. 異常拋出通知
* 在拋出異常后通知
* 在配置文件中編寫具體的配置:<aop:after-throwing method="afterThorwing" pointcut-ref="myPointcut3"/>
* 應用:包裝異常的信息
5. 環繞通知
* 方法的執行前后執行。
* 在配置文件中編寫具體的配置:<aop:around method="around" pointcut-ref="myPointcut2"/>
* 要注意:目標的方法默認不執行,需要使用ProceedingJoinPoint對來讓目標對象的方法執行。