javascript
Spring AOP解析
AOP: Aspect Oriented Programming 面向切面編程。
AOP底層實現原理:代理模式
什么是代理模式?
通過代理控制對象的訪問,可以詳細訪問某個對象的方法,在這個方法調用處理,或調用后處理。既(AOP微實現) ,AOP核心技術面向切面編程。
代理模式分為靜態代理與動態代理
?
靜態代理:
什么是靜態代理?
由程序員創建或工具生成代理類的源碼,再編譯代理類。所謂靜態也就是在程序運行前就已經存在代理類的字節碼文件,代理類和委托類的關系在運行前就確定了。
通過別的類B代理這個類A,這個類的具體情況,調用的類C并不知道
?
動態代理:
什么是動態代理?
1.代理對象,不需要實現接口
2.代理對象的生成,是利用JDK的API,動態的在內存中構建代理對象(需要我們指定創建代理對象/目標對象實現的接口的類型)
3.動態代理也叫做:JDK代理,接口代理
?
JDK動態代理:
實現方式:
1.通過實現InvocationHandler接口創建自己的調用處理器 IvocationHandler handler = new InvocationHandlerImpl(…);
2.通過為Proxy類指定ClassLoader對象和一組interface創建動態代理類Class clazz = Proxy.getProxyClass(classLoader,new Class[]{…});
3.通過反射機制獲取動態代理類的構造函數,其參數類型是調用處理器接口類型Constructor constructor = clazz.getConstructor(new Class[]{InvocationHandler.class});
4.通過構造函數創建代理類實例,此時需將調用處理器對象作為參數被傳入Interface Proxy = (Interface)constructor.newInstance(new Object[] (handler));
需要被代理的類:
public interface Subject {public void rent();public void hello(String str); } public class RealSubject implements Subject {@Overridepublic void rent(){System.out.println("I want to rent my house");}@Overridepublic void hello(String str){System.out.println("hello: " + str);} }動態代理類:
public class DynamicProxy implements InvocationHandler {// 這個就是我們要代理的真實對象private Object subject;// 構造方法,給我們要代理的真實對象賦初值public DynamicProxy(Object subject){this.subject = subject;}@Overridepublic Object invoke(Object object, Method method, Object[] args)throws Throwable{// 在代理真實對象前我們可以添加一些自己的操作System.out.println("before rent house");System.out.println("Method:" + method);// 當代理對象調用真實對象的方法時,其會自動的跳轉到代理對象關聯的handler對象的invoke方法來進行調用method.invoke(subject, args);// 在代理真實對象后我們也可以添加一些自己的操作System.out.println("after rent house");return null;} }調用:
public static void main(String[] args){// 我們要代理的真實對象Subject realSubject = new RealSubject();// 我們要代理哪個真實對象,就將該對象傳進去,最后是通過該真實對象來調用其方法的InvocationHandler handler = new DynamicProxy(realSubject);/** 通過Proxy的newProxyInstance方法來創建我們的代理對象,我們來看看其三個參數* 第一個參數handler.getClass().getClassLoader(),我們這里使用handler這個類的ClassLoader對象來加載我們的代理對象* 第二個參數realSubject.getClass().getInterfaces(),我們這里為代理對象提供的接口是真實對象所實行的接口,表示我要代理的是該真實對象,這樣我就能調用這組接口中的方法了* 第三個參數handler,我們這里將這個代理對象關聯到了上方的 InvocationHandler 這個對象上*/Subject subject = (Subject)Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), handler);System.out.println(subject.getClass().getName());subject.rent();subject.hello("world");}結果:
$Proxy0before rent house Method:public abstract void com.xiaoluo.dynamicproxy.Subject.rent() I want to rent my house after rent housebefore rent house Method:public abstract void com.xiaoluo.dynamicproxy.Subject.hello(java.lang.String) hello: world after rent house總結:AOP主要是通過InvocationHandler(Interface)和 Proxy(Class)來實現
invoke是InvocationHandler的唯一方法
?
通過被代理的類,接口,以及我們實現的InvocationHandler作為參數,調用newProxyInstance
這樣就把完成了代理
調用時通過invoke方法進行處理,我們可以在處理前后加上一些其他處理。
?
?
CGLIB動態代理:
public class CglibProxy implements MethodInterceptor {private Object targetObject;// 這里的目標類型為Object,則可以接受任意一種參數作為被代理類,實現了動態代理public Object getInstance(Object target) {// 設置需要創建子類的類this.targetObject = target;Enhancer enhancer = new Enhancer();enhancer.setSuperclass(target.getClass());enhancer.setCallback(this);return enhancer.create();} ?public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("開啟事物");Object result = proxy.invoke(targetObject, args);System.out.println("關閉事物");// 返回代理對象return result;}public static void main(String[] args) {CglibProxy cglibProxy = new CglibProxy();UserDao userDao = (UserDao) cglibProxy.getInstance(new UserDao());userDao.save();} }java動態代理是利用反射機制生成一個實現代理接口的匿名類,在調用具體方法前調用InvokeHandler來處理。
而cglib動態代理是利用asm開源包,對代理對象類的class文件加載進來,通過修改其字節碼生成子類來處理。
?
編程中注解的AOP實現:
@Component @Aspect public class AopLog { ?// 前置通知@Before("execution(* com.service.UserService.add(..))")public void begin() {System.out.println("前置通知");} ? ?// 后置通知@After("execution(* com.service.UserService.add(..))")public void commit() {System.out.println("后置通知");} ?// 運行通知@AfterReturning("execution(* com.service.UserService.add(..))")public void returning() {System.out.println("運行通知");} ?// 異常通知@AfterThrowing("execution(* com.service.UserService.add(..))")public void afterThrowing() {System.out.println("異常通知");} ?// 環繞通知@Around("execution(* com.service.UserService.add(..))")public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {System.out.println("環繞通知開始");proceedingJoinPoint.proceed();System.out.println("環繞通知結束");} }?
總結
以上是生活随笔為你收集整理的Spring AOP解析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 7-2 是否完全二叉搜索树 (30分)
- 下一篇: js正则检测输入内容为数字,包括负数,整