spring的IOC,DI,AOP理解
IOC即控制反转,是一种设计思想,由spring去管理javaBean,标记被spring管理的类都会再IOC容器中登记,需要使用时告诉spring你需要的使用的是哪个对象,通过byName或者byType的方式,spring就会在你需要的时候提供给你。springIoc容器相当于一个中介,当你想要什么房子的时候不需要满大街去找房子,只需要告诉中介你需要什么房子,中介就给你一个房子。
spring的Ioc容器会读取bean配置信息(xml,@Configuration,@Autowired),维护一张Bean定义的注册表,根据注册表去实例化bean,装配好bean的依赖关系,Ioc容器中的bean默认是单例的。
DI即依赖注入,应用程序依赖IOC容器,由IOC容器注入程序所需要的对象,上层controller需要service,只需要直接注入service,不需要关注service的具体实现,实现了解耦和,如果是通过new的方式创建的还需要了解service的实现,一旦service出现改动,那么controller也需要改动。spring通过反射来进行注入。
AOP即面向切面编程,主要是用来解决一些日志处理,事物控制,数据源切换。。比如说日志处理,每个方法都需要做,但是每个方法都写就太麻烦了,把那些需要进行日志管理的方法一刀切,方法执行之前干什么,方法执行之后干什么。spring的AOP基于jdk的动态代理,CGLib,如果目标类实现了接口使用jdk代理,否则使用cglib代理。
jdk动态代理和CGLib的区别
jdk的动态代理(核心是Proxy类,InvocationHandler接口,通过反射机制实现),反射机制在生成类的过程比较高效,
1.能够继承静态代理的全部优点.并且能够实现代码的复用.
2.JDK 的动态代理要求代理者必须实现接口, , 否则不能生成代理对象.
CGLib(以继承的方式动态生成代理对象,借助ASM实现),ASM在生成类的执行过程比较高效
1.不管有无接口都可以创建代理对象.
2.cglib创建的代理对象是目标对象的子类.,被代理的对象不能是Final类
3.在jdk1.8之后效率不如jdk的动态代理
AOP的基本概念
(1)Aspect(切面):通常是一个类,里面可以定义切入点和通知
(2)JointPoint(连接点):程序执行过程中明确的点,一般是方法的调用
(3)Advice(通知):AOP在特定的切入点上执行的增强处理,有before,after,afterReturning,afterThrowing,around
(4)Pointcut(切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式
(5)AOP代理:AOP框架创建的对象,代理就是目标对象的加强。Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类
通知类型
(1)Before(前置通知):在目标方法被调用之前做增强处理,@Before只需要指定切入点表达式即可
(2)AfterReturning(正常返回通知):在目标方法正常完成后做增强,@AfterReturning除了指定切入点表达式后,还可以指定一个返回值形参名returning,代表目标方法的返回值
(3)AfterThrowing(异常返回通知):主要用来处理程序中未处理的异常,@AfterThrowing除了指定切入点表达式后,还可以指定一个throwing的返回值形参名,可以通过该形参名来访问目标方法中所抛出的异常对象
(4)After(返回通知):在目标方法完成之后做增强,无论目标方法是否成功完成。@After可以指定一个切入点表达式
(5)Around(环绕通知):在目标方法完成前后做增强处理,环绕通知是最重要的通知类型,像事务,日志等都是环绕通知,注意编程中核心是一个ProceedingJoinPoint,
这里环绕通知是个坑,如果方法有返回值那么环绕通知必须返回,否则正常返回通知中不会接到返回值。如果方法中存在异常,环绕通知捕获异常必须抛出,否则不会进入异常返回通知,反而会进入正常返回通知,小伙伴们可以自己实验一下。
我看网上的通知类型执行顺序,查半天也没查出个所以然,这里就自己测试一下五种通知类型的执行顺序。
接口,这里如果没有引入CGlib包,那么被拦截的方法必须要实现接口
public interface UserService { String run(String name); }
被拦截的方法
@Service("userService") public class UserServiceImpl implements UserService{ public String run(String name){ System.out.println(name); return name; } }
增强类
@Component @Aspect public class Demo { @Pointcut(value = "execution(* demo.spring.service.*.*(..))") public void pointCut(){ } @Before(value = "pointCut()") public void doBefore(JoinPoint joinPoint){ //获取方法名 String name = joinPoint.getSignature().getName(); System.out.println("Before:"+name); } //切点和返回的值 @AfterReturning(value = "pointCut()",returning = "result") public void doAfterReturning(JoinPoint joinPoint,Object result){ System.out.println("AfterReturning:"+result); } @After(value = "pointCut()") public void doAfter(JoinPoint joinPoint){ String name = joinPoint.getSignature().getName(); System.out.println("After:"+name); } //切点和异常类型 @AfterThrowing(value = "pointCut()",throwing = "ex") public void doAfterThrowing(JoinPoint joinPoint,Exception ex){ System.out.println("AfterThrowing"); throw new RuntimeException("程序出错:"+ex); } @Around(value = "pointCut()") public Object around(ProceedingJoinPoint proceedingJoinPoint){ Object result = null; String methodName = proceedingJoinPoint.getSignature().getName(); try { System.out.println("Around方法执行前"+methodName); //让方法继续进行,可以设置返回值 result = proceedingJoinPoint.proceed(); } catch (Throwable throwable) { System.out.println("Around抛出异常"+methodName); //必须抛出异常,否则不会进入异常通知 throw new RuntimeException(throwable); } System.out.println("Around方法执行后"+methodName); //如果有返回值,必须返回,不然返回值为空 return result; } }
配置文件:
<context:component-scan base-package="demo"/> <!--开启aop切面--> <aop:aspectj-autoproxy/>
新建一个测试方法用于测试
@Test public void run(){ ApplicationContext applicationContext = new ClassPathXmlApplicationContext( "classpath:applicationContext.xml"); UserService userService = (UserService) applicationContext.getBean("userService"); String name = userService.run("张三"); }
接着我们进行测试
正常执行:
我们可以看到织入顺序
Around–Before—执行的方法—Around—After—AfterReturning
接着是异常执行:
我们只需要在执行方法中加个异常:
public String run(String name){ System.out.println(name); int a = 10; a = a / 0; return name; }
异常执行的织入顺序
Around–Before—执行的方法—Around—After—AfterThrowing
- 对Spring的 IOC DI AOP的理解
- spring IOC AOP DI的理解
- 理解Spring的AOP和Ioc/DI就这么简单
- Spring IoC,DI,AOP的一点理解
- Spring特点中关于DI,IOC及AOP的个人理解
- Spring核心概念理解-IoC容器、DI、AOP
- Spring特点中关于DI,IOC及AOP的个人理解
- Spring的IoC DI和AOP理解
- Spring特点中关于DI,IOC及AOP的理解
- ######【spring属性注入(Ioc的DI)总结】:注解方式属性注入,属性名任意.=for理解:Aop注入代理对象时,注入被增强类对象时,属性名为proxy(自定义)。
- 对spring的DI,IOC, AOP概念的理解
- 深入理解Spring的两大特征(IOC和AOP)
- Spring中IoC和DI的理解
- Spring学习,依赖注入(DI)、控制反转(IoC)和面向切面(AOP)
- OPP,OOP,AOP,IoC,DI的个人理解
- 学习AOP之透过Spring的Ioc理解Advisor
- Spring面试:IOC和AOP的理解
- Spring+IOC(DI)+AOP概念及优缺点
- IOC和AOP是spring中的两个核心的概念,下面谈谈对这两个概念的理解。
- Spring中IoC和AOP的理解