一.AOP(面向切面編程)的四種實現分別爲最原始的經典AOP、代理工廠bean(ProxyFacteryBean)和默認自動代理DefaultAdvisorAutoProxyCreator以及BeanNameAutoProxyCreator代理、Aspectj的註解和xml配置文件。java
1.代理工廠bean(ProxyFacteryBean)的方式正則表達式
1.1 接口(Interface)spring
1 package cn.happy.interfaces; 2
3 public interface Advice { 4
5 public void fristMethod(); 6
7 public String secondMethod(); 8 }
1.2 接口的實現類express
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 前置加強app
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 環繞加強this
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 異常加強spa
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面向切面編程思想有更深的瞭解。