Spring IOC和AOP

摘要:

        本文简要介绍了Spring中两个重要的概念IOC控制反转和AOP面向切面编程,包括基本思想及其实现的基本原理,帮助小伙伴快速地了解IOC和AOP。

一,Spring IOC

IOC全称控制反转,代表一种创建和获取对象的技术思想,是 Spring 框架的核心思想之一。

控制:开发者手动控制对象的创建、依赖的组装。

public class UserService {
    private UserDao userDao = new UserDao(); 
    public void save() {
        userDao.insert();
    }
}

反转:对象的创建权、依赖管理权从开发者反转给了 Spring 容器。

@Service
public class UserService {
    @Autowired
    private UserDao userDao; 
    public void save() {
        userDao.insert();
    }
}

以前Java中创建一个类对象通常需要我们手动地使用new关键字,而采用IoC控制反转技术后,我们可以省去大量的手动创建类对象的工作,类对象的创建由Spring容器帮我们完成,通过XML文件和注解的方式快速地生成类对象并储存在IoC容器中,也就是我们常说的 Bean(默认单例)

因此我们可以直接通过依赖注入的方式直接调用某个对象,这种简洁的方式让我们能够专注于业务上而不是这种重复的工作,同时也实现了代码的解耦

二,依赖注入

Spring容器在创建对象时,自动将其依赖的其他对象传递给它,无需开发者手动设置。

IOC是一种技术思想,而依赖注入就是实现IOC的具体技术手段。

常见的注入方式有3种:

1,构造器注入

@Service
public class UserService {
    private UserDao userDao;
    @Autowired
    public UserService(UserDao userDao) {
        this.userDao = userDao;
    }
}

2,setter方法注入

@Service
public class UserService {
    private UserDao userDao;
    @Autowired
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
}

3,字段注入

@Service
public class UserService {
    @Autowired
    private UserDao userDao;
    ......
}

现在我们能够直接通过依赖注入的方式随心所欲地使用各个对象,但是如果A类中注入B,而B类中又注入A,这样形成一个依赖循环怎么办?


三,循环依赖

循环依赖指的是两个类的属性相互依赖,A类中有B对象属性,B类中又有A对象属性;

Spring通过三级缓存的方式能够解决单例模式下的Setter/Field注入的循环依赖,但是构造器注入必须在实例化前获得依赖进而无解。

private final Map<String, Object> singletonObjects = new ConcurrentHashMap(256);
private final Map<String, ObjectFactory<?>> singletonFactories = new ConcurrentHashMap(16);
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap(16);

(1)一级缓存:singletonObjects的Map集合用于存储完整的Bean

(2)二级缓存:earlySingletonObjects二级缓存存放Bean的早期引用

(3)三级缓存:singletonFactories三级缓存存放Bean 实例化完成的 ObjectFactory 工厂对象

四,Spring AOP

AOP全称面向切面编程,我们知道Java是一门面向对象的语言,其实AOP所谓的切面本质就是对非业务代码逻辑的一种抽象,以减少系统的重复代码,降低模块间的耦合度。

注意:代理对象的类型是接口而不是对象本身:

常见场景:日志采集、事务控制、权限管理。

AOP是一种面向切面的技术思想,而JDK动态代理和第三方库CGLIB是实现AOP的技术手段

【1】JDK动态代理

(1)目标对象:必须实现一个或多个接口,常常是执行业务的方法(crud)的操作类

(2)逻辑增强:实现IvocationHandler接口,构造器获取目标对象,重写invoke方法,在方法内添加增强逻辑,如日志记录,事务实现,权限控制,通过形参的目标对象的方法反射对象method执行原始方法

(3)代理对象:调用Proxy.newProxyInstance(类加载器、目标类接口、增强逻辑)整合目标对象和增强逻辑到一个代理类对象中

通过InvocationHandler接口将代理逻辑(增强代码)与目标对象的方法调用绑定,具体流程:

1,代理类重写接口所有方法,这些方法都只包含一个逻辑:通过反射获取目标类型的method对象

2,将目标对象的方法调用(获取到的method对象)转发给InvocationHandler的invoke方法

3,然后执行代理逻辑(invoke上下)输出日志、执行method对象所对应的原始方法、输出日志

【2】CGLIB库:一个第三方库,通过生成目标类的子类作为代理类实现动态代理,是Spring在没有实现接口类的AOP的一种实现方式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值