第五章、AOP底层实现原理 1. 核心问题
1.AOP如何创建动态代理类(动态字节码技术)
2.Spring工厂如何加工创建代理对象
通过原始对象的id,获得的是代理对象
2. 动态代理的创建 2.1JDK的动态代理 (原理 + 编码)1.Proxy.newProxyInstance方法参数详解
2.编码
2.2 CGlib的动态代理public class TestJDKProxy {
public static void main(String[] args) {
//1.创建原始对象
UserServiceImpl userService = new UserServiceImpl();
//2.JDK创建动态代理
InvocationHandler handler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("---------proxy log----------");
//原始方法运行
Object ret = method.invoke(userService, args);
return ret;
}
};
UserService userServiceProxy =(UserService) Proxy.newProxyInstance(TestJDKProxy.class.getClassLoader(), userService.getClass().getInterfaces(), handler);
userServiceProxy.register(new User());
userServiceProxy.login("liulei","123456");
}
}
CGlib创建动态代理的原理:父子继承关系创建对象,父类为原始类,子类为代理类,这样既可以保证二者方法一致,同时能够在代理类中提供新的实现(额外功能+原始方法)
CGlib编码
public class TestCGlib {
public static void main(String[] args) {
//1.创建原始对象
UserService userService = new UserService();
//2.通过CGlib的方式创建动态代理对象
//对比JDK:Proxy.newProxyInstance(classloader,interfaces,invocationhandler)
Enhancer enhancer = new Enhancer();
enhancer.setClassLoader(TestCGlib.class.getClassLoader());
enhancer.setSuperclass(userService.getClass());
MethodInterceptor interceptor = new MethodInterceptor() {
//等同InvocationHandler----invoke
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("-----log------");
Object ret = method.invoke(userService, args);
return ret;
}
};
enhancer.setCallback(interceptor);
UserService userServiceProxy = (UserService)enhancer.create();
userServiceProxy.login("liulei","13245");
userServiceProxy.register(new User());
}
}
总结
1.JDK动态代理 Proxy。newProxyInstance() 通过接口创建代理的实现类
2.Cglib动态代理 Enhancer 通过继承父类创建代理的实现类
3.Spring工厂如何加工原始对象思路分析
编码
public class ProxyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
InvocationHandler handler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("---------log--------");
Object ret= method.invoke(bean, args);
return ret;
}
};
return Proxy.newProxyInstance(ProxyBeanPostProcessor.class.getClassLoader(),bean.getClass().getInterfaces(),handler);
}
}
配置文件
第六章、基于注解的AOP编程 1.基于注解的AOP编程的开发步骤
1.原始对象
public interface UserService {
void register(User user);
boolean login(String name,String password);
}
public class UserServiceImpl implements UserService {
@Override
public void register(User user) {
System.out.println("UserServiceImpl.register 业务运算 + DAO");
// throw new RuntimeException("测试异常");
}@Override
public boolean login(String name, String password) {
System.out.println("UserServiceImpl.login");
return true;
}
}
2.额外功能
3.切入点
4.组装切面
#通过切面类定义了 额外功能 @Around
切入点 @Around(* login(..))
@Aspect 切面类
2.3.4都放在MyAspect类中完成
@Aspect
public class MyAspect {
@Around("execution(* login(..))")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("-------------log-----------");
Object ret = joinPoint.proceed();
return ret;
}
}
配置文件
2.细节
切入点复用:在切面类中定义一个函数,上面@Pointcut注解 通过这样的方式,定义切入点表达式,有利于切入点的复用
@Aspect
public class MyAspect {
@Pointcut("execution(* login(..))")
public void myPointcut(){}
@Around(value = "myPointcut()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("-------------log-----------");
Object ret = joinPoint.proceed();
return ret;
}@Around(value = "myPointcut()")
public Object around1(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("-------------logty-----------");
Object ret = joinPoint.proceed();
return ret;
}
}
2.动态代理对象的创建
AOP底层实现 2种代理创建方式
1.JDK 通过实现接口 做新的实现类方式 创建代理对象
2.Cglib 通过继承父类 做新的子类 创建代理对象
默认:AOP编程 底层应用JDK动态代理创建方式
如果切换Cglib
1.基于注解AOP开发
2.传统的AOP开发
...
第七章、AOP开发中的一个坑
坑:在同一个业务类中,进行业务方法间的相互调用,只有最外层的方法,才是加入额外功能(内部的方法,通过普通的方式调用,调用的都是原始方法),如果想让内层的方法也调用代理对象的方法的,ApplicationContextAware获得工厂,进而获得代理对象
public class UserServiceImpl implements UserService, ApplicationContextAware {
private ApplicationContext ctx;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.ctx = applicationContext;
}
@Log
@Override
public void register(User user) {
System.out.println("UserServiceImpl.register 业务运算 + DAO");
// throw new RuntimeException("测试异常");
//this.login("liulei","123465");
UserService userService = (UserService)ctx.getBean("userService");
userService.login("liulei","123456");
}
@Override
public boolean login(String name, String password) {
System.out.println("UserServiceImpl.login");
return true;
}



