AOP:
aop切面编程,其实就是spring增强器的一个扩展,就是通过beanPostProcessor的after后置方式实现的,其中在after中把需要的bean通过放射+动态代理完成bean的替换,替换成代理bean。然后通过注册拦截器完成代理方式的执行;
1、代理对象的创建过程(advice,切面、切点)
2、通过jdk或cglib的方式生产代理对象(通过beanPostProcessor的after后置方式实现)
3、执行方法回调的时候,会到字节码的文件中,直接找回到DynamicAdviceedInterceptor中的intercept方法,在这里执行
4、在执行过程中,会生成之前定义好的通知拦截器,来执行
Spring AOP使用的动态代理,所谓的动态代理就是说AOP框架不会去修改字节码,而是在内存中临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。
Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理。
JDK动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口。JDK动态代理的核心是InvocationHandler接口和Proxy类。如果目标类没有实现接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。
CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成某个类的子类,注意,CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。
1、首先要注入 @EnableAspectJAutoProxy
@EnableAspectJAutoProxy @ComponentScan(value = "com.flm") public class Config { }
2、创建service
@Component public class UserServiceImpl implements UserService { public UserServiceImpl(){ System.out.println("UserServiceImpl 构造方法 create ......"); }
@PostConstruct private void rn(){ System.out.println("UserServiceImpl 使用@PostConstruct run... ......"); } @Override public String test(){ System.out.println("aop test 业务逻辑...."); return "OK"; } @Override public void testData() { System.out.println("testData 业务逻辑...."); } }
3、启动类
public class APP { public static void main(String[] args) { // 方式1:指定xml启动 // ApplicationContext context = new ClassPathXmlApplicationContext("beans-context-content.xml"); // 方式二:指定配置类启动 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext (Config.class); // 在spring容器获取bean UserService userService = context.getBean(UserService.class); // 执行要aop的接口 String rt = userService.test(); System.out.println(rt); userService.testData(); } }
4、自定义aop方法(原理)
@Component public class AopPostProcessor implements BeanPostProcessor { // 原理 BeanPostProcessor + jdk动态代理实现 @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { // 判断哪个接口需要代理的 ,写死 if("userServiceImpl".equals(beanName)){ // 创建代理对象 , JDK代理是依赖接口的,有实现接口的为jdk代理,否则为 cglib代理 Object proxyInstance = Proxy.newProxyInstance(bean.getClass().getClassLoader(), UserServiceImpl.class.getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = null; // 判断哪个方法需要代理使用执行的,现在写死test if("test".equals(method.getName())){ // 方法之前执行 System.out.println("invoke before ..."); // 执行方法 result = method.invoke(bean, args); // 方法之后执行 System.out.println("invoke after ...:"+result.toString()); } // 执行方法 返回结果 return result; } }); return proxyInstance; } return bean; } }
最后执行userSerie.test(),aop拦截结果如下
================
详情源码看这个大神写的
https://www.cnblogs.com/liuyk-code/p/9886033.html