AOP是Aspect Oriented Programming的縮寫,意思是面向方面編程,與OOP(Object Oriented Programming)面向對象編程對等,都是一種編程思想。
從OOP角度分析,我們關注業務的處理邏輯,是屬於縱向的行爲,從AOP角度分析,我們關注對象行爲發生時的問題,是屬於橫向的行爲。
AOP 作用:
1 監控函數的調用
2 捕獲異常發生
實際應用在:事務、安全、日誌等橫切關注。
兩種實現AOP的方式:
1,JDK提供的動態代理實現
//接口
public interface UserBean
{
void getUser();
void addUser();
void updateUser();
void deleteUser();
}
//原始實現類
public class UserBeanImpl implements UserBean
{
private String user = null;
public UserBeanImpl()
{
}
public UserBeanImpl(String user)
{
this.user = user;
}
public String getUserName()
{
return user;
}
public void getUser()
{
System.out.println("this is getUser() method!");
}
public void setUser(String user)
{
this.user = user;
System.out.println("this is setUser() method!");
}
public void addUser()
{
System.out.println("this is addUser() method!");
}
public void updateUser()
{
System.out.println("this is updateUser() method!");
}
public void deleteUser()
{
System.out.println("this is deleteUser() method!");
}
}
//代理類
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import com.cignacmc.finance.bean.UserBeanImpl;
public class UserBeanProxy implements InvocationHandler
{
private Object targetObject;
public UserBeanProxy(Object targetObject)
{
this.targetObject = targetObject;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
UserBeanImpl userBean = (UserBeanImpl) targetObject;
String userName = userBean.getUserName();
Object result = null;
//權限判斷
if(userName != null && !"".equals(userName))
{
result = method.invoke(targetObject, args);
}
return result;
}
}
//測試類
import java.lang.reflect.Proxy;
import com.cignacmc.finance.bean.UserBean;
import com.cignacmc.finance.bean.UserBeanImpl;
import com.cignacmc.finance.proxy.UserBeanProxy;
public class ProxyExe
{
public static void main(String[] args)
{
System.out.println("Proved.............");
UserBeanImpl targetObject = new UserBeanImpl("Bob Liang");
UserBeanProxy proxy = new UserBeanProxy(targetObject);
//生成代理對象
UserBean object = (UserBean)Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
targetObject.getClass().getInterfaces(), proxy);
object.addUser();
System.out.println("NO Proved.............");
targetObject = new UserBeanImpl();
proxy = new UserBeanProxy(targetObject);
//生成代理對象
object = (UserBean)Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
targetObject.getClass().getInterfaces(), proxy);
object.addUser();
}
}
輸出:
Proved.............
this is addUser() method!
NO Proved.............
從上面這個例子可以成功攔截了調用的方法addUser()並對其做了相應的處理
2, 通過cglib創建代理類, 好處是不要求我們的目標對象實現接口
//原始類
public class ClientBean
{
private String name = null;
public ClientBean()
{
}
public ClientBean(String name)
{
this.name = name;
}
public void addClient()
{
System.out.println("this is addClient() method!");
}
public void deleteClient()
{
System.out.println("this is deleteClient() method!");
}
public void getClient()
{
System.out.println("this is getClient() method!");
}
public void updateClient()
{
System.out.println("this is updateClient() method!");
}
public String getClientName()
{
return name;
}
public void setClientName(String name)
{
this.name = name;
}
}
//代理類
import java.lang.reflect.Method;
import com.cignacmc.finance.bean.ClientBean;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CGLibProxy implements MethodInterceptor
{
private Object targetObject;
public Object createProxyObject(Object targetObject)
{
this.targetObject = targetObject;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.targetObject.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable
{
ClientBean clientBean = (ClientBean)targetObject;
String userName = clientBean.getClientName();
Object result = null;
if(userName != null && !"".equals(userName))
{
result = method.invoke(targetObject, args);
}
return result;
}
}
//測試類
import java.lang.reflect.Proxy;
import com.cignacmc.finance.bean.ClientBean;
import com.cignacmc.finance.bean.UserBean;
import com.cignacmc.finance.bean.UserBeanImpl;
import com.cignacmc.finance.proxy.CGLibProxy;
import com.cignacmc.finance.proxy.UserBeanProxy;
public class ProxyExe
{
public static void main(String[] args)
{
System.out.println(".............CGLIB Proxy....................");
System.out.println("Proved....................");
CGLibProxy cproxy = new CGLibProxy();
ClientBean clientBean = (ClientBean)cproxy.createProxyObject(new ClientBean("Bob Liang"));
clientBean.addClient();
System.out.println("NO Proved....................");
cproxy = new CGLibProxy();
clientBean = (ClientBean)cproxy.createProxyObject(new ClientBean());
clientBean.addClient();
}
}
輸出:
.............CGLIB Proxy....................
Proved....................
this is addClient() method!
NO Proved....................
切面(Aspect):對橫切關注點的抽象(類似類對對象的抽象)
連接點(JoinPoint):被攔截到的點,泛指方法
切入點(CutPoint):對哪些連接點進行攔截的定義
通知(Advice):在特定的連接點,AOP框架執行的動作.前置/後置/例外/最終/環繞通知(調用方法之前執行,全部執行完畢之後)
引入(Introduction): 添加方法或字段到被通知的類。 Spring允許引入新的接口到任何被通知的對象。例如,你可以使用一個引入使任何對象實現 IsModified接口,來簡化緩存。
目標對象(Target Object): 包含連接點的對象。也被稱作 被通知或被代理對象。
AOP代理(AOP Proxy): AOP框架創建的對象,包含通知。 在Spring中,AOP代理可以是JDK動態代理或者CGLIB代理。
織入(Weaving): 組裝方面來創建一個被通知對象。這可以在編譯時 完成(例如使用AspectJ編譯器),也可以在運行時完成。Spring和其他純Java AOP框架一樣, 在運行時完成織入。