文章目录
代理设计模式
静态代理
为每一个目标类手动编写一个代理类
问题:类文件太多,额外功能难维护
动态代理
动态字节码框架:ASM、CGlib
增强(额外功能):
- MethodInterceptor:事务、异常捕获
- MethodBeforeAdvice
切入点:切入点表达式
execution(修饰符 返回值 包.类.方法(参数))
切入点函数
args(String, String)
:execution(* *(String, String))
within(*..Class)
:execution(* *..Class.*(..))
within(xx.xx..*)
:execution(* xx.xx..*(..))
@annotation(注解全类名)
切入点函数的逻辑运算
- and:不能是同种类型的切入点函数
- or
AOP编程
AOP(Aspect Oriented Programing)面向切面编程(动态代理开发)
AOP是对OOP的增强补充
OOP:面向对象
POP:面向过程
切面 = 切点 + 增强
JDK动态代理
动态代理类没有字节码
public class TestJDKProxy {
public static void main(String[] args) {
UserService userService= new UserServiceImpl();
UserService proxy = (UserService) Proxy.newProxyInstance(UserServiceImpl.class.getClassLoader(), UserServiceImpl.class.getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("----proxy------");
return method.invoke(userService,args);
}
});
proxy.login("","");
}
}
Cglib
针对没有实现任何借口的类(通过继承)
public class TestCglib {
public static void main(String[] args) {
UserService userService = new UserService();
Enhancer enhancer =new Enhancer();
enhancer.setClassLoader(userService.getClass().getClassLoader());
enhancer.setSuperclass(userService.getClass());
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("------cglib-----");
return method.invoke(userService,objects);
}
});
UserService proxy = (UserService) enhancer.create();
proxy.hello();
}
}
两种动态代理的切换
- JDK动态代理:通过接口
- Cglib动态代理:通过继承
默认使用JDK动态代理
<aop:config proxy-target-class="true">
<aop:aspectj-autoproxy proxy-target-class="true"/>
- true:使用Cglib
- false:JDK动态代理(默认)
Spring处理原始对象
通过BeanPostProcessor
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return Proxy.newProxyInstance(getClass().getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("my before enhance");
return method.invoke(bean, args);
}
});
}
}
<bean class="com.tonkia.aop.UserServiceImpl"/>
<bean class="com.tonkia.aop.MyBeanPostProcessor"/>
基于注解的AOP
@Aspect
public class AspectJTest {
@Around("execution(* *(..))")
public Object enhance(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("-----aspectj-------");
Object ret = joinPoint.proceed();
return ret;
}
}
<bean class="com.tonkia.aop.UserServiceImpl"/>
<bean class="com.tonkia.aop.AspectJTest"/>
<aop:aspectj-autoproxy/>
PointCut注解
@Aspect
public class AspectJTest {
@Pointcut("execution(* *(..))")
public void myPointcut(){
}
@Around("myPointcut()")
public Object enhance(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("-----aspectj-------");
Object ret = joinPoint.proceed();
return ret;
}
}
ApplicationContextAware
在同一个业务类内互相调用方法,调用的是原始类的方法(而不是代理类的),如果想调用代理类的方法,需要实现ApplicationContextAware,获取ApplicationContext
public class UserServiceImpl implements UserService, ApplicationContextAware {
ApplicationContext applicationContext;
@Override
public void hello() {
System.out.println("hello");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}