AOP(Aspect Oriented Programming)的縮寫,面向切面編程,主要作用就是對代碼進行增強處理。理解面向切面編程的含義:就是在不改變原有程序的基礎上為代碼增加新的功能。
實現面向切面編程需要了解兩個概念:
>切入點:可以插入增強處理的方法,比如原對象的fun()方法。
>增強處理類型:在原對象fun()方法之前還是之後插入新功能。
1.新建一個java項目
2.到官網下載Spring AOP和AspectJ框架所需要的jar包,並將下載所需的jar文件添加到項目中。
3.在項目中添加User實體類
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20package
com.jbit.fsd.entity;
public
class
User {
private
int
id;
private
String username;
public
int
getId() {
return
id;
}
public
void
setId(
int
id) {
this
.id = id;
}
public
String getUsername() {
return
username;
}
public
void
setUsername(String username) {
this
.username = username;
}
}
4.添加數據訪問層接口和實現類,並添加相應的方法
1 2 3 4 5 6 7 8 9 10 11 12package
com.jbit.fsd.dao;
import
java.util.List;
import
com.jbit.fsd.entity.User;
// 數據訪問層接口
public
interface
UserDao {
public
List<User> getAll();
public
void
addUser(User user);
}
實現類:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26package
com.jbit.fsd.dao.impl;
import
java.util.ArrayList;
import
java.util.List;
import
com.jbit.fsd.dao.UserDao;
import
com.jbit.fsd.entity.User;
public
class
UserDaoImpl
implements
UserDao {
@Override
public
List<User> getAll() {
//操作數據庫讀到所有數據
List<User> list=
new
ArrayList<User>();
list.add(
new
User());
list.add(
new
User());
list.add(
new
User());
return
list;
}
@Override
public
void
addUser(User user) {
System.out.println(
"添加成功"
);
}
}
5.添加業務處理層接口和實現類
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15package
com.jbit.fsd.service;
import
java.util.List;
import
com.jbit.fsd.dao.UserDao;
import
com.jbit.fsd.entity.User;
public
interface
UserService {
public
List<User> getAll();
public
void
addUser(User user);
}
實現類:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27package
com.jbit.fsd.service.impl;
import
java.util.List;
import
com.jbit.fsd.dao.UserDao;
import
com.jbit.fsd.entity.User;
import
com.jbit.fsd.service.UserService;
public
class
UserServiceImpl
implements
UserService{
private
UserDao dao;
//通過spring注入進來
public
void
setDao(UserDao dao) {
this
.dao = dao;
}
@Override
public
List<User> getAll() {
System.out.println(
"正在執行添加用戶的業務!"
);
return
dao.getAll();
}
@Override
public
void
addUser(User user) {<br> System.out.println(
"正在執行添加用戶的業務!"
);
dao.addUser(user);
}
}
6.添加AOP增強處理類
1 2 3 4 5 6 7 8 9 10 11 12package
com.jbit.fsd.aop;
import
org.apache.commons.logging.Log;
import
org.apache.commons.logging.LogFactory;
public
class
ServiceLoging {
private
Log log = LogFactory.getLog(
this
.getClass());
public
void
beforeService(){
log.info(
"aop方法被調用!"
);
}
}
7.在src目錄下新建applicationContext.xml文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32<?xml version=
"1.0"
encoding=
"UTF-8"
?>
<!--
- Application context definition
for
JPetStore's business layer.
- Contains bean references to the transaction manager and to the DAOs in
- dataAccessContext-local/jta.xml (see web.xml's
"contextConfigLocation"
).
-->
<beans xmlns=
"http://www.springframework.org/schema/beans"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
<span style=
"color: rgb(255, 0, 0);"
>xmlns:aop=
"http://www.springframework.org/schema/aop"
</span>
xmlns:tx=
"http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http:
//www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
<span style=
"color: rgb(255, 0, 0);"
>http:
//www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd</span>
http:
//www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<!-- 以面向接口思想編程實現解耦和 -->
<bean id=
"userDao"
class
=
"com.jbit.fsd.dao.impl.UserDaoImpl"
>
</bean>
<bean id=
"userServiceImpl"
class
=
"com.jbit.fsd.service.impl.UserServiceImpl"
>
<property name=
"dao"
ref=
"userDao"
></property> <!-- 屬性注入 -->
</bean>
<!-- 配置切面 -->
<bean id=
"serviceLogging"
class
=
"com.jbit.fsd.aop.ServiceLoging"
></bean>
<aop:config>
<!-- 配置切入點 -->
<aop:pointcut expression=
"execution(public void addUser(com.jbit.fsd.entity.User))"
id=
"servicePointcut"
/>
<!-- 將切面和切入點編制在一起-->
<aop:aspect ref=
"serviceLogging"
>
<aop:before method=
"beforeService"
pointcut-ref=
"servicePointcut"
/>
</aop:aspect>
</aop:config>
</beans>
8.main方法測試:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25package
com.jbit.fsd.test;
import
java.util.List;
import
org.springframework.context.ApplicationContext;
import
org.springframework.context.support.ClassPathXmlApplicationContext;
import
com.jbit.fsd.dao.UserDao;
import
com.jbit.fsd.entity.User;
import
com.jbit.fsd.printer.Printer;
import
com.jbit.fsd.service.UserService;
import
com.jbit.fsd.service.impl.UserServiceImpl;
public
class
Test {
/**
* @param args
*/
public
static
void
main(String[] args) {
ApplicationContext ac=
new
ClassPathXmlApplicationContext(
"applicationContext.xml"
);
UserService dao=(UserService) ac.getBean(
"userServiceImpl"
);
dao.addUser(
new
User());
}
}
說明:
1.在.xml文件中需要添加aop命名空間,導入與aop配置相關的標簽。
2.AOP相關的配置在<aop:config>標簽中,切入點的配置在<aop:pointcut>標簽中。
3.execution是切入點的標識符,括號是切入點的表達式,配置需要增強的方法。
4.切入點表達式常用幾種模糊匹配方式:
>public * addUser(com.able.entity.User),“*”表示配置所有類型的返回值。
>public void * (com.able.entity.User), "*"代表匹配所有的方法名。
>public void addUser(..), " .. "表示匹配所有參數個數和類型。
> * com.able.service.*.*( . . ), 表示匹配com.able.service包下面所有類的所有方法。
> * com.able.service . . *(), 表示匹配com.able.service包以及子包下所有類的所有方法。
1.前置增強處理
特點:在目標方法前織入增強處理。
<aop:before method="beforeService" poontcut-ref="servicePointcut"/>
如果想在這個方法中獲得切入點的信息,使用如下方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17package
com.jbit.fsd.aop;
import
org.apache.commons.logging.Log;
import
org.apache.commons.logging.LogFactory;
import
org.aspectj.lang.JoinPoint;
public
class
ServiceLoging {
private
Log log = LogFactory.getLog(
this
.getClass());
public
void
beforeService(JoinPoint joinPoint){
System.out.println(
"aop方法被調用"
);
System.out.println(
"連接點對象:"
+joinPoint.getTarget().getClass().getSimpleName());
System.out.println(
"連接點方法:"
+joinPoint.getSignature());
System.out.println(
"連接點方法參數:"
+joinPoint.getArgs()[
0
]);
}
}
2.後置增強處理
特點:在目標方法正常執行(不出現異常)後織入增強處理。
<aop:after-returning method="afterReturning" pointcut-ref="servicePointcut"/>
如果需要獲取返回值,添加returning="returnVal"
<aop:after-returning method="aft" pointcut-ref="ser" returning="returnVal"/>
1 2 3public
void
afterService(Object returnVal){
System.out.println(returnVal);
}
3.異常增強處理
特點:在目標方法出現異常後織入增強處理。
<aop:after-throwing mehod=" " pointcut-ref=" " throwing ="ex"/>
如果需要獲取異常對象才添加throwing="ex"
1 2 3public
void
afterThrowing(Exception ex){
System.out.println(ex.getMessage());
}
4.最終增強處理
特點:不論方法是否拋異常,都會在目標方法最後織如增強處理,類似與finally。
<aop:after method="after" pointcut-ref="servicePointcut"/>
5.環繞增強處理
特點:在目標方法的前後都可以織入增強處理。
<aop:around method="" pointcut-ref="" />
1 2 3 4 5 6 7 8 9public
Boolean around(ProceedingJoinPoint pjp)
throws
Throwable{
System.out.println(
"目標方法的參數:"
+pjp.getArgs()[
0
]);
Boolean b =
null
;
if
(
true
) {
b = (Boolean) pjp.proceed(pjp.getArgs());
}
return
b;
}
Spring的AOP配置常有兩種方式:
>通過schema形式實現簡單AOP配置,也就是上面事例使用方法。
>使用annotation簡化AOP配置。
AspectJ是一個面向切面的框架,AspectJ定義了AOP語法。
使用@AspectJ必須使用jdk5.0以上版本。
步驟:
1.編寫業務類(與上面方法相同)。
2.編寫切面類。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26package
com.jbit.ssh.aop;
import
org.aspectj.lang.annotation.After;
import
org.aspectj.lang.annotation.Aspect;
import
org.aspectj.lang.annotation.Before;
@Aspect
//1.通過注解標記一個切面
public
class
AspectTest {
@Before
(
"execution(* com.jbit.ssh.service..*.*(..))"
)
//2.定義切點和增強類型(切點表達式)
public
void
ba(){
//3.增強處理的fun 4.配置xml
System.out.println(
"前置增強-------"
);
}
@After
(
"execution(* com.jbit.ssh.service..*.*(..))"
)
public
void
aa(){
System.out.println(
"後置增強------"
);
}
/**
* @before表示前置增強
* @AfterReturning:表示後置增強處理
* @Around:表示環繞增強處理
* @AfterThrowing:表示異常增強處理
* @After:表示最終增強處理
*/
}
3.編寫配置文件實現AOP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24<?xml version=
"1.0"
encoding=
"UTF-8"
?>
<!--
- Application context definition
for
JPetStore's business layer.
- Contains bean references to the transaction manager and to the DAOs in
- dataAccessContext-local/jta.xml (see web.xml's
"contextConfigLocation"
).
-->
<beans xmlns=
"http://www.springframework.org/schema/beans"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
<span style=
"color: rgb(255, 0, 0);"
>xmlns:aop=
"http://www.springframework.org/schema/aop"
</span>
xmlns:tx=
"http://www.springframework.org/schema/tx"
xmlns:p=
"http://www.springframework.org/schema/p"
xmlns:context=
"http://www.springframework.org/schema/context"
xsi:schemaLocation="
http:
//www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http:
//www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
<span style=
"color: rgb(255, 0, 0);"
>http:
//www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd</span>
http:
//www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd" >
<!--
4
.基於
@AspectJ
切面的驅動器 -->
<aop:aspectj-autoproxy />
<bean
class
=
"com.jbit.ssh.aop.AspectTest"
></bean>
</beans>