IoC控制反转
IoC控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)。
Spring 的AOP 实现原理
Spring 的 AOP 实现原理其实很简单,就是通过动态代理实现的。
如果我们为Spring的某个bean配置了切面,那么Spring在创建这个bean的时候,实际上创建的是这个bean的一个代理对象,我们后续对bean中方法的调用,实际上调用的是代理类重写的代理方法。
Spring的AOP使用了两种动态代理,分别是 JDK 的动态代理,以及 CGLib 的动态代理。
- JDK动态代理:
- CGLib动态代理:
Spring 默认使用JDK的动态代理实现AOP,类如果实现了接口,Spring就会使用这种方式实现动态代理。
JDK 实现动态代理需要两个组件,首先第一个就是InvocationHandler接口。我们在使用JDK的动态代理时,需要编写一个类,去实现这个接口,然后重写invoke方法,这个方法其实就是我们提供的代理方法。
然后JDK动态代理需要使用的第二个组件就是Proxy这个类,我们可以通过这个类的newProxyInstance方法,返回一个代理对象。生成的代理类实现了原来那个类的所有接口,并对接口的方法进行了代理,我们通过代理对象调用这些方法时,底层将通过反射,调用我们实现的invoke方法。
JDK的动态代理存在限制,那就是被代理的类必须是一个实现了接口的类,代理类需要实现相同的接口,代理接口中声明的方法。若需要代理的类没有实现接口,此时JDK的动态代理将没有办法使用,于是Spring会使用CGLib的动态代理来生成代理对象。CGLib直接操作字节码,生成类的子类,重写类的方法完成代理。
aop 在私有方法上不生效,在final方法上不生效,在同一个类内部互相调用不生效,在静态方法上不生效,归根到底在于aop的实现依赖于代理类继承自原有类,非public方法都无法继承。
SPI
SPI 机制
SPI机制最大的好处在于也就是与API 的区别,在于实现类的输出由谁来负责,API 机制由接口提供者实现,多用于具体多业务实现,而SPI 机制则是由使用的人来实现,通常SPI 只要用来规范处理流程,而具体的处理内容则由使用的人来实现,多用于框架中。
@Autowired和@Resource的区别
共同点:二者都可以写在字段和setter方法上。
区别:
- @Autowired 为Spring 提供的注解,按照byType 注入,默认情况下依赖对象必须存在,如果允许null 值,则要设置required 属性为false。如果要按照名称byName 来装配,则需要搭配@Qualifer 注解一起使用。
- @Resource 由J2EE 提供,默认按照byName 装配,其有两个属性:name 和type,将@Resource 的name 属性解析为bean 的名称,而type 为解析的类型。如果既不指定name 也不指定type 则通过反射机制使用byName 自动注入。
@Transactional事务传播机制
@Transactional事务传播机制,是指包含多个事务的方法在相互调用时,事务是如何在这些方法之间传播的。
事务传播机制共有七种:
- Propagation.REQUIRED:默认的事务传播级别,它表示如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
- Propagation.SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
- Propagation.MANDATORY:(mandatory:强制性)如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
- Propagation.REQUIRES_NEW:表示创建一个新的事务,如果当前存在事务,则把当前事务挂起。也就是说不管外部方法是否开启事务,Propagation.REQUIRES_NEW 修饰的内部方法会新开启自己的事务,且开启的事务相互独立,互不干扰。
- Propagation.NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。
- Propagation.NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。
- Propagation.NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于 PROPAGATION_REQUIRED。