IOC:
IOC,Inversion of control,控制反转,是Spring Core的核心,IOC并不能算作一种技术,而是一种思想,要知道控制反转,就必须先连接DI,依赖注入,因为控制反转就是由DI实现的,我们以设计一个行李箱来说明,我们一般设计行李箱的流程为:
我们的设计思路是根据轮子设计底盘,根据底盘设计箱体,再根据箱体设计行李箱。这里面有以下的依赖关系,行李箱依赖箱体,箱体依赖于底盘,底盘依赖于轮子,这样设计的代码可维护性低,假如这时候提出需求,要将轮子的尺寸改大一码,这时候所有的代码都需要改了,代价是很高的,这时候我们使用依赖注入,所谓的依赖注入就是:把底层类作为参数,传递给上层类,实现上层对下层的控制,设计行李箱的过程变成如下图所示:
我们先根据行李箱的大小来设计箱体,根据箱体来设计底盘,根据底盘来设计轮子,假如这时候的需要求是要求改轮子的大小,就不需要改其他部分的代码,只需修改轮子部分的代码即可。即将底层注入到上层。
AOP:即面向切面编程,可以说是对面向对象编程的补充和完善,面对对象编程引入封装,继承,多态等概念来建立一种对象层次结构,允许开发者定义纵向的关系,但并不适合定义横向的关系,比如日志功能,如果硬是要使用面对对象对象来进行实现日志的功能的话,势必导致项目的重复代码的增多,且进行维护时的难度加大。AOP技术恰恰相反,它利用一种称为横切的技术,剥解开封装对象的内部,将哪些影响了多个类的公共行为封装到一个可重用模块,并将其命名为切面,所谓切面,就是将哪些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码。降低模块之间的耦合度。例如我们要在一个保存数据到数据的方法中要进行权限验证。我们传统解决方法一:是编写一个可重复调用方法,各模块进行调用即可,方法二:是我们可以将这个方法封装到一个类中,然后要使用这个方法的类就继承这个类即可,但是这样的代码重复率高和维护难度大,我们采用AOP的方式,就可以解决上诉解决方法的缺点。
AOP用法:
jdk动态代理:只能对实现接口的类产生代理对象,必须是实现接口的类才能用jdk动态代理
假设我们现在有一个接口UseDao,和一个它的实现类UseDaoImpl,接口里面有一个save方法,作用是保存数据,但现在我们要实现在保存之前做一些类似权限验证的操作,
package DynamicProxy;
//接口
public interface UserDao {
public void save();
}
//实现类
public class UserDaoImpl implements UserDao{
public void save(){
System.out.println("保存。。。");
}
}
代理类
/**
* 使用JDK动态代理对UserDaoImpl产生代理
*/
public class JdkProxy implements InvocationHandler {
//将被增强的对象传递到代理中
public UserDao userDao;
public JdkProxy(UserDao userDao){
this.userDao=userDao;
}
/**
* 产生UserDaoImpl代理的方法
* @return
*/
public UserDao createProxy() {
/**
* 第一个参数:类加载器,对谁产生代理,这个类加载就是加载谁的
* 第二个参数:接口,实际上传的是实例
* 第三个参数:InvocationHandler,真正执行方法的对象
*/
UserDao userDaoProxy= (UserDao) Proxy.newProxyInstance(userDao.getClass().getClassLoader(),
userDao.getClass().getInterfaces(),this);
return userDaoProxy;
}
/**
*
* @param proxy 代理对象
* @param method 正在执行的方法
* @param args 方法参数
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//判断方法是否是我们需要增强的
if("save".equals(method.getName())){
//增强
System.out.println("权限校验");
return method.invoke(userDao,args);
}
return method.invoke(userDao,args);
}
}
//测试
public class TestProxy {
@Test
public void save(){
UserDao userDao=new UserDaoImpl();
//创建代理
UserDao userDaoproxy=new JdkProxy(userDao).createProxy();
userDaoproxy.save();
}
}
Cglib产生代理对象:
对没有实现接口的类产生代理对象,生成子类对象
//具体类,而不是接口了
public class CustomerDao {
public void save(){
System.out.println("保存。。。");
}
}
//产生代理的类
public class CglibProxy implements MethodInterceptor {
private CustomerDao customerDao;
public CglibProxy(CustomerDao customerDao){
this.customerDao=customerDao;
}
/**
* 使用Cglib产生代理的方法
*/
public CustomerDao createProxy(){
//1.创建Cglib核心类的对象
Enhancer enhancer=new Enhancer();
//2.设置父类
enhancer.setSuperclass(customerDao.getClass());
//3.设置回调(类似于InvocationHandler对象)
enhancer.setCallback(this);
//4.创建代理对象
CustomerDao proxy = (CustomerDao) enhancer.create();
return proxy;
}
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
//判断方法是否是我们需要增强的
if("save".equals(method.getName())){
//增强
System.out.println("权限校验");
return methodProxy.invokeSuper(proxy,args);
}
return methodProxy.invokeSuper(proxy,args);
}
}
//测试
@Test
public void save2(){
CustomerDao customerDao=new CustomerDao();
CustomerDao proxy = new CglibProxy(customerDao).createProxy();
proxy.save();
}