浅谈Spring两大核心组件

1.IoC(Inversion of Control, 控制翻转) 

 IOC 容器负责创建对象,将对象连接在一起,配置这些对象,并从创建中处理这些对象的整个生命周期,直到它们被完全销毁。

控制翻转怎么理解呢? 举个例子:"对象a 依赖了对象 b,当对象 a 需要使用 对象 b的时候必须自己去创建。但是当系统引入了 IOC 容器后, 对象a 和对象 b 之前就失去了直接的联系。这个时候,当对象 a 需要使用 对象 b的时候, 我们可以指定 IOC 容器去创建一个对象b注入到对象 a 中"。 对象 a 获得依赖对象 b 的过程,由主动行为变为了被动行为,控制权翻转,这就是控制反转名字的由来。

2.DI(Dependecy Inject, 依赖注入)

是实现控制反转的一种设计模式,依赖注入就是将实例变量传入到一个对象中去。

 

工厂设计模式

Spring使用工厂模式可以通过 BeanFactory 或 ApplicationContext 创建 bean 对象。

两者对比:

  • BeanFactory :延迟注入(第一次getBean 的时候才会注入),相比于ApplicationContext 来说会占用更少的内存,程序启动速度更快。

  • ApplicationContext :容器启动的时候,不管你用没用到,一次性创建所有 bean 。BeanFactory 仅提供了最基本的依赖注入支持,ApplicationContext 扩展了 BeanFactory ,除了有BeanFactory的功能还有额外更多功能,所以一般开发人员使用ApplicationContext会更多。

  • ApplicationContext的三个实现类:                                                                                                 ClassPathXmlApplication:把上下文文件当成类路径资源;                                                              FileSystemXmlApplication:从文件系统中的 XML 文件载入上下文定义信息;                                  XmlWebApplicationContext:从Web系统中的XML文件载入上下文定义信息。

  • Spring AOP 就是基于动态代理的,如果要代理的对象,实现了某个接口,那么Spring AOP会使用JDK Proxy,去创建代理对象,而对于没有实现接口的对象,就无法使用 JDK Proxy 去进行代理了,这时候Spring AOP会使用Cglib ,这时候Spring AOP会使用 Cglib 生成一个被代理对象的子类来作为代理

  • Spring AOP 和 AspectJ AOP 有什么区别?

    Spring AOP 属于运行时增强,而 AspectJ 是编译时增强。 Spring AOP 基于代理(Proxying),而 AspectJ 基于字节码操作(Bytecode Manipulation)。

    Spring AOP 已经集成了 AspectJ ,AspectJ 应该算的上是 Java 生态系统中最完整的 AOP 框架了。AspectJ 相比于 Spring AOP 功能更加强大,但是 Spring AOP 相对来说更简单,

    如果我们的切面比较少,那么两者性能差异不大。但是,当切面太多的话,最好选择 AspectJ ,它比Spring AOP 快很多。

  • #################################################################################

  • AopProxy有CglibAopProxy和JdkDynamicAopProxy两种实现。
    Spring AOP会通过策略模式—即根据目标对象是类还是接口来使用CglibAopProxy或JdkDynamicAopProxy完成对目标类进行代理。
    不同的AopProxy实现的实例化过程采用工厂模式—即通过AopProxyFactory进行封装(在下一小节织入过程详细介绍AopProxyFactory是如何进行封装的过程)。

    Spring AOP采用ProxyFactory来完成织入操作(下小节会详细介绍),下面来看下在Spring AOP中两种机制的代码实现。
    (1)基于接口的代理—JDK动态代理
    代码实现:

  • //代码分为四个类,亲测可用,date:20190912
    //接口
    public interface LoginInterface
    {
        public void login();
    }
    
    //实现类
    public class LoginImpl implements LoginInterface
    {
        @Override
        public void login()
        {
            System.out.println("****** Login Success ******");
        }
    
    }
    
    //代理类
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    //Around Advice:横切逻辑
    public class LoginInvocation implements InvocationHandler
    {
    
        //被代理的对象
        private Object target;
    
        public Object getTarget()
        {
            return target;
        }
    
        public void setTarget(Object target)
        {
            this.target = target;
        }
    
        public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable
        {
            //在方法执行前所要执行的业务逻辑
            beforeMethod(method);
            long starttime = System.currentTimeMillis();
    
            method.invoke(target, args);
    
            long result = System.currentTimeMillis() - starttime;
            System.out.println("执行时间为:" + result + "毫秒");
    
            afterMethod(method);//在方法执行后所要执行的业务逻辑
            return null;
        }
    
        public void beforeMethod(Method m)
        {
            System.out.println(m.getName() + "执行before....");
        }
    
        public void afterMethod(Method m)
        {
            System.out.println(m.getName() + "执行after...");
        }
    
    }
    
    
    //测试类
    import java.lang.reflect.Proxy;
    
    public class TestMain
    {
    
        public static void main(String args[])
        {
            //被代理的对象
            LoginImpl loginImpl = new LoginImpl();
            //获取日志的InvocationHandler
            LoginInvocation loginInvocation = new LoginInvocation();
            loginInvocation.setTarget(loginImpl);
    
            // 设置代理对象,参数1:被代理对象的classloader
            // 参数2:被代理对象所实现的接口(该对象必须要实现接口,不然无法产生代理)
            // 参数3:指定处理的InvocationHandler
            LoginInterface loginInterface =
                (LoginInterface)Proxy.newProxyInstance(loginImpl.getClass().getClassLoader(),
                    new Class[] {LoginInterface.class},
                    loginInvocation);
    
            // 触发具体方法
            loginInterface.login();
    
        }
    
    }
    
    运行结果:
    login执行before....
    ****** Login Success ******
    执行时间为:0毫秒
    login执行after...
    

    (2)基于类的代理—CGLIB
    代码实现:

  • //没有实现任何接口的目标类
    public class LoginWithoutInterface {
        public void login(){
            System.out.println("没有接口的登录--基于类的代理");
        }
    }
    //Around Advice(同上)
    public class LoginInterceptor implements MethodInterceptor {
        @Override
        public Object invoke(MethodInvocation methodInvocation) throws Throwable {
            try{
                System.out.println("拦截下,再执行");
                return methodInvocation.proceed();
            }finally {
                System.out.println("拦截结束");
            }
        }
    }
    //织入操作
    public static void main(String[] args) {
       LoginWithoutInterface login = new LoginWithoutInterface();
       ProxyFactory weaver = new ProxyFactory(login);
       NameMatchMethodPointcutAdvisor advisor = new NameMatchMethodPointcutAdvisor();
       advisor.setMappedNames("login");
       advisor.setAdvice(new LoginInterceptor());
       weaver.addAdvisor(advisor);
    
        //返回代理对象
       LoginWithoutInterface loginProxy = (LoginWithoutInterface) weaver.getProxy();
       loginProxy.login();
       System.out.println(loginProxy.getClass());
    }
    

     

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值