代理模式是springAOP的底层
静态代理模式角色分析
抽象角色:一般会使用接口或者抽象类来解决
真实角色:被代理的角色
代理角色:代理真实角色,代理真实角色后,我们一般会做一些附属操作
客户:访问代理对象的人
步骤:
1.接口
//租房
public interface Rent {
public void rent();
}
2.真实角色
//房东
public class Host implements Rent{
@Override
public void rent() {
System.out.println("房东要出租房子");
}
}
3.代理角色
/代理 中介
public class HostProxy {
private Host host;
public HostProxy() {
}
public HostProxy(Host host) {
this.host = host;
}
public void rent(){
host.rent();
}
//看房
public void seeHouse(){
System.out.println("看房");
}
//收中介费
public void fare(){
System.out.println("收中介费");
}
}
4.客户端访问代理角色
public class Client {
public static void main(String[] args) {
//房东
Host host = new Host();
//代理房东
HostProxy hostProxy = new HostProxy(host);
//中介出租房子
hostProxy.rent();
//代理角色的附属操作
hostProxy.seeHouse();
hostProxy.fare();
}
}
代理模式的好处:
可以使真实角色的操作更加纯粹!不用去关注一些公共的业务
公共的业务交给代理角色,实现了业务的分工
公共业务发生扩展的时候,方便集中管理
缺点:
一个真实角色就会产生一个代理角色:代码量翻倍 开发效率会变低
加深理解
动态代理和静态代理角色一样
动态代理的的代理类是动态生成的,不是我们直接写好的
动态代理分为两大类:基于接口的动态代理,基于类的动态代理
基于接口–JDK动态代理 我们在这里使用
基于类:cglib
java字节码实现javassist
需要了解反射包下的两个类 类 Proxy 代理, 接口 InvocationHandler 调用处理程序
代码:
角色接口不变
角色接口实现类 可创建多个
代理类处理程序
//会用这个类自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler {
//被代理的接口
private Object target;
public void setTarget(Object target) {
this.target = target;
}
//生成得到代理类
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}
@Override
//处理代理实例,并返回结果
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//动态代理的本质,就是使用反射机制实现!
log(method.getName());
Object result = method.invoke(target, args);
return result;
}
public void log(String msg){
System.out.println("执行了" + msg +"方法");
}
}
顾客 client
public class Client {
public static void main(String[] args) {
//真实角色
Host host = new Host();
//代理角色
ProxyInvocationHandler handler = new ProxyInvocationHandler();
//通过调用程序处理角色来处理我们要调用的接口对象
handler.setRent(host);
Rent proxy = (Rent) handler.getProxy();//这里的proxy是动态生成的
proxy.rent();
}
}
动态代理的好处:
可以使真实角色的操作更加纯粹!不用去关注一些公共的业务
公共的业务交给代理角色,实现了业务的分工
公共业务发生扩展的时候,方便集中管理
一个动态代理类代理的是一个接口,,一般就是对应的一类业务
一个动态代理类可以代理多个类,只要是实现了同一个接口即可!
面向切面编程:通过预编译方式和运行期工台代理实现程序功能的统一维护的一种技术。是面向对象的延续
重点:使用AOP织入,需要导入一个依赖包
方式一:使用spring的API接口org.aspectj aspectjweaver1.9.5
接口UserService
接口实现类UserServiceImpl
前置 通知
public class Log implements MethodBeforeAdvice {
//method 要执行的目标对象的方法
//args:参数
//target 目标对象
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println(target.getClass().getName()+"的"+method.getName()+"被执行类");
}
}
后置通知
public class AfterLog implements AfterReturningAdvice {
//returnValue 返回值
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("执行了"+method.getName()+"方法,返回结果为"+returnValue);
}
}
xml方式注册AOP bean 配置aop切入点
测试
public class MyTest {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//动态代理的是接口
UserService userService = (UserService) context.getBean("userService");
userService.add();
}
}
方式二 自定义类实现AOP
横切关注点为自定义切面类
public class DiyPointCut {
切面类中的方法为通知
public void before(){
System.out.println("========方法执行前=======");
}
public void after(){
System.out.println("========方法执行后=======");
}
}
配置bean
讲通知在那里插入
方式三 使用注解实现
//使用注解方式实现AOP
//标注这个类是一个切面
@Aspect
public class Annotation {
@Before(value = "execution(* com.zxw.service.UserServiceImpl.*(..))")
public void before(){
System.out.println("========方法执行前=======");
}
@After(value = "execution(* com.zxw.service.UserServiceImpl.*(..))")
public void after(){
System.out.println("========方法执行后=======");
}
//在环绕增强中,我们可以给定一个参数,代表我们要获取处理切入的点
@Around(value = "execution(* com.zxw.service.UserServiceImpl.*(..))")
public void around(ProceedingJoinPoint jp) throws Throwable {
System.out.println("========环绕前=======");
//执行方法
Object proceed = jp.proceed();
System.out.println("========环绕后=======");
}
}
配置
测试如方式二



