1.面向切面编程的思想
(1).好处:
(2).实现:基于代理模式(动态代理)实现的
2.代理模式(委托类:真正干活的那个,代理类:只能使用接口,代理接口)
(1).静态代理:
委托类:真正干活的那个
public class War implements IWar {
@Override
public void play() {
System.out.println("玩游戏");
}
@Override
public void chat() {
System.out.println("聊天");
}
}
代理类:在代理类里面添加东西,保证委托类的无污染
public class ProxyWar implements IWar{
private IWar target;//拿到接口,目标对象
public ProxyWar(IWar target) {
super();
this.target = target;
}
@Override
public void play() {
charge();//添加的操作
target.play();
}
@Override
public void chat() {
System.out.println("开会员");
}
private void charge(){
System.out.println("收费");
}
}
代理接口:
public interface IWar {
public void play();
public void chat();
}
静态代理类优缺点
优点:开闭原则,对添加开启,对修改关闭,保证代码的重用性业务类只需要关注业务逻辑本身,保证了业务类的重用性。这是代理的共有优点。
缺点:
1)代理对象的一个接口只服务于一种类型的对象,如果要代理的方法很多,势必要为每一种方法都进行代理,静态代理在程序规模稍大时就无法胜任了。
2)如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。
(2).JDK动态代理:实现InvocationHandler接口
public class ProxyWar implements InvocationHandler{
private IWar target;
public ProxyWar(IWar target) {
super();
this.target = target;
}
private void charge(){
System.out.println("收费");
}
/**
* 执行方法的两种方式
* 1.obj.method(args)通过对象来调用
* 2.method.invoke(obj,args)
* 好处:可以处理方法,执行目标对象时对其中的方法进行过滤(增强)advice,统一管理方法,决定哪些方法需要增强,哪些不用
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if(method.getName().equals("play")){
charge();
}
return method.invoke(target, args);//让目标方法执行
}
}
优点:灵活的处理目标对象中的方法,处理哪些需要增强,不需要像静态代理那样在每个方法种进行中转处理
缺点:是基于接口代理的,如果目标对象没有接口就搞不定了
(3).CGLIB动态代理:
CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。不能定义成final,否则没有子类
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
public class ProxyWar implements MethodInterceptor {
private void charge(){
System.out.println("收费");
}
@Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
if(method.getName().equals("play")){
charge();
}
return methodProxy.invokeSuper(obj, args);
}
}
测试主函数
import org.springframework.cglib.proxy.Enhancer;
public class Test {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(War.class);
enhancer.setCallback(new ProxyWar());
War war = (War)enhancer.create();
war.play();
}
}