SpringAOP第一個案例
阿新 • • 發佈:2021-06-12
1.Aop解決的問題
- 當需要為多個不具有繼承關係的物件引入同一個公共行為時,例如日誌、安全檢測等,我們只有在每個物件裡引用公共行為,比如列印日誌,這樣程式中就產生了大量的重複程式碼,程式就不便於維護了,所以就有了一個對面向物件程式設計的補充,即面向方面程式設計(AOP),AOP所關注的方向是橫向的,不同於OOP的縱向。
2.Aop的實現方式 - 靜態 AOP 實現, AOP 框架在編譯階段對程式原始碼進行修改,生成了靜態的 AOP 代理類(生成的 *.class 檔案已經被改掉了,需要使用特定的編譯器),比如 AspectJ。
- 動態 AOP 實現, AOP 框架在執行階段對動態生成代理物件(在記憶體中以 JDK 動態代理,或 CGlib 動態地生成 AOP 代理類),如 SpringAOP。
3.Aop的專有名詞
- 通知(Advice): AOP 框架中的增強處理。通知描述了切面何時執行以及如何執行增強處理。
- 連線點(join point): 連線點表示應用執行過程中能夠插入切面的一個點,這個點可以是方法的呼叫、異常的丟擲。在 Spring AOP 中,連線點總是方法的呼叫。
- 切點(PointCut): 可以插入增強處理的連線點。
- 切面(Aspect): 切面是通知和切點的結合。
- 引入(Introduction):引入允許我們向現有的類新增新的方法或者屬性。
- 織入(Weaving): 將增強處理新增到目標物件中,並建立一個被增強的物件,這個過程就是織入。
4.第一個動態Aop例項:例如SSM框架中,Service層會有一些業務比如常見的增刪改查,例如現在需要在插入資料成功之後列印下日誌 - 引入依賴類AspectJ
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.9.2</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.2</version> </dependency>
- 建立要增強的行為:Service介面的實現類調mapper介面插入資料
public interface UserService {
int insertUser();
int update(SuperUser user);
}
/**
* @author ngLeede
* @version 1.0
* @Desc service的實現類
* @date 2021/6/10 22:07
*/
public class UserServiceImpl implements UserService {
private UserMapper userMapper;
public UserMapper getUserMapper() {
return userMapper;
}
public void setUserMapper(UserMapper userMapper) {
this.userMapper = userMapper;
}
@Override
public int insertUser() {
userMapper.insertUser();
return 0;
}
@Override
public int update(SuperUser user) {
userMapper.update(user);
return 0;
}
}
/**
* @desc mapper介面
* @author ngLeede
* @date 2021/6/11 22:27
*/
public interface UserMapper {
int insertUser();
void update(SuperUser user);
}
/**
* @author ngLeede
* @version 1.0
* @Desc mapper介面的實現類,對應的行為是SSM框架裡的mapper.xml
* @date 2021/6/10 22:06
*/
public class UserMapperImpl implements UserMapper {
@Override
public int insertUser() {
System.out.println("--插入資料--mapper介面--");
return 0;
}
@Override
public void update(SuperUser user) {
System.out.println("---修改超人資訊---");
}
}
- 建立增強類實現aop的MethodBeforeAdvice 前置方法增強--具體要實現的功能是在呼叫Service層的方法前列印日誌
/**
* @author ngLeede
* @version 1.0
* @Desc 增強類
* @date 2021/6/10 22:46
*/
public class MyAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
String mt = method.getName();
System.out.println("前置增強"+mt+"方法");
}
}
- 配置切點使前置增強方法能夠作用於Service層的方法,在applicationContext.xml中進行配置
<?xml version="1.0" encoding="UTF-8"?>
<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">
<!--第一個aopyi 例項-->
<bean id="userMapper" class="com.ngLeede.aopyi.mapper.impl.UserMapperImpl"></bean>
<bean id="userService" class="com.ngLeede.aopyi.service.impl.UserServiceImpl">
<property name="userMapper" ref="userMapper" />
</bean>
<bean id="myadvice" class="com.ngLeede.aopyi.advice.MyAdvice"></bean>
<aop:config>
<!--切點表示式 增強service下的方法-->
<aop:pointcut id="ponitcut" expression="execution(* com.ngLeede.aopyi.service.*.*(..))"/>
<!--織入-->
<aop:advisor advice-ref="myadvice" pointcut-ref="ponitcut"/>
</aop:config>
</beans>
- 簡單的測試
public class AppTest
{
/**
* @desc 測試第一Aop例項
* @author ngLeede
* @date 2021/6/10 22:12
*/
@Test
public void testAopyi(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) applicationContext.getBean("userService");
userService.insertUser();
SuperUser user = new SuperUser();
user.setName("超人");
user.setPhone("167777");
userService.update(user);
}
}