AOP:Aspect Oriented Programming 面向切面编程,在Spring框架中被作为核心组成部分之一,最常见的就是事务控制,主要通过利用代理模式来实现。
代理原理说明:当客户端调用代理对象的业务方法的时候,代理对象将拦截所有业务方法,根据事先给出的权限规则,判断当前请求是否符合权限要求,在符合条件的情况下,再将业务方法委派给目标对象,执行方法体,实现事务控制管理(如图过程趋势大致走向)。
常见的三大代理模式:举例介绍&(附注释说明)
1、静态代理:即设计模式中的Proxy模式,example:
<1>业务接口:
public interface InterfaceProxy {
public String save(String name);
}
<2>业务实现(省略):
<3>代理对象:
/**
* 静态代理:要代理的类是自己写的,要实现代理功能,必须实现要代理的那个目标对象的接口
* 代理模式:为一些对象加入代理,以控制该对象的访问
* @author zhoujh
*/
public class StaticProxyFactory implements InterfaceProxy{
//要代理的目标对象
private InterfaceProxy target;
public StaticProxyFactory(InterfaceProxy target){
this.target = target;
}
@Override
public String save(String name) {
target.save(name);//组合代理要实现的目标对象接口方法
return name;
}
}
2、动态代理:jdk1.5中提供,利用反射,实现InvocationHandler接口。
/**
* JDK提供Proxy类创建动态代理对象
* 通过代理对象实现目标对象的所有接口,能将方法的调用委派给目标对象
* 使用代理类Proxy:应用的条件是目标对象必须是面向接口的,否则是不能应用JDK动态代理的 横切性关注点
* 应用原理:当客户端调用代理对象的业务方法的时候,代理对象就会执行invoke方法,执行过程中再将该方法委派给目标对象
* @author zhoujh
*/
public class JDKProxyFactory implements InvocationHandler {
public Object targetObject;
public Object createProxyInstance(Object targetObject) {
this.targetObject = targetObject;
/**
* new一个代理实例
*
* @param1:目标对象的类加载器
* @param2:目标对象的所有接口
* @param3:当前类实例本身:Handler(回调) 该参数表示接口
* 同时要求该回调实例必须实现InvocationHandler这个接口
*/
return Proxy.newProxyInstance(this.targetObject.getClass()
.getClassLoader(),
this.targetObject.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
InterfaceProxyIntance bean = (InterfaceProxyIntance)this.targetObject;
Object result = null;
if(bean.getUser()!= null){//代表该用户有权限,允许执行业务方法
result = method.invoke(targetObject, args);
}
return result;
}
}
3.利用cglib框架实现动态代理
/**
* CGlib动态代理
* @author zhoujh
*
*/
public class CglicProxyFactory {
//使用CGlib生成动态代理对象
public Object createProxyInstance(final Object target){
//加强 Proxy增加者
Enhancer enhancer = new Enhancer();
//指定目标对象作为代理对象的父类
enhancer.setSuperclass(target.getClass());
//定义回调方法
Callback callback = new MethodInterceptor() {
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2,
MethodProxy method) throws Throwable {
Object result = null;
System.out.println("begin....");
result = method.invoke(target, arg2);
System.out.println("end....");
return result;
}
};
//设置回调方法
enhancer.setCallback(callback);
//创建代理对象并返回
return enhancer.create();
}
}
4.普通类(非接口实现类):
public class RunnerService {
public void add(String name){
System.out.println("前方高能"+name);
}
}
5.接口实现类:
public class InterfaceProxyIntance implements InterfaceProxy{
private String user = null;
public String getUser() {
return user;
}
public InterfaceProxyIntance(){}
public InterfaceProxyIntance(String user){
this.user = user;
}
public String read() {
return "read()";
}
public String save(String name) {
return name;
}
}
6.测试:
public class ProxyTest {
public static void main(String[] args) {
//静态代理Test
StaticProxyFactory factory1 = new StaticProxyFactory(new InterfaceProxyIntance("hehe"));
System.out.println(factory1.save("888"));
//JDK动态代理Test
JDKProxyFactory factory = new JDKProxyFactory();
/**
* 注意:这里要通过接口去引用代理对象,因为该代理对象是实现了接口的
*/
InterfaceProxy proxy = (InterfaceProxy)factory.createProxyInstance(new InterfaceProxyIntance("xxx"));
System.out.println(proxy.save("888"));
//CGlib框架动态代理Test
CglicProxyFactory cg = new CglicProxyFactory();
InterfaceProxy proxy1 = (InterfaceProxy)cg.createProxyInstance("");
System.out.println(proxy1.save("8888"));
//非接口实现下的CGlib代理实现
RunnerService service = new RunnerService();
CglicProxyFactory cg1 = new CglicProxyFactory();
RunnerService service1 = (RunnerService)cg1.createProxyInstance(service);
service1.add("888");
}
}
spring对AOP的支持
*如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
*如果目标对象实现了接口,可以强制使用CGLIB实现AOP
*如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换