SpringAOP
Aspect Oriented Programming 面向切面编程
Object Oriented Programming面向对象编程
拦截器、过滤器
都是基于代理模式
单例模式、简单工厂模式、代理模式
代理模式介绍:
静态代理:
让目标对象和代理类实现同一个接口,目的是让客户端访问的时候行为是一致。
这其实就是一种保护(对目标对象的保护),控制对具体目标对象的访问,这个时候就由代理说了算。
在代理对象里面转调目标对象之前和之后做一些事(打印日志、权限控制等),
这样就方便为原有的功能添加新的功能,这就是代理模式。
Proxy:代理对象,通常具有以下功能(秘书)
1、
实现与具体的目标对象一样的接口,这样就可以是使用代理来代替具体的目标对象。(外界访问时候秘书也具有董事长相同功能)
2、保存一个具体的目标对象引用,可以在需要的时候调用具体的目标对象的方法。
3、可以控制对具体目标对象的访问。权限控制、日志处理。
public
interface IQianZi {
public
void qianzi();
}
public
class DongShiZhang
implements IQianZi{
@Override
public
void qianzi() {
System.
out.println(
"DongShiZhang.qianzi()");
}
}
public
class MiShu
implements IQianZi{
private DongShiZhang
dongShiZhang;
public MiShu(DongShiZhang
dongShiZhang) {
this.
dongShiZhang =
dongShiZhang;
}
@Override
public
void qianzi() {
// 判断是否合法
System.
out.println(
"MiShu.qianzi() befoe
开启事物
");
dongShiZhang.qianzi();
System.
out.println(
"MiShu.qianzi() after
事物关闭
");
// ...
}
}
public
class Client {
public
static
void main(String[]
args) {
DongShiZhang
dongShiZhang =
new DongShiZhang();
IQianzi
miShu =
new
MiShu(
dongShiZhang);
miShu.qianzi();
}
}
MiShu.qianzi() befoe
DongShiZhang.qianzi()
MiShu.qianzi() after
静态代理:
优点:
可以做到不修改目标对象的前提下,对目标对象的功能进行扩展
(目标对象董事长只要关注签字,像开启事物和关闭事物的操作都交给秘书处理)。
缺点:
1、代理对象Proxy对象和目标对象实现相同的接口,有一个目标对象就要有一个代理对象,会产生
很多代理类,类太多。
2、一旦接口增加方法,目标对象和代理对象都要去维护。
动态代理(JDK代理):
1)不需要自己写代理对象,但是目标对象还是需要实现接口;
2)代理对象的生成,是利用JDKAPI, 动态的在内存中构建代理对象(需要我们指定创建 代理对象/目标对象 实现的接口的类型;);
3) 动态代理也叫:JDK代理,
接口代理;
JDK中生成代理对象的API:
|-- Proxy java.lang.reflect.Proxy
static Object newProxyInstance(
ClassLoader loader, 指定当前
目标对象使用类加载器
Class<?>[] interfaces, 目标对象实现的接口的类型
InvocationHandler h 事件处理器
)
public
class ProxyFactory {
/**
* 得到代理对象
*
@param
object 目标对象
*
@return
代理对象
*/
public
static Object getProxyInstance(Object
target) {
return Proxy.
newProxyInstance(
target.getClass().getClassLoader(),
// 指定目标对象使用的类加载器
target.getClass().getInterfaces(),
// 目标对象实现的接口
new InvocationHandler() {
// 事件处理器
// Object
proxy
代理对象
// Method method 调用的方法
// Object[]
args
调用的方法的参数
@Override
public Object invoke(Object
proxy, Method
method, Object[]
args)
throws Throwable {
System.
out.println(
"开启事物");
Object
returnValue =
method.invoke(
target,
args);
System.
out.println(
"关闭事物");
return
returnValue;
}
});
}
}
// 目标对象
IQianZi
target =
new DongShiZhang();
// 给目标对象创建代理对象
IQianZi
proxy = (IQianZi) ProxyFactory.
getProxyInstance(
target);
proxy.qianzi();
动态代理的优点和缺点:
优点:不需要自己去创建代理类。
缺点:但是目标对象一定要实现接口,否则不能用动态代理。
Cglib代理:
也叫做子类代理。在内存中构建一个子类对象从而实现对目标对象功能的扩展。
JDK的动态代理有一个限制,就是使用动态代理的对象必须实现一个或多个接口。如果想代理不实现接口,就可以使用CGLIB实现。
Cglib代理要求:
目标对象不能为final, 否则报错。
目标对象的方法如果为final/static, 那么就不会被拦截,即不会执行目标对象额外的业务方法。
在Spring的AOP编程中,
如果加入容器的目标对象有实现接口,用动态代理(JDK代理);
如果目标对象没有实现接口,用Cglib代理;
AOP:Aspect Oriented Programming 面向切面编程
OOP:Object Oriented Programming
功能:让关注点(事物处理、权限、日志)和业务代码分离。
事物:逻辑上的一组操作,保证要么同时成功,要么同时失败(失败之后会回滚) 例子:A给B转账,
设计到两条sql语句,一个是A账户减100,另一个是B账户加100,这个过程卸在Service层,
所以在Service层都会加上事物。
public void transfer(A a, B b, double money) {
// 开启事物
调用dao代码:a-100;
调用dao代码:
b+100;
// 关闭事物
}
MyBatis:动态代理的功能:通过拦截器拦截,对目标target方法进行增强。