spring架構學習筆記5:SpringAOP樣本,springspringaop
1.導包:
匯入spring中的這兩個包
再匯入其他包(網上下載):
2.準備目標對象:
package service;public class UserServiceImpl implements UserService { @Override public void save() { System.out.println("儲存使用者!"); } @Override public void delete() { System.out.println("刪除使用者!"); } @Override public void update() { System.out.println("更新使用者!"); } @Override public void find() { System.out.println("尋找使用者!"); }}
View Code
3.準備通知:
package springaop;import org.aspectj.lang.ProceedingJoinPoint;//通知類public class MyAdvice { //前置通知 // |-目標方法運行之前調用 //後置通知(如果出現異常不會調用)// |-在目標方法運行之後調用 //環繞通知// |-在目標方法之前和之後都調用 //異常攔截通知// |-如果出現異常,就會調用 //後置通知(無論是否出現 異常都會調用)// |-在目標方法運行之後調用//---------------------------------------------------------------- //前置通知 public void before(){ System.out.println("這是前置通知!!"); } //後置通知 public void afterReturning(){ System.out.println("這是後置通知(如果出現異常不會調用)!!"); } //環繞通知 public Object around(ProceedingJoinPoint pjp) throws Throwable { System.out.println("這是環繞通知之前的部分!!"); Object proceed = pjp.proceed();//調用目標方法 System.out.println("這是環繞通知之後的部分!!"); return proceed; } //異常通知 public void afterException(){ System.out.println("出現異常了!"); } //後置通知 public void after(){ System.out.println("這是後置通知(出現異常也會調用)!"); }}
4.配置將通知織入目標對象
(匯入aop約束)
bean包的user對象:
package bean;import javax.annotation.PostConstruct;import javax.annotation.PreDestroy;import javax.annotation.Resource;import org.junit.validator.PublicClassValidator;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.beans.factory.annotation.Value;import org.springframework.context.annotation.Scope;import org.springframework.stereotype.Component;import org.springframework.stereotype.Controller;import org.springframework.stereotype.Repository;import org.springframework.stereotype.Service;//代替的設定檔內容<bean name="user" class="bean.User"/>// @Component("user")//四種本質相同,為了方便理解建議使用以下三種// @Service("user")//service層使用// @Controller("user")//web層使用 @Repository("user")//dao層使用//指定對象的作用範圍@Scope(scopeName="singleton")public class User { @Value("Tom")//賦值 private String name; private Integer age; //@Autowired//對象賦值,自動裝配 //存在問題:如果是多個類型一致的對象,無法分辨 @Resource(name="car")//這種方式可以明確指定(推薦) private Car car; public Car getCar() { return car; } public void setCar(Car car) { this.car = car; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } @Value("20")//也可以在set方法賦值,效果一樣,但不破壞封裝性 public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "User [name=" + name + ", age=" + age + ", car=" + car + "]"; } @PostConstruct//初始化方法,當相於設定檔中的init-mothod public void init(){ System.out.println("初始化"); } @PreDestroy//銷毀方法 public void destory(){ System.out.println("銷毀"); } }
xml設定檔:
<?xml version="1.0" encoding="UTF-8"?><beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd "><!-- 準備工作: 匯入aop(約束)命名空間 --><!-- 1.配置目標對象 --> <bean name="userService" class="service.UserServiceImpl" ></bean><!-- 2.配置通知對象 --> <bean name="myAdvice" class="springaop.MyAdvice" ></bean><!-- 3.配置將通知織入目標對象 --> <aop:config> <!-- 配置切入點 public void service.UserServiceImpl.save() 切點為save()方法 void service.UserServiceImpl.save() public可以省略 * service.UserServiceImpl.save() 傳回值不做要求,可以*代替 * service.UserServiceImpl.*() 為某類的所有空參方法 * service.*ServiceImpl.*(..) 最終形態:從某包下找以serviceimpl結尾的類的所有方法 * service..*ServiceImpl.*(..) --> <aop:pointcut expression="execution(* service.*ServiceImpl.*(..))" id="pc"/> <aop:aspect ref="myAdvice" > <!-- 指定名為before方法作為前置通知 --> <aop:before method="before" pointcut-ref="pc" /> <!-- 後置 --> <aop:after-returning method="afterReturning" pointcut-ref="pc" /> <!-- 環繞通知 --> <aop:around method="around" pointcut-ref="pc" /> <!-- 異常攔截通知 --> <aop:after-throwing method="afterException" pointcut-ref="pc"/> <!-- 後置 --> <aop:after method="after" pointcut-ref="pc"/> </aop:aspect> </aop:config></beans>
測試類別:
package springaop;import javax.annotation.Resource;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import bean.User;import service.UserService;@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration("classpath:springaop/applicationContext.xml")public class Demo { @Resource(name="userService") private UserService us; @Test public void fun1(){ us.save(); } }
調用sava方法:控制台列印如下
補充(這種方式不推薦,瞭解即可):
可以不使用xml設定檔,改為註解
package annotationaop;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.After;import org.aspectj.lang.annotation.AfterReturning;import org.aspectj.lang.annotation.AfterThrowing;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.aspectj.lang.annotation.Pointcut;//通知類@Aspect//表示該類是一個通知類public class MyAdvice { @Pointcut("execution(* service.*ServiceImpl.*(..))") public void pc(){} //前置通知 //指定該方法是前置通知,並制定切入點 @Before("MyAdvice.pc()") public void before(){ System.out.println("這是前置通知!!"); } //後置通知 @AfterReturning("MyAdvice.pc()") public void afterReturning(){ System.out.println("這是後置通知(如果出現異常不會調用)!!"); } //環繞通知 @Around("MyAdvice.pc()") public Object around(ProceedingJoinPoint pjp) throws Throwable { System.out.println("這是環繞通知之前的部分!!"); Object proceed = pjp.proceed();//調用目標方法 System.out.println("這是環繞通知之後的部分!!"); return proceed; } //異常通知 @AfterThrowing("MyAdvice.pc()") public void afterException(){ System.out.println("出現異常了!"); } //後置通知 @After("MyAdvice.pc()") public void after(){ System.out.println("這是後置通知(出現異常也會調用)!!"); }}
設定檔做相應修改:
<?xml version="1.0" encoding="UTF-8"?><beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd "><!-- 準備工作: 匯入aop(約束)命名空間 --><!-- 1.配置目標對象 --> <bean name="userService" class="service.UserServiceImpl" ></bean><!-- 2.配置通知對象 --> <bean name="myAdvice" class="annotationaop.MyAdvice" ></bean><!-- 3.開啟使用註解完成織入 --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy></beans>