一.AOP(面向切面編程)的四種實現分別為最原始的經典AOP、代理工廠bean(ProxyFacteryBean)和默認自動代理DefaultAdvisorAutoProxyCreator以及BeanNameAutoProxyCreator代理、Aspectj的注解和xml配置文件。
1.代理工廠bean(ProxyFacteryBean)的方式
1.1 接口(Interface)
1 package cn.happy.interfaces;
2
3 public interface Advice {
4
5 public void fristMethod();
6
7 public String secondMethod();
8 }
1.2 接口的實現類
1 package cn.happy.impl;
2
3 import cn.happy.interfaces.Advice;
4
5 public class AdviceImpl implements Advice {
6
7 public void fristMethod() {
8 System.out.println("==fristMethod==");
9 }
10
11 public String secondMethod() {
12 System.out.println("==secondMethod==");
13 return "abc";
14 }
15
16 }
1.3 各種通知增強
1.3.1 前置增強
1 package cn.happy.advice;
2
3 import java.lang.reflect.Method;
4
5 public class MethodBeforeAdvice implements
6 org.springframework.aop.MethodBeforeAdvice {
7
8 public void before(Method arg0, Object[] arg1, Object arg2)
9 throws Throwable {
10 System.out.println("==Before==");
11
12 }
13
14 }
1.3.2 後置增強
1 package cn.happy.advice;
2
3 import java.lang.reflect.Method;
4
5 import org.springframework.aop.AfterReturningAdvice;
6
7 public class AfterReturningAdvie implements AfterReturningAdvice {
8
9 public void afterReturning(Object arg0, Method arg1, Object[] arg2,
10 Object arg3) throws Throwable {
11 System.out.println("==After==");
12
13 }
14
15 }
1.3.3 環繞增強
package cn.happy.aroundadvice;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class MyInterceptor implements MethodInterceptor{
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("==before==");
String result= (String)invocation.proceed();
System.out.println("==after==");
return result;
}
}
1.3.4 異常增強
package cn.happy.exception;
import org.springframework.aop.ThrowsAdvice;
public class MyException implements ThrowsAdvice {
public void afterThrowing(Exception ex){
System.out.println("異常通知");
}
}
1.4 配置文件
<?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: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 id="adviceimpl" class="cn.happy.impl.AdviceImpl"></bean>
<!-- 前置增強 通知-->
<bean id="advicebefore" class="cn.happy.advice.MethodBeforeAdvice"></bean>
<!-- 後置增強 通知-->
<bean id="adviceafter" class="cn.happy.advice.AfterReturningAdvie"></bean>
<!-- 環繞增強 -->
<bean id="around" class="cn.happy.aroundadvice.MyInterceptor"></bean>
<!-- 關聯 代理工廠bean ProxyFacteryBean 通知 -->
<!--<bean id="serviceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="targetName" value="adviceimpl"></property>
<property name="interceptorNames" value="advicebefore,adviceafter"></property>
</bean>-->
<!-- 環繞增強 代理工廠 顧問包裝通知 -->
<bean id="aroundserviceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="adviceimpl"></property>
<property name="interceptorNames" value="beforeadvisor"></property>
</bean>
<!-- 切面 通知 -->
<bean id="beforeadvice" class="cn.happy.mymethodbefore.MyMethodBeforeAdvice"></bean>
<!-- 顧問 包裝advice -->
<bean id="beforeadvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
<property name="advice" ref="beforeadvice"></property>
<property name="mappedNames" value="fristMethod,secondMethod"></property>
</bean>
<!-- 顧問 包裝advice 正則表達式-->
<!--<bean id="beforeadvisor1" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice" ref="beforeadvice"></property>
<property name="pattern" value=".*Method.*"></property>
</bean>-->
<!-- 默認自動代理 默認只找通知-->
<!--<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean>-->
<!-- beanname自動代理 可以選擇顧問或者通知-->
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames" value="adviceimpl"></property>
<property name="interceptorNames" value="beforeadvisor"></property>
</bean>
</beans>
1.5 測試類
package cn.happy.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import cn.happy.interfaces.Advice;
public class Test {
/**
* 通知的前置和後置測試
*/
public static void main(String[] args) {
//解析配置文件
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
Advice advice= (Advice)ctx.getBean("adviceimpl"); //自動代理beanname的方式
advice.fristMethod();
advice.secondMethod();
}
}
2. 最原始的經典AOP
2.1 最基本分層模式dao、biz、service以及最後測試Test
2.1.1DAO層
package cn.happy.dao;
import cn.happy.entity.User;
//接口
public interface UDao {
//保存方法
public void save(User user);
}
//實現類
package cn.happy.dao;
import cn.happy.entity.User;
public class UserDaoImpl implements UDao{
public void save(User user) {
System.out.println("保存成功");
}
}
2.1.2 BIZ層
package cn.happy.biz;
import cn.happy.entity.User;
//業務接口
public interface UBiz {
//保存方法
public void save2(User user);
}
//業務實現類
package cn.happy.biz;
import cn.happy.dao.UDao;
import cn.happy.entity.User;
public class UserBiz implements UBiz{
//dao的對象
private UDao udao;
public void save2(User user) {
udao.save(user);
}
public UDao getUdao() {
return udao;
}
public void setUdao(UDao udao) {
this.udao = udao;
}
}
2.1.3 AOP模塊即service層
package cn.happy.logger;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
//前置內容
public class LoggerBefore implements MethodBeforeAdvice {
public void before(Method arg0, Object[] arg1, Object arg2)
throws Throwable {
System.out.println("save前置內容");
}
}
//後置內容
package cn.happy.logger;
import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice;
public class LoggerAfter implements AfterReturningAdvice{
public void afterReturning(Object arg0, Method arg1, Object[] arg2,
Object arg3) throws Throwable {
System.out.println("save後置內容");
}
}
2.1.4 經典的配置文件
<?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-4.1.xsd">
<!-- 業務biz與dao接口對象的實現 -->
<bean id="dao" class="cn.happy.dao.UserDaoImpl"></bean>
<bean id="biz" class="cn.happy.biz.UserBiz">
<property name="udao" ref="dao"></property>
</bean>
<!-- 前置與後置內容的配置 -->
<bean id="before" class="cn.happy.logger.LoggerBefore"></bean>
<bean id="after" class="cn.happy.logger.LoggerAfter"></bean>
<!-- aop的配置 -->
<aop:config>
<aop:pointcut expression="execution(public void save2(cn.happy.entity.User))" id="pointcut"/>
<!-- 在切入點處插入增強處理、完成"織入" -->
<aop:advisor advice-ref="before" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="after" pointcut-ref="pointcut"/>
</aop:config>
</beans>
2.1.5 測試類
package cn.happy.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import cn.happy.biz.UBiz;
import cn.happy.entity.User;
public class AOPTest {
public static void main(String[] args) {
ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
UBiz ubiz=(UBiz)context.getBean("biz");
User user=new User();
ubiz.save2(user);
System.out.println("save~ok");
}
}
3. 然後就是Aspectj的注解以及xml配置文件的兩種方式了。
3.1 Aspectj注解
3.1.1 接口和實現類
package cn.happy.impl;
//接口
public interface AspectDao {
public void add();
public void delete();
}
//實現類
package cn.happy.impl;
public class AspectjIpml implements AspectDao{
//添加
public void add() {
System.out.println("==ADD==");
}
//刪除
public void delete() {
System.out.println("==DELETE==");
}
}
3.1.2 注解類Aspect
package cn.happy.aspectj;
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.Before;
@org.aspectj.lang.annotation.Aspect
public class Aspect {
//前置增強
@Before(value="execution(public * *(..))")
public void asBefore(){
System.out.println("這是前置增強");
}
//後置增強
@AfterReturning(value="execution(public * *(..))")
public void asAfterReturning(){
System.out.println("這是後置增強");
}
//環繞增強
@Around(value="execution(public * *(..))")
public void asAround(ProceedingJoinPoint pj){
System.out.println("這是環繞前置增強");
try {
pj.proceed();
} catch (Throwable e) {
//抓捕異常
e.printStackTrace();
}
System.out.println("這是環繞後置增強");
}
//異常增強
@AfterThrowing(value="execution(public * *(..))")
public void asThorws(){
System.out.println("這是異常增強");
}
//最終增強
@After(value="execution(public * *(..))")
public void asAfter(){
System.out.println("這是最終增強");
}
}
3.1.3 注解的配置文件
<?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: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.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 目標對象 -->
<bean id="aspectimpl" class="cn.happy.impl.AspectjIpml"></bean>
<!-- 增強類 -->
<bean id="aspectj" class="cn.happy.aspectj.Aspect"></bean>
<!-- 掃描整個項目 關聯注解類和實現類 -->
<aop:aspectj-autoproxy />
</beans>
3.1.4 測試類
package cn.happy.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import cn.happy.impl.AspectDao;
public class AspectjTest {
/**
* 注解測試 */
public static void main(String[] args) {
// 解析配置文件
ApplicationContext ctx = new ClassPathXmlApplicationContext(
"applicationContext.xml");
AspectDao aspect = (AspectDao) ctx.getBean("aspectimpl");
aspect.add();
aspect.delete();
}
}
4. Aspectj的XML配置法,其他的基本都一樣只要修改Aspectj增強類和配置文件就行了
4.1 Aspect增強類只需將那些注解消去即可
package cn.happy.aspectj;
import org.aspectj.lang.ProceedingJoinPoint;
public class Aspect {
//前置增強
public void asBefore(){
System.out.println("這是前置增強");
}
//後置增強
public void asAfterReturning(){
System.out.println("這是後置增強");
}
//環繞增強
public void asAround(ProceedingJoinPoint pj){
System.out.println("這是環繞前置增強");
try {
pj.proceed();
} catch (Throwable e) {
//抓捕異常
e.printStackTrace();
}
System.out.println("這是環繞後置增強");
}
//異常增強
public void asThorws(){
System.out.println("這是異常增強");
}
//最終增強
public void asAfter(){
System.out.println("這是最終增強");
}
}
4.2 XML的配置文件會稍微會復雜一點,但大致的還是跟對原始的經典aop實現方式相同
<?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: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.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 目標對象 -->
<bean id="aspectimpl" class="cn.happy.impl.AspectjIpml"></bean>
<!-- 增強類 -->
<bean id="aspectj" class="cn.happy.aspectj.Aspect"></bean>
<!-- Aspectj的XML配置文件 -->
<aop:config>
<aop:pointcut expression="execution(public * *(..))" id="pointcut"/>
<aop:aspect ref="aspectj">
<aop:before method="asBefore" pointcut-ref="pointcut"/>
<aop:after-returning method="asAfterReturning" pointcut-ref="pointcut"/>
<aop:after-returning method="asAround(org.aspectj.lang.ProceedingJoinPoint)" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>
</beans>
好了,這就是AOP(面向切面編程)的四種實現方式了。希望你們看了之後能讓你們對AOP面向切面編程思想有更深的了解。