AOP的實現有三種方式:java
l aop底層將採用代理機制進行實現。spring
l 接口 + 實現類 :spring採用 jdk 的動態代理Proxy。express
l 實現類:spring 採用 cglib字節碼加強。編程
JDK動態代理 對「裝飾者」設計模式 簡化。使用前提:必須有接口設計模式
1.目標類:接口 + 實現類框架
2.切面類:用於存通知 MyAspectide
3.工廠類:編寫工廠生成代理函數
4.測試測試
UserService.javaspa
package com.zk.a_jdk; public interface UserService { public void addUser(); public void updateUser(); public void deleteUser(); }
UserServiceImpl.java
package com.zk.a_jdk; public class UserServiceImpl implements UserService{ @Override public void addUser() { // TODO Auto-generated method stub System.out.println("proxy addUser"); } @Override public void updateUser() { // TODO Auto-generated method stub System.out.println("proxy updateUser"); } @Override public void deleteUser() { // TODO Auto-generated method stub System.out.println("proxy deleteUser"); } }
MyAspect.java
package com.zk.a_jdk; public class MyAspect { public void before(){ System.out.println("雞頭"); } public void after(){ System.out.println("牛後"); } }
package com.zk.a_jdk; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class MyBeanFactory { //手工代理 public static UserService createService(){ //1.目標類 final UserService userservice=new UserServiceImpl(); //2.切面類 final MyAspect myAspect=new MyAspect(); //3.代理類:將目標類(切入點)和切面類(通知)結合-->切面 //Proxy.newProxyInstance /* * 參數一:loader類加載器,動態代理類,運行時建立,任何類都須要類加載器將其加載至內存。 * 通常狀況下:當前類,class.getClassLoader(); * 目標類實例:getClass().get... * 參數二:interfaces,代理類須要實現的全部接口 * 方式一:目標類實例.getClass().getInterfaces();注意:只能得到本身的接口,得到不到父元素的接口 * 方式二:new Class[]{UserService.class} * 例如:jdbc驅動 * 參數三:InvocationHandler 處理類,接口,必須進行實現類,通常採用匿名內部類 * 提供invoke方法,代理類每個方法執行時,都將去調用invoke * 參數三.1.Object proxy代理對象 * 參數三.2.Method method 代理對象當前方法的描述對象(反射) * 執行方法方法名:method.getName(); * 執行方法:method.invoke(對象,實際參數) * 參數三.3 Object[] args 方法實際參數 */ UserService proxyService=(UserService)Proxy.newProxyInstance (MyBeanFactory.class.getClassLoader(), userservice.getClass().getInterfaces(), new InvocationHandler(){ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub //前執行 myAspect.before(); //執行目標類的方法 Object obj=method.invoke(userservice, args); //後執行 myAspect.after(); return null; } }); return proxyService; } }
package com.zk.a_jdk; import org.junit.Test; public class TestJDK { @Test public void test(){ UserService userservice=MyBeanFactory.createService(); userservice.addUser(); userservice.deleteUser(); userservice.updateUser(); } }
運行效果:
l 沒有接口,只有實現類。
l 採用字節碼加強框架 cglib,在運行時 建立目標類的子類,從而對目標類進行加強。
l 導入jar包:
UserService.java
package com.zk.a_jdk; public interface UserService { public void addUser(); public void updateUser(); public void deleteUser(); }
UserServiceImpl.java
package com.zk.a_jdk; public class UserServiceImpl implements UserService{ @Override public void addUser() { // TODO Auto-generated method stub System.out.println("proxy addUser"); } @Override public void updateUser() { // TODO Auto-generated method stub System.out.println("proxy updateUser"); } @Override public void deleteUser() { // TODO Auto-generated method stub System.out.println("proxy deleteUser"); } }
MyAspect.java
package com.zk.a_jdk; public class MyAspect { public void before(){ System.out.println("雞頭"); } public void after(){ System.out.println("牛後"); } }
package com.zk.b_cglib; import java.lang.reflect.Method; import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; public class MyBeanFactory { //手工代理 public static UserService createService(){ //1.目標類 final UserServiceImpl userservice=new UserServiceImpl(); //2.切面類 final MyAspect myAspect=new MyAspect(); /*3.代理類 * 採用字節碼加強框架-cglib,程序運行時建立目標類的子類,從而對目標類進行加強 * 導入jar包 * intercept等效於jdk中invoke方法 * 參數一二三 與invoke相同 * 參數四方法的代理 */ Enhancer enhance=new Enhancer(); //肯定父類 enhance.setSuperclass(userservice.getClass()); enhance.setCallback(new MethodInterceptor(){ //設置回調函數,MethodInterceptor接口等效 jdk InvocationHandler接口 @Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodproxy) throws Throwable { // TODO Auto-generated method stub //前before myAspect.before(); //執行目標類的方法 Object obj=method.invoke(userservice, args); //執行代理類的父類 methodproxy.invokeSuper(proxy, args); //後after myAspect.after(); return null; } }); //建立代理 UserServiceImpl proxyservice=(UserServiceImpl) enhance.create(); return proxyservice; } }
package com.zk.b_cglib; import org.junit.Test; public class Testcglib { @Test public void test(){ UserService userservice=MyBeanFactory.createService(); userservice.addUser(); userservice.deleteUser(); userservice.updateUser(); } }
運行效果圖:
讓spring 建立代理對象,從spring容器中手動的獲取代理對象。
導入jar包:
AOP:AOP聯盟(規範)、spring-aop (實現)
UserService.java
public interface UserService { public void addUser(); public void updateUser(); public void deleteUser(); }
UserServiceImpl.java
package com.zk.springAop; public class UserServiceImpl implements UserService{ @Override public void addUser() { // TODO Auto-generated method stub System.out.println("addUser"); } @Override public void updateUser() { // TODO Auto-generated method stub System.out.println("updateUser"); } @Override public void deleteUser() { // TODO Auto-generated method stub System.out.println("deleteUser"); } }
/** * 切面類中肯定通知,須要實現不一樣接口,接口就是規範,從而就肯定方法名稱。 * * 採用「環繞通知」 MethodInterceptor * */ public class MyAspect implements MethodInterceptor { @Override public Object invoke(MethodInvocation mi) throws Throwable { System.out.println("前3"); //手動執行目標方法 Object obj = mi.proceed(); System.out.println("後3"); return obj; } }
<?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: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-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd "> <!-- 建立目標類 --> <bean id="userserviceid" class="com.zk.factorybean.UserServiceImpl"></bean> <!-- 建立切面類 --> <bean id="aspectid" class="com.zk.factorybean.MyAspect"></bean> <!-- 建立代理類 使用工廠bean factorybean,底層調用getObject(), 返回特殊bean ProxyBeanFactory用於建立代理工廠bean,生成特殊代理對象 interface肯定接口 經過Array肯定多個值 只有一個值時,value="" target肯定目標類 interceptorNames:通知切面類名稱,類型String[],若是設置一個值, value="" optimize:強制使用cglib <property name="optimized value="true"></property> 底層機制: 若是目標類有接口,採用jdk代理 若是沒有接口,採用cglib代理 若是聲明式optimize=true,都使用cglib --> <bean id="proxyServiceid" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="interfaces" value="com.zk.factorybean.UserService"></property> <property name="target" ref="userserviceid"></property> <property name="interceptorNames" value="aspectid"></property> </bean> </beans>
package com.zk.factorybean; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Testfactorybean { @Test public void test(){ String path="com/zk/factorybean/ApplicationContext.xml"; ApplicationContext ac=new ClassPathXmlApplicationContext(path); UserService userservice=(UserService) ac.getBean("proxyServiceid"); userservice.addUser(); userservice.deleteUser(); userservice.updateUser(); } }
運行效果:
從spring容器得到目標類,若是配置aop,spring將自動生成代理。
要肯定目標類,aspectj 切入點表達式,導入jar包spring-framework-3.0.2.RELEASE-dependencies\org.aspectj\com.springsource.org.aspectj.weaver\1.6.8.RELEASE
UserService.java
public interface UserService { public void addUser(); public void updateUser(); public void deleteUser(); }
UserServiceImpl.java
package com.zk.springAop; public class UserServiceImpl implements UserService{ @Override public void addUser() { // TODO Auto-generated method stub System.out.println("addUser"); } @Override public void updateUser() { // TODO Auto-generated method stub System.out.println("updateUser"); } @Override public void deleteUser() { // TODO Auto-generated method stub System.out.println("deleteUser"); } }
/** * 切面類中肯定通知,須要實現不一樣接口,接口就是規範,從而就肯定方法名稱。 * * 採用「環繞通知」 MethodInterceptor * */ public class MyAspect implements MethodInterceptor { @Override public Object invoke(MethodInvocation mi) throws Throwable { System.out.println("前3"); //手動執行目標方法 Object obj = mi.proceed(); System.out.println("後3"); return obj; } }
<?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:p="http://www.springframework.org/schema/p" 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-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd "> <!-- 建立目標類 --> <bean id="userserviceid" class="com.zk.springAop.UserServiceImpl"></bean> <!-- 建立切面類 --> <bean id="aspectid" class="com.zk.springAop.MyAspect"></bean> <!-- Aop編程 1.導入命名空間 2.使用<aop:config>進行配置 proxy-target-class="true"聲明是使用cglib代理 <aop:pointcut>:切入點,從目標對象上獲取具體的方法 <aop:advisor>特殊的切面,只有一個通知和一個切入點 advise-ref 通知引用 pointcut-ref 切入點引用 advisor通知 3.切入點表達式 execution(* com.zk.springAop.*.*(..)) 選擇方法 *表示返回值任意 包 類名任意. 方法名任意 . 參數任意 . --> <aop:config> <aop:pointcut expression="execution(* com.zk.springAop.*.*(..))" id="myPointCut"/> <aop:advisor advice-ref="aspectid" pointcut-ref="myPointCut"/> </aop:config> </beans>