Spring中IOC和AOP的实现原理

IOC

java程序中的每个业务逻辑至少需要两个或以上的对象来协作完成,通常,在使用其他的合作对象时,均要使用像new object() 这样的语法来完成合作对象的创建。而IOC的思想说白了就是由Spring容器来实现对象的创建管理工作。我们只需要关心业务逻辑本身就可以了。从这方面来说,对象如何得到他的协作对象的责任被反转了(IOC、DI)。

IOC是基于java的反射机制以及工厂模式实现的。具体可以看下这两篇文章,https://www.cnblogs.com/Eason-S/p/5851078.html和http://blog.csdn.net/liushuijinger/article/details/35978965,写的都很好

工场:各类都实现了某一接口,并提供一个工场类,根据传入参数的不同来创建不同的对象

反射:可以根据类名获取该类实例, Class.forName(ClassName).newInstance()

在项目启动时首先获取class 对应name和beanDefinition,然后通过beanDefinition创建实例,以类似键值对的方式将name和bean实例存储在spring上下文容器中,当需要使用时直接利用getBean(String beanName)从容器中获取对应的实例。

AOP主要是使用动态代理实现 https://www.cnblogs.com/lcngu/p/5339555.html,https://www.cnblogs.com/cenyu/p/6289209.html这个讲代理的也挺好

AOP(面向切面编程),在业务处理过程之前或之后总会有一些公共行为比如像权限认证、事务处理、打印日志等等,我们将那些公共行为封装到一个可重用模块,这些公共行为叫做切面,而被环绕的业务代码叫做切点,环绕切点的一系列操作均是对切点的增强处理

JDK动态代理(被代理的类需要实现一个接口):中使用InvocationHandler接口和Proxy类来实现,在InvocationHandler中的invoke(Proxy proxy,Method method, object arg[])方法,中处理日志,认证,事务等操作

//接口
public interface Fruit {
    void fruitName();
}

//实现类
public class AppleService implements Fruit {

    @Override
    public void fruitName() {
        System.out.println( "我是苹果");
    }
}


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//代理对象工场
public class ProxyFactory {

    private Object targect;

    public ProxyFactory(Fruit fruit) {
        targect = fruit;
    }

    public Object getProxyInstance() {
        return Proxy.newProxyInstance(targect.getClass().getClassLoader(), targect.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("动态代理进来了");
                Object object =  method.invoke(targect, args);
                System.out.println("动态代理执行完了");
                return object;
            }
        });
    }

    public static void main(String[] args) {
        ProxyFactory proxyFactory = new ProxyFactory(new AppleService());
        Fruit target = (Fruit) proxyFactory.getProxyInstance();
        target.fruitName();
    }
}

步骤:(1)构造InvocationHandler处理器,定义invoke()方法(2)获取Proxy代理类,并生成代理类对象,调用方法完成相关操作

Proxy.newProxyInstance()

 public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
newProxyInstance,方法有三个参数:

loader: 用哪个类加载器去加载代理对象

interfaces:动态代理类需要实现的接口

h:动态代理方法在执行时,会调用h里面的invoke方法去执行,invoke(Proxy proxy,Method method, object arg[])

静态代理:实现了被代理类接口的类,其中保存了一个被代理类的实例。在接口的实现方法中,调用被代理对象对应的方法,同时添加需要的其他操作。缺点:代理类和委托类都实现了同样的接口,代码重复;当需要对对不同的委托类实现相同的处理时,需要定义多个代理类

CGLIB动态代理:无论是静态代理还是动态代理都需要委托类实现接口,如果要对不实现接口的类进行代理,就需要使用cglib库,使用Enhancer来创建代理类,使用MethodIntercepter接口,重写intercept()方法,实现具体操作

//未实现接口
public class BananaService {
    public void fruitName() {
        System.out.println("我是香蕉");
    }
}

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class CglibProxyFactory {
    private Object target;

    public CglibProxyFactory(BananaService bananaService) {
        target = bananaService;
    }

    public Object getCglibProxyInstance() {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                System.out.println("cglib 动态代理进来了");
                Object value = method.invoke(target, objects);
                System.out.println("cglib 动态代理跑完了");
                return value;
            }
        });
        return enhancer.create();
    }

    public static void main(String[] args) {
        CglibProxyFactory cglibProxyFactory = new CglibProxyFactory(new BananaService());
        BananaService proxy = (BananaService)cglibProxyFactory.getCglibProxyInstance();
        proxy.fruitName();
    }
}

Spring会根据具体的Bean是否具有接口去选择动态代理方式,如果有接口,使用的是Jdk的动态代理方式,如果没有接口,使用的是cglib的动态代理方式。

https://blog.csdn.net/zizila/article/details/83169005

  • 1
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值