Spring IOC
控制反转(IOC):Spring Bean对象统一创建交给IOC容器管理,来实现对象之间的解耦
依赖注入(DI):构造器注入、setter方法注入、根据注解注入
Spring AOP
AOP的实现关键在于代理模式,主要分为静态代理和动态代理
静态代理的代表为AspectJ,动态代理以SpringAOP为例。
1)AspectJ是静态代理的增强,所谓静态代理,就是AOP框架会在编译阶段生成AOP代理类,因此也 称为编译时增强,他会在编译阶段将AspectJ(切面)织入到Java字节码中,运行的时候就是增强之后的 AOP对象。
@Aspect @Component public class MyAnnotionAop { // 定义切入点 @Pointcut("execution(* com.test.AnnotionImpl.*.*(..))") public void point() {} // 前置通知 @Before("point()") public void before() { System.out.println("前置"); } // 后置通知 始终会执行 @After("point()") public void after() { System.out.println("后置"); } // 环绕通知 @Around("point()") public Object around(ProceedingJoinPoint pjp) throws Throwable { System.out.println("环绕前"); Object result = pjp.proceed(); System.out.println("环绕后"); return result; } // 后置 发生异常时不会执行 @AfterReturning("point()") public void returning() { System.out.println("After returning 后置"); } // 发生异常 @AfterThrowing("point()") public void throwing() { System.out.println("发生异常了"); } }
2)Spring AOP使用的动态代理,所谓的动态代理就是说AOP框架不会去修改字节码,而是每次运行 时在内存中临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。
Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理
①JDK动态代理只提供接口的代理,不支持类的代理。核心InvocationHandler接口和Proxy类, InvocationHandler 通过invoke()方法反射来调用目标类中的代码,动态地将横切逻辑和业务编织在一 起;接着,Proxy利用 InvocationHandler动态创建一个符合某一接口的的实例, 生成目标类的代理对 象。
public class JdkProxyDemo { interface Foo{ void foo(); } static class Target implements Foo{ @Override public void foo() { System.out.println(" target foo"); } } /** * jdk代理只能针对接口进行代理 * 内部采用asm技术动态生成字节码() * @param args */ public static void main(String[] args) { Target target = new Target(); ClassLoader classLoader = JdkProxyDemo.class.getClassLoader(); Foo proxy = (Foo)Proxy.newProxyInstance(classLoader, new Class[]{Foo.class}, new InvocationHandler() { //proxy 代理对象自身 //method 正在执行的方法 //方法参数 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("before"); Object result = method.invoke(target, args); //代理类返回的是目标方法执行的结果 System.out.println("after"); return result; } }); proxy.foo(); } }
②如果代理类没有实现 InvocationHandler 接口,那么Spring AOP会选择使用CGLIB来动态代理目 标类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成指定类 的一个子类对象,并覆盖其中特定方法并添加增强代码,从而实现AOP。CGLIB是通过继承的方式做的动态代 理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。
3)静态代理与动态代理区别在于生成AOP代理对象的时机不同,相对来说AspectJ的静态代理方式具 有更好的性能,但是AspectJ需要特定的编译器进行处理,而Spring AOP则无需特定的编译器处理。