AOP 即面向切面編程。通常用來處理具有橫切性質的系統級別服務,比如事務,安全,緩存等。
AOP 代理主要分爲兩大類:
靜態代理:使用 AOP 框架提供的命令進行編譯,從而在編譯階段就可生成 AOP 代理類,因此也稱爲編譯時增強;靜態代理以 AspectJ 爲代表。
動態代理:在運行時藉助於 JDK 動態代理、CGLIB 等在內存中“臨時”生成 AOP 動態代理類,因此也被稱爲運行時增強。Spring AOP 用的就是 動態代理。
AspectJ靜態代理就不介紹了。
下面介紹動態代理的兩種方式。
第一種:JDK動態代理
代碼如下
接口
package com.cbf4life; /** * Created by Maggie on 2017/6/7. */ public interface Bean { void print(); }實現累
package com.cbf4life.common; import com.cbf4life.Bean; /** * Created by Maggie on 2017/6/7. */ public class TargetBean implements Bean{ private String name; public TargetBean(){} public TargetBean(String name){this.name = name;} public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public void print(){ System.out.println("hello world"); } }
代理工廠
package com.cbf4life; import com.cbf4life.common.TargetBean; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * Created by Maggie on 2017/6/7. */ public class ProxyFactory implements InvocationHandler { private Object bean; public Object createBeanProxy(Object be){ this.bean = be; return Proxy.newProxyInstance(be.getClass().getClassLoader(), be.getClass().getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { TargetBean s = (TargetBean)bean; Object object = null; if(s.getName() != null) object = method.invoke(bean, args); else System.out.println("名字爲空,代理類已經攔截!"); return object; } }
這就是JDK動態代理,下面是解釋
- 目標對象必須實現接口。
- 調用Proxy.newProxyInstance()方法,返回創建的代理對象。
- 由於該方法需要一個實現了InvocationHandler接口的對象,所以我們還要重寫該接口的invoke()方法。
- 我們的限制條件就可以放在這個invoke()方法中,當滿足條件,就調用method.invoke()真正的調用目標對象的方法,否則,不做任何事情,直接過濾。
第二種:CGLIB動態代理
需要jar包:
代碼實例
package com.cbf4life; import com.cbf4life.common.TargetBean; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.annotation.Target; import java.lang.reflect.Method; /** * Created by Maggie on 2017/6/7. */ public class CGlibProxyFactory implements MethodInterceptor { private Object object; public Object createTargetBean(Object object){ this.object = object; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(object.getClass()); enhancer.setCallback(this); return enhancer.create(); } public Object getObject() { return object; } public void setObject(Object object) { this.object = object; } @Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { TargetBean stu = (TargetBean)object; Object result = null; if(stu.getName() != null) result = methodProxy.invoke(object, args); else System.out.println("方法已經被攔截..."); return result; } }
總體來說,使用CGlib的方法和使用Proxy的方法差不多,只是Proxy創建出來的代理對象和目標對象都實現了同一個接口。而CGlib的方法則是直接繼承了目標對象。
下面是main方法的測試
public static void main(String[] args) { Bean stu1 = (Bean)(new ProxyFactory().createBeanProxy(new TargetBean())); Bean stu2 = (Bean)(new ProxyFactory().createBeanProxy(new TargetBean("aaa"))); TargetBean stu3 = (TargetBean)(new CGlibProxyFactory().createTargetBean(new TargetBean())); TargetBean stu4 = (TargetBean)(new CGlibProxyFactory().createTargetBean(new TargetBean("aaa"))); stu1.print(); stu2.print(); stu3.print(); stu4.print(); }