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