精华内容
下载资源
问答
  • 容器一个Java 所编写的程序,可当做一个工具,没有容器时必须自行编写程序以管理对象关系,现在容器都会自动做好。 有一说法:如果有一个类专门用来存放其它类的对象,这个类就叫做容器。另一说法:容器里...

    Javaweb里“容器“为何出现,应用在哪,未来发展趋势

         容器是一个Java 所编写的程序,可当做一个工具,没有容器时必须自行编写程序以管理对象关系,现在容器都会自动做好。

         有一说法:如果有一个类专门用来存放其它类的对象,这个类就叫做容器。另一说法:容器里存放的是对象的引用(或者说变量)而不是对象,对象还在容器外,容器内放的是对象的引用,类似于C语言的指针,也就是对象实例化后在堆内存中的地址,容器存放引用而不是存放对象本身也是容器设计巧妙的地方。

    常用的容器有:

      
     
         举个栗子
          1、早期的Tomcat是一个嵌入Apache内的JSP/Servlet解释引擎Apache+Tomcat就相当于IIS+ASP。后来的Tomcat已不再嵌入Apache内,Tomcat进程独立于Apache进程运行。 而且,Tomcat已经是一个独立的Servlet和JSP容器,业务逻辑层代码和界面交互层代码可以分离了。因此,有人把Tomcat叫做轻量级应用服务器。
    一般来说,大的站点都是将Tomcat与Apache的结合,Apache负责接受所有来自客户端的HTTP请求,然后将Servlets和JSP的请求转发给Tomcat来处理。Tomcat完成处理后,将响应传回给Apache,最后Apache将响应返回给客户端。
           2、WebSphere是IBM公司的产品,可进一步细分为 WebSphere Performance Pack、Cache Manager 和WebSphere Application Server等系列,其中WebSphere Application Server 是基于Java 的应用环境,可以运行于 Sun Solaris、Windows NT 等多种操作系统平台,用于建立、部署和管理Internet和Intranet Web应用程序。
     
         容器为什么出现?
         容器显然是放东西的,通俗点,就好比,杯子、碗等等。java的容器类里常用的List,Map等就好比是杯子,杯子是用来盛水的,List是用来放对象的,一个杯子里能放水,饮料等,list里能放各种对象。然后对这个list进行操作,便捷又简单。
          容器的应用
          在java开发中我们离不开集合数组等,在java中有个专有名词:“容器” ,下面会结合Thinking in Java的知识和实际开发中业务场景讲述一下容器在Web项目中的用法。可结合图片代码了解Java中的容器
         其中淡绿色的表示接口,红色的表示我们经常使用的类 
             其中淡绿色的表示接口,红色的表示我们经常使用的类
             剩余部分细看远方大大详解
             容器未来趋势
              1、容器主宰世界
              2、Function As a Service
    • 减少开支。通过购买共享的基础设施,同时减少了花费在运维上的人力成本,最终减少了开支。

    • 减轻负担。不再需要重复造轮子,需要什么功能直接集成调用即可,也无需考虑整体的性能,只专注于业务代码的实现。

    • 易于扩展。云上提供了自动的弹性扩展,用了多少计算资源,就购买多少,完全按需付费。

    • 简化管理。自动化的弹性扩展、减少了打包和部署的复杂度、可以快速推向市场,这些都让管理变得简单高效。

    • 环保计算。即使在云的环境上,仍习惯于购买多余的服务器,最终导致空闲。Serverless杜绝了这种情况

     
          以下是查询及相关的文章
          2、容器的简易理解
          3、常见容器
    posted @ 2019-03-10 23:14 .知寒 阅读(...) 评论(...) 编辑 收藏
    展开全文
  • 在游戏里经常会用到重复资源,最常来举例的就是射击游戏中的子弹,像这样大量有共同特征的对象,就用一个容器来统一管理,需要的时候从容器里获取,销毁的时候也并不是真的Destroy,而是回收到容器里,如果容器中...

    在游戏里经常会用到重复资源,最常哪来举例的就是射击游戏中的子弹,像这样大量有共同特征的对象,就用一个容器来统一管理,需要的时候从容器里获取,销毁的时候也并不是真的Destroy,而是回收到容器里,如果容器中没有空闲对象,则创建,这样就可以避免大量的创建、销毁操作,实现代码的高效与低开销。
    不同的项目中,可能会根据项目情况对对象池进行不同的优化或简化,不过原理都是一样。而且很多情况是一个项目中并不只有一种重复资源,可能会有很多种,这样就需要多组对象池来管理。如果是每一个对象池,都复制粘贴一遍代码,这无疑是各位大大们最不想看到的。最好是有一个管理器,来统一管理所有的对象池,这里我也根据最近几个小项目写了一个简易的对象池,由管理器来创建或销毁所有的对象池及其池对象,在此做一下总结。

    //为了方便后期识别和管理,用枚举来标记对象在池中的状态

    //对象的池状态
    public enum PoolItemState
    {
        Work,
        Idle
    }
    

    //管理对象池,原理也很简单,就是用一个容器,再来统一的管理所有的对象池,用管理器来创建或销毁对象池,以及对池的子对象进行的操作。

    public class PoolManager : MonoBehaviour
    {
        public static PoolManager instance;
    
        //Dictionary查找、添加、删除 速度较快,不过内存占用相对较多
        Dictionary<int, PoolItemBase> itemPrefabDic;
        Dictionary<int, Transform> workParentDic;
        Dictionary<int, Transform> idleParentDic;
        Dictionary<int, List<PoolItemBase>> workListDic;
        Dictionary<int, List<PoolItemBase>> idleListDic;
    
        void Awake()
        {
            instance = this;
    
            itemPrefabDic = new Dictionary<int, PoolItemBase>();
            workParentDic = new Dictionary<int, Transform>();
            idleParentDic = new Dictionary<int, Transform>();
            workListDic = new Dictionary<int, List<PoolItemBase>>();
            idleListDic = new Dictionary<int, List<PoolItemBase>>();
        }
    
        //注册一个对象
        public int InitNewPool(PoolItemBase poolItem, Transform parentTrans = null)
        {
            //判断是否已注册
            if (itemPrefabDic.ContainsValue(poolItem))
            {
                Debug.Log("<color=red> 注册的 poolIndex 已存在   </color>" + poolItem);
                return -1;
            }
            //生成对象池Index,在销毁时某个对象池,长度会缩减,获取的值将会重复,所以不能用itemPrefabDic.Count
            //int poolIndex = itemPrefabDic.Count;
            int poolIndex = GetNewPoolIndex();
    
            //记录PoolItemBase
            itemPrefabDic.Add(poolIndex, poolItem);
            //设置子对象的父物体
            if (parentTrans == null)
            {
                //如果未指定父物体,生成
                parentTrans = new GameObject(poolItem.name + "_WorkParent_CanDestroy").transform;
                parentTrans.parent = transform;
            }
            workParentDic.Add(poolIndex, parentTrans);
            Transform idleParentTrans = new GameObject(poolItem.name + "_IdleParent").transform;
            idleParentTrans.gameObject.SetActive(false);
            idleParentTrans.parent = transform;
            idleParentDic.Add(poolIndex, idleParentTrans);
            //用List保存子对象
            workListDic.Add(poolIndex, new List<PoolItemBase>());
            idleListDic.Add(poolIndex, new List<PoolItemBase>());
            //返回新注册对象池的Index
            return poolIndex;
        }
    
        //获取池对象
        public PoolItemBase GetOneItem(int poolIndex)
        {
            //判断是否在池内
            if (!itemPrefabDic.ContainsKey(poolIndex))
            {
                Debug.Log("<color=red> 获取的 poolIndex 不存在  </color>" + poolIndex);
                return null;
            }
    
            PoolItemBase tmpGetItem = null;
            if (idleListDic[poolIndex].Count > 0)
            {
                //如果有多余Item
                tmpGetItem = idleListDic[poolIndex][0];
                tmpGetItem.transform.SetParent(workParentDic[poolIndex]);
                idleListDic[poolIndex].RemoveAt(0);
            }
            else
            {
                //如果没有,加载
                tmpGetItem = Instantiate(itemPrefabDic[poolIndex], transform.position, Quaternion.identity, workParentDic[poolIndex]);
            }
            workListDic[poolIndex].Add(tmpGetItem);
            //初始化
            tmpGetItem.InitPool(poolIndex);
            //
            return tmpGetItem;
        }
    
        //回收池对象
        public void DestroyOneItem(int poolIndex, PoolItemBase item)
        {
            if (!itemPrefabDic.ContainsKey(poolIndex))
            {
                Debug.Log("<color=red> 回收的 poolIndex 不存在   </color>" + poolIndex);
                return;
            }
            //将工作的Item回收
            if (!idleListDic[poolIndex].Contains(item))
                idleListDic[poolIndex].Add(item);
            if (workListDic[poolIndex].Contains(item))
                workListDic[poolIndex].Remove(item);
            item.transform.SetParent(idleParentDic[poolIndex]);
            //重置
            item.ResetPool();
        }
    
        //清空对象池
        public void ClearPool(int poolIndex)
        {
            if (!itemPrefabDic.ContainsKey(poolIndex))
            {
                Debug.Log("<color=red> 回收的 pool 不存在   </color>" + poolIndex);
                return;
            }
            //遍历,回收
            for (int i = 0; i < workListDic[poolIndex].Count; i++)
            {
                DestroyOneItem(poolIndex, workListDic[poolIndex][i]);
            }
            workListDic[poolIndex].Clear();
        }
    
        //销毁一个对象池
        public void DestroyPool(int poolIndex)
        {
            if (!itemPrefabDic.ContainsKey(poolIndex))
            {
                Debug.Log("<color=red> 销毁的的 pool 不存在   </color>" + poolIndex);
                return;
            }
            //销毁/清空
            if (workParentDic[poolIndex].name.EndsWith("CanDestroy", System.StringComparison.Ordinal))
                Destroy(workParentDic[poolIndex].gameObject);
            else
            {
                ClearPool(poolIndex);
            }
            Destroy(idleParentDic[poolIndex].gameObject);
            //数据移除
            itemPrefabDic.Remove(poolIndex);
            workParentDic.Remove(poolIndex);
            idleParentDic.Remove(poolIndex);
            workListDic.Remove(poolIndex);
            idleListDic.Remove(poolIndex);
        }
    
        int indexNum = 0;
        int GetNewPoolIndex()
        {
            return indexNum++;
        }
    
    }
    

    //因为是对池对象的统一管理,给其添加一个父类,关于继承和多态,能搜到各种详细的资料~~

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    //池对象父类
    public abstract class PoolItemBase : MonoBehaviour
    {
    
        protected PoolItemState itemState;
        protected int poolIndex;
    
        //初始化
        public void InitPool(int poolInde)
        {
            itemState = PoolItemState.Work;
            poolIndex = poolInde;
    
            gameObject.name = "item_" + poolIndex;
    
            Init();
        }
    
        //重置,销毁时调用
        public void ResetPool()
        {
            itemState = PoolItemState.Idle;
            transform.localPosition = Vector3.zero;
    
            Reset();
        }
    
        public abstract void Init();
    
        public abstract void Reset();
    
    }
    

    //到这里对象池就算写完咯,关于其中的数据结构,需要根据实际项目的数据量及数据操作方式,选择合适的方案,如果数据比较多,字典就不是最佳选择了···

    //接下来是一个简单的小测试,看一下实际效果
    //对象类继承父类,并重写方法

    public class CubeItem : PoolItemBase
    {
        public override void Init()
        {
            StartCoroutine(Move());
        }
    
        public override void Reset()
        {
            StopAllCoroutines();
        }
    
        IEnumerator Move()
        {
            float timer = 0;
            while(timer < 2)
            {
                transform.position += Vector3.forward * 5;
                timer += 0.02f;
                yield return new WaitForSeconds(0.02f);
            }
            PoolManager.instance.DestroyOneItem(poolIndex, this);
        }
    }
    

    //对象的使用者,注册一个对象池,获取对象池的Index,然后就可以创建对象啦

    public class LauncherControl : MonoBehaviour 
    {
        [SerializeField] CubeItem CubePrefab;
    
        int poolIndex;
    
    	void Start () 
        {
            poolIndex = PoolManager.instance.InitNewPool(CubePrefab);
            StartCoroutine(LaunchCube());
    	}
    
        void Update()
        {
            if (Input.GetMouseButtonDown(1))
                PoolManager.instance.ClearPool(poolIndex);
            else if (Input.GetMouseButtonDown(2))
                PoolManager.instance.DestroyPool(poolIndex);
        }
        
        IEnumerator LaunchCube()
        {
            while(true)
            {
                PoolManager.instance.GetOneItem(poolIndex);
                yield return new WaitForSeconds(0.5f);
            }
        }
    }
    

    感谢大家的鼓励与支持,本人目前正处于我工作 我学习 我快乐的学习阶段,在技术上还需要继续努力,分享的Demo或案例或多或少都存在有待优化的地方,欢迎指点~~~

    展开全文
  • 一个IOC简单实现方法

    2012-03-07 18:12:00
    下面是一个简单的IOC实现,代码较少只是为了便于理解IOC这个概念。 首先说下什么事IOC,IOC(Inversion of Control),控制反转。 什么意思,就是设计好的类交给系统去控制,而不是在你的类内部控制。这称为控制...

    下面是一个简单的IOC实现,代码较少只是为了便于理解IOC这个概念。

    首先说下什么事IOC,IOC(Inversion of Control),控制反转。 什么意思哪,就是设计好的类交给系统去控制,而不是在你的类内部控制。这称为控制反转。也可以理解为,将对象的创建和获取提取到外部。由外部容器提供需要的组件

    我这个代码是基于“学无止境”网友的介绍的基础上修改的 地址为:http://www.cnblogs.com/springcsc/archive/2009/12/02/1615500.html。

    1. 首先贴出代码结构,如下图

    2附上类,由于在类中都做了详细的说明,所以就不在介绍了。

    Kissable.java

    package com.wzpmt.entity.boy; public class Kissable { public void kiss(){ System.out.println("父类的方法"); } }

    LiSi.java

    package com.wzpmt.entity.boy; public class LiSi extends Kissable{ public void kiss() { System.out.println("非常丑的李四"); } }

    ZhanSan.java

    package com.wzpmt.entity.boy; public class ZhanSan extends Kissable{ @Override public void kiss() { System.out.print("非常酷的张三"); } }

    Girl.jva

    package com.wzpmt.entity.girl; import com.wzpmt.entity.boy.Kissable; import com.wzpmt.ioc.IocUtil; public class Girl { Kissable kissable=(Kissable) IocUtil.getEntity(); public void kiss(){ System.out.println("我想kiss"); kissable.kiss(); } }


    IocUtil.java

    package com.wzpmt.ioc; public class IocUtil { public static Object getEntity(){ //通过外部容器获得类路径 String classPaht=ReadConfig.getClassPath(); if(classPaht==null) return null; try { return (Object)Class.forName(classPaht).newInstance(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } }

    ReadConfig.java

    package com.wzpmt.ioc; import java.io.FileInputStream; import java.util.Properties; public class ReadConfig { static Properties prop; static{ try { //获取ioc.properties所在目录 String path=getRootPath()+"ioc.properties"; System.out.println(path); FileInputStream fi = new FileInputStream(path); prop=new Properties(); prop.load(fi); fi.close(); } catch (Exception e) { e.printStackTrace(); } } public static String getClassPath(){ if(prop==null) return null; return prop.get("kiss").toString(); } private static String getRootPath(){ String path=Thread.currentThread().getContextClassLoader().getResource("").getPath(); //替换空格产生的%20 path=path.replace("%20", " "); //由于路径第一个字符是/ ,所以去掉 //return path.substring(1); // 测试下可以不用去掉 /D:/work/zqgame 和 D:/work/zqgame 都可以得到正确位置 return path; } public static void main(String[] args) { //当前文件所在路径 //String path=ReadConfig.class.getResource("").getPath(); //获得bin路径 System.out.println(getRootPath()); } }

    Test.java

    package com.wzpmt.test; import com.wzpmt.entity.girl.Girl; public class Test { /** * @param args */ public static void main(String[] args) { Girl girl=new Girl(); girl.kiss(); } }

    ioc.properties
    #kiss=com.wzpmt.entity.boy.LiSi kiss=com.wzpmt.entity.boy.ZhanSan

    这个程序实现了Girl想kiss谁,必须有容器提供,可以在ioc.properties中配置 欢迎共同探讨


    展开全文
  • 最近在做一个监控系统,需要制作两个图形,一个度盘,一个波形图,最先开始使用了JFreeChart绘制图形,但是在服务器端绘制图形鸭梨很大,占用带宽多,浏览图形不畅快,抛弃之。     然后觉得...
  • 在ioc环境里,在一个UserAction 要获得 request对象,可以这么实现: 让UserAction 实现ServletRequestAware接口,然后在UserAction里面写下面这个方法: public HttpServletRequest request;//定义...
  • Spring学习笔记IOC与AOP实例 ...在以XML语言描述的配置文件中,声明web系统中哪个组件需要哪一种服务时,不是在程序中让对象和服务直接连接,具体负责连接工作的是Web容器,Spring中就是Ioc容器。 1 IoC的优...

    常听到前辈讲Spring有2大核心:
    Spring学习笔记IOC与AOP实例
    Spring框架核心由两部分组成:
    觉得不错大家点赞支持下呗
    第一部分是反向控制(IOC),也叫依赖注入(DI);

    控制反转(依赖注入)的主要内容是指:只描述程序中对象的被创建方式但不显示的创建对象。在以XML语言描述的配置文件中,声明web系统中哪个组件需要哪一种服务时,不是在程序中让对象和服务直接连接,具体负责连接工作的是Web容器,Spring中就是Ioc容器。
    1
    IoC的优点和缺点

    优点:因为把对象生成放在了XML里定义,所以当我们需要换一个实现子类将会变成很简单(一般这样的对象都是实现于某种接口的),只要修改XML就可以了,这样我们甚至可以实现对象的热插拔(有点象USB接口和SCIS硬盘了)。**

    缺点:(1)生成一个对象的步骤变复杂了(其实上操作上还是挺简单的),对于不习惯这种方式的人,会觉得有些别扭和不直观。(2)对象生成因为是使用反射编程,在效率上有些损耗。但相对于IoC提高的维护性和灵活性来说,这点损耗是微不足道的,除非某对象的生成对效率要求特别高。(3)缺少IDE重构操作的支持,如果在Eclipse要对类改名,那么你还需要去XML文件里手工去改了,这似乎是所有XML方式的缺憾所在。

       开发中具体实现方式:
    

    1
    2
    SSH深度历险(八) 剖析SSH核心原理+Spring依赖注入的三种方式

          1.JavaBean的Setter方法注入
    

    1
    如图:
    在这里插入图片描述

    接口 Logic.java

       package DI;
        
        /**
        
        类Logic.java的实现描述:TODO 类实现描述
        
        @author jinlian.xjl 2015年7月6日 下午2:02:35
        */
        public interface Logic {
        
        public String getName();
        
        }
    接口实现类 LogicImpl.java
    
    package DI;
    
        /**
    
    类Logiclmpl.java的实现描述:TODO 类实现描述
    
    @author jinlian.xjl 2015年7月6日 下午2:03:53
    */
    public class Logiclmpl implements Logic {
    
    public String getName() {
    return “xiong jinlian”;
    }
    

    } 
    一个处理类 LoginAction.java(LoginAction.java 会根据使用不同的注入方法而稍有不同)

    package DI;
     
    /**
     * 类LoginAction.java的实现描述:TODO 类实现描述
     * @author jinlian.xjl 2015年7月6日 下午2:07:10
     */
    public class LoginAction {
     
        private Logic logic;
     
        /**
         * @return the logic
         */
        public Logic getLogic() {
            return logic;
        }
     
        /**
         * @param logic the logic to set
         */
        public void setLogic(Logic logic) {
            this.logic = logic;
        }
     
        public void execute() {
            String name = logic.getName();
            System.out.println("My name is " + name);
        }
     
    }
    
    package DI;
    
    /**
    
    类LoginAction.java的实现描述:TODO 类实现描述
    
    @author jinlian.xjl 
    */
    public class LoginAction {
    
    private Logic logic;
    
    /**
    
    @return the logic
    */
    public Logic getLogic() {
    return logic;
    }
    /**
    
    @param logic the logic to set
    */
    public void setLogic(Logic logic) {
    this.logic = logic;
    }
    public void execute() {
    String name = logic.getName();
    System.out.println("My name is " + name);
    }
    
    }
    

    还有一个测试类 TestMain.java(客户端测试类)

    package DI;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    /**
    
    类TestMain.java的实现描述:TODO 类实现描述
    
    @author jinlian.xjl 
    */
    public class TestMain {
    
    /**
    
    @param args
    */
    public static void main(String[] args) {
    // TODO Auto-generated method st
    ApplicationContext ac = new ClassPathXmlApplicationContext(“appContext.xml”);
    LoginAction la = (LoginAction) ac.getBean(“loginAction”);
    la.execute();
    }
    }
    

    定义了一个Logic 类型的变量 logic, 在LoginAction并没有对logic 进行实例化,而只有他对应的setter/getter方法,因为我们这里使用的是Spring的依赖注入的方式

    appContext.xml

    <?xml version="1.0"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
        <!--配置spring的bean-->
        <bean id="logiclmpl"   class="DI.Logiclmpl"></bean>
        <bean id="loginAction" class="DI.LoginAction">
            <property name="logic"  ref="logiclmpl"></property>
        </bean>
     </beans>
    

    运行截图:
    在这里插入图片描述
    2.构造方法注入

    构造方法注入,就是我们依靠LoginAction的构造方法来达到DI的目的,如下所示,添加了一个LoginAction的构造方法:

    LoginAction.java

    package DI;
    
    /**
    
    类LoginAction.java的实现描述:TODO 类实现描述
    
    @author jinlian.xjl 2015年7月6日 下午2:07:10
    */
    public class LoginAction {
    
    private Logic logic;
    
    public LoginAction(Logic logic){
    this.logic = logic;
    }
    
    public void execute() {
    String name = logic.getName();
    System.out.println("My name is " + name + “构造方法注入”);
    }
    }
    

    appContext.xml

     <?xml version="1.0"?>
        <beans xmlns="http://www.springframework.org/schema/beans"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:schemaLocation="http://www.springframework.org/schema/beans
                   http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
            <!--配置spring的bean-->
            <bean id="logiclmpl"   class="DI.Logiclmpl"></bean>
            <bean id="loginAction" class="DI.LoginAction">
                <constructor-arg index="0" ref="logiclmpl"></constructor-arg>
            </bean>
    
     </beans> 
    

    使用constructor-arg来进行配置, index属性是用来表示构造方法中参数的顺序的,如果有多个参数,则按照顺序,从 0,1…来配置。其中需要注意一点:构造函数有多个参数的话,如:参数1,参数2,而参数2依赖于参数1,这种情况则要注意构造函数的顺序,必须将参数1放在参数2之前。

    我们现在可以运行testMain.java了,结果跟使用Setter方法注入完全一样.
    在这里插入图片描述
    3.接口注入
    1
    不常用到的接口注入,还是以LogicAction为例,我们对他进行了修改,如下所示:

    LogicAction.java

    package DI;
    
    /**
    
    类LoginAction.java的实现描述:TODO 类实现描述
    
       
    
     @author jinlian.xjl 2015年7月6日 下午2:07:10
        */
        public class LoginAction {
        
        private Logic logic;
        
        public void execute() {
        try {
        // forName(String className)返回与带有给定字符串名的类或接口相关联的 Class 对象。
        Class clazz = Class.forName(“DI.Logiclmpl”);
        
             // newInstance() 创建此 Class 对象所表示的类的一个新实例。
             logic = (Logic) clazz.newInstance();
        
             String name = logic.getName();
             System.out.println("My name is " + name + "测试接口注入");
        
         } catch (Exception e) {
        
             e.printStackTrace();
         }
    

    这里是引用

    }
    }
      appContext.xml

    <?xml version="1.0"?> <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
        <!--配置spring的bean-->
        <bean id="logiclmpl"   class="DI.Logiclmpl"></bean>
        <bean id="loginAction" class="DI.LoginAction"></bean>  </beans>
    

    运行:
     
    在这里插入图片描述
    小结:

    对于Spring的依赖注入,最重要的就是理解它们,无非就是让容器来给我们实例化那些类,我们要做的就是给容器提供这个接口,这个接口就我们的set方法或者构造函数了。
    1
    第二部分面向方面的编程(AOP).

    1.Aop简介

    AOP(Aspect Oriented Programming):面向切面编程(面向方面编程),通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,提高开发效率。

    用途:

    AOP 来处理一些具有横切性质的系统性服务,如事物管理、安全检查、缓存、对象池管理(日志记录,性能统计,安全控制,权限管理,事务处理,异常处理,资源池管理)等

    AOP 的实现原理:
    1
    2
    3
    4
    5
    6
    7

    如图:AOP 实际上是由目标类的代理类实现的。AOP 代理其实是由 AOP 框架动态生成的一个对象,该对象可作为目标对象使用。AOP 代理包含了目标对象的全部方法,但 AOP 代理中的方法与目标对象的方法存在差异,AOP 方法在特定切入点添加了增强处理,并回调了目标对象的方法。

    Spring 中对 AOP 的支持:

     Spring 中 AOP 代理由 Spring 的 IoC 容器负责生成、管理,其依赖关系也由 IoC 容器负责管理。因此,AOP 代理可以直接使用容器中的其他 Bean 实例作为目标,这种关系可由 IoC 容器的依赖注入提供。Spring 默认使用 Java 动态代理来创建 AOP 代理, 这样就可以为任何接口实例创建代理了。当需要代理的类不是代理接口的时候, Spring 自动会切换为使用 CGLIB 代理,也可强制使用 CGLIB。 
    
     AOP 编程需要程序员参与的只有三个部分:
    

    1
    2
    3
    4
    5
    6
    7
    定义普通业务组件。
    定义切入点,一个切入点可能横切多个业务组件。
    定义增强处理,增强处理就是在 AOP 框架为普通业务组件织入的处理动作。
    所以进行 AOP 编程的关键就是定义切入点和定义增强处理。一旦定义了合适的切入点和增强处理,AOP 框架将会自动生成 AOP 代理,即:代理对象的方法 = 增强处理 + 被代理对象的方法。

    Spring 中 AOP 的实现:

    Spring 有如下两种选择来定义切入点和增强处理。
    

    1
    2
    3
    基于 Annotation注解的“零配置”方式:使用@Aspect、@Pointcut等 Annotation 来标注切入点和增强处理。
    基于 XML 配置文件的管理方式:使用 Spring 配置文件来定义切入点和增强点。

    1). 切面(Aspect)

    官方的抽象定义为“一个关注点的模块化,这个关注点可能会横切多个对象”,在本例中,“切面”就是类TestAspect所关注的具体行为,例如:AServiceImpl.barA()的调用就是切面TestAspect所关注的行为之一。“切面”在ApplicationContext中aop:aspect来配置。

    2). 连接点(Joinpoint)

    程序执行过程中的某一行为,例如,AServiceImpl.barA()的调用或者BServiceImpl.barB(String _msg, int _type)抛出异常等行为。

    3). 通知(Advice)

    “切面”对于某个“连接点”所产生的动作,例如,TestAspect中对com.spring.service包下所有类的方法进行日志记录的动作就是一个Advice。其中,一个“切面”可以包含多个“Advice”,例如TestAspect。Advice共有如下5种类型:

    A 前置通知(Before advice) :在某连接点(JoinPoint)之前执行的通知,但这个通知不能阻止连接点前的执行。xml中在aop:aspect里面使用aop:before元素进行声明;例如,TestAspect中的doBefore方法。注解中使用@Before声明;例如,TestAnnotationAspect中的doBefore方法。

    B 后通知(After advice) :当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。xml中在aop:aspect里面使用aop:after元素进行声明。例如,TestAspect中的doAfter方法,所以AOPTest中调用BServiceImpl.barB抛出异常时,doAfter方法仍然执行。注解中使用@After声明。

    C 返回后通知(After return advice) :在某连接点正常完成后执行的通知,不包括抛出异常的情况。xml中在aop:aspect里面使用元素进行声明。注解中使用@AfterReturning声明;
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    D 环绕通知(Around advice) :包围一个连接点的通知,类似Web中Servlet规范中的Filter的doFilter方法。可以在方法的调用前后完成自定义的行为,也可以选择不执行。xml中在aop:aspect里面使用aop:around元素进行声明。例如,TestAspect中的doAround方法。注解中使用@Around声明。

    E 抛出异常后通知(After throwing advice) : 在方法抛出异常退出时执行的通知。xml中在aop:aspect里面使用aop:after-throwing元素进行声明。例如,TestAspect中的doThrowing方法。注解中使用@AfterThrowing声明。

    通知执行顺序:前置通知→环绕通知连接点之前→连接点执行→环绕通知连接点之后→返回通知→后置通知→(如果发生异常)异常通知→后通知

    4). 切入点(Pointcut)

    匹配连接点的断言,在AOP中通知和一个切入点表达式关联。例如,TestAspect中的所有通知所关注的连接点,都由切入点表达式execution(* com.spring.service..(…))来决定。

    ● 切入点表达式

    execution:用于匹配方法执行的连接点;

    within:用于匹配指定类型内的方法执行;

    this:用于匹配当前AOP代理对象类型的执行方法;注意是AOP代理对象的类型匹配,这样就可能包括引入接口也类型匹配;注意this中使用的表达式必须是完整类名,不支持通配符;

    target:用于匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配,这样就不包括引入接口也类型匹配;注意target中使用的表达式必须是完整类名,不支持通配符;

    args:用于匹配当前执行的方法传入的参数为指定类型的执行方法;参数类型列表中的参数必须是完整类名,通配符不支持;args属于动态切入点,这种切入点开销非常大,非特殊情况最好不要使用;

    @within:用于匹配所以持有指定注解类型内的方法;注解类型也必须是完整类名;

    @target:用于匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解;注解类型也必须是完整类名;

    @args:用于匹配当前执行的方法传入的参数持有指定注解的执行;注解类型也必须是完整类名;

    @annotation:用于匹配当前执行方法持有指定注解的方法;注解类型也必须是完整类名;

    bean:Spring AOP扩展的,AspectJ没有对于指示符,用于匹配特定名称的Bean对象的执行方法;

    reference pointcut:表示引用其他命名切入点,只有注解风格支持,XML风格不支持。

    ● 匹配语法

    匹配任何数量字符;  
      
    .. 匹配任何数量字符的重复,如在类型模式中匹配任何数量子包;而在方法参数模式中匹配任何数量参数。  
      
    + 匹配指定类型的子类型;仅能作为后缀放在类型模式后边。
    
    匹配任何数量字符;
    … 匹配任何数量字符的重复,如在类型模式中匹配任何数量子包;而在方法参数模式中匹配任何数量参数。
    
    匹配指定类型的子类型;仅能作为后缀放在类型模式后边。
    

    例如:
    java.lang.String 匹配String类型;

    java.*.String 匹配java包下的任何“一级子包”下的String类型;如匹配java.lang.String,但不匹配java.lang.ss.String。

    java…* 匹配java包及任何子包下的任何类型;如匹配java.lang.String、java.lang.annotation.Annotation。

    java.lang.*ing 匹配任何java.lang包下的以ing结尾的类型;

    java.lang.Number+ 匹配java.lang包下的任何Number的自类型;如匹配java.lang.Integer,也匹配java.math.BigInteger。

    ● 匹配种类

    A 类

    [plain] view plaincopy

    注解 类名
    注解:可选,类上持有的注解,如@Deprecated;

    类名:必填,任何类的完整名称。

    B 方法

    [plain] view plaincopy

    注解 修饰符 返回值类型 类名 方法名(参数列表) 异常列表
    注解:可选,方法上持有的注解,如@Deprecated;

    修饰符:可选,如public、protected;

    返回值类型:必填,可以是任何类型模式;“*”表示所有类型;

    类名:可选,任何类的完整名称;

    方法名:必填,可以使用“*”进行模式匹配;

    参数列表:“()”表示方法没有任何参数;“(…)”表示匹配接受任意个参数的方法,“(…,java.lang.String)”表示匹配接受java.lang.String类型的参数结束,且其前边可以接受有任意个参数的方法;“(java.lang.String,…)” 表示匹配接受java.lang.String类型的参数开始,且其后边可以接受任意个参数的方法;“(*,java.lang.String)” 表示匹配接受java.lang.String类型的参数结束,且其前边接受有一个任意类型参数的方法;

    异常列表:可选,以“throws 异常全限定名列表”声明,异常全限定名列表如有多个以“,”分割,如throws java.lang.IllegalArgumentException, java.lang.ArrayIndexOutOfBoundsException。

    C Bean

    可以使用Bean的id或name进行匹配,并且可使用通配符“*”。

    ● 匹配逻辑运算

    可以使用且(&&)、或(||)、非(!)来组合切入点表达式。由于在XML中使用“&&”需要使用转义字符“&&”来代替之,所以很不方便,因此Spring ASP 提供了and、or、not来代替&&、||、!。

    ● 切入点表达式示例

    在这里插入代码片A execution
    
    模式	描述
    public * *(..)	任何公共方法的执行
    * cn.javass..IPointcutService.*()	cn.javass包及所有子包下IPointcutService接口中的任何无参方法
    * cn.javass..*.*(..)	cn.javass包及所有子包下任何类的任何方法
    * cn.javass..IPointcutService.*(*)	cn.javass包及所有子包下IPointcutService接口的任何只有一个参数方法
    * (!cn.javass..IPointcutService+).*(..)	非“cn.javass包及所有子包下IPointcutService接口及子类型”的任何方法
    * cn.javass..IPointcutService+.*()	cn.javass包及所有子包下IPointcutService接口及子类型的的任何无参方法
    *  cn.javass..IPointcut*.test*(java.util.Date)	cn.javass包及所有子包下IPointcut前缀类型的的以test开头的只有一个参数类型为java.util.Date的方法,注意该匹配是根据方法签名的参数类型进行匹配的,而不是根据执行时传入的参数类型决定的如定义方法:public void test(Object obj);即使执行时传入java.util.Date,也不会匹配的;
    * cn.javass..IPointcut*.test*(..) throws IllegalArgumentException, ArrayIndexOutOfBoundsException	cn.javass包及所有子包下IPointcut前缀类型的的任何方法,且抛出IllegalArgumentException和ArrayIndexOutOfBoundsException异常
    * (cn.javass..IPointcutService+&& java.io.Serializable+).*(..)	任何实现了cn.javass包及所有子包下IPointcutService接口和java.io.Serializable接口的类型的任何方法
    @java.lang.Deprecated * *(..)	任何持有@java.lang.Deprecated注解的方法
    @java.lang.Deprecated @cn.javass..Secure  * *(..)	任何持有@java.lang.Deprecated和@cn.javass..Secure注解的方法
    @(java.lang.Deprecated ||  cn.javass..Secure) * *(..)	任何持有@java.lang.Deprecated或@  cn.javass..Secure注解的方法
    (@cn.javass..Secure *) *(..)	任何返回值类型持有@cn.javass..Secure的方法
    * (@cn.javass..Secure *).*(..)	任何定义方法的类型持有@cn.javass..Secure的方法
    * *(@cn.javass..Secure (*) ,  @cn.javass..Secure (*))	任何签名带有两个参数的方法,且这个两个参数都被@ Secure标记了,如public void test(@Secure String str1,@Secure String str1);
    * *((@ cn.javass..Secure *))或* *(@ cn.javass..Secure *)	任何带有一个参数的方法,且该参数类型持有@ cn.javass..Secure;如public void test(Model model);且Model类上持有@Secure注解
    * *(@cn.javass..Secure (@cn.javass..Secure *)  ,@ cn.javass..Secure (@cn.javass..Secure  *))	任何带有两个参数的方法,且这两个参数都被@ cn.javass..Secure标记了;且这两个参数的类型上都持有@  cn.javass..Secure;
    * *(java.util.Map<cn.javass..Model, cn.javass..Model>, ..)	任何带有一个java.util.Map参数的方法,且该参数类型是以<  cn.javass..Model, cn.javass..Model >为泛型参数;注意只匹配第一个参数为java.util.Map,不包括子类型;如public void test(HashMap<Model, Model> map, String str);将不匹配,必须使用“* *(java.util.HashMap<cn.javass..Model,cn.javass..Model>, ..)”进行匹配;而public void test(Map map, int i);也将不匹配,因为泛型参数不匹配
    *  *(java.util.Collection<@cn.javass..Secure *>)	任何带有一个参数(类型为java.util.Collection)的方法,且该参数类型是有一个泛型参数,该泛型参数类型上持有@cn.javass..Secure注解;如public void test(Collection<Model> collection);Model类型上持有@cn.javass..Secure
    B within
    
    模式	描述
    within(cn.javass..*)	cn.javass包及子包下的任何方法执行
    within(cn.javass..IPointcutService+)	cn.javass包或所有子包下IPointcutService类型及子类型的任何方法
    within(@cn.javass..Secure *)	持有cn.javass..Secure注解的任何类型的任何方法必须是在目标对象上声明这个注解,在接口上声明的对它不起作用
    C this
    
    模式	描述
    this(cn.javass.spring.chapter6.service.IPointcutService)	当前AOP对象实现了 IPointcutService接口的任何方法
    this(cn.javass.spring.chapter6.service.IIntroductionService)	
    当前AOP对象实现了 IIntroductionService接口的任何方法也可能是引入接口
    
    D target
    
    模式	描述
    target(cn.javass.spring.chapter6.service.IPointcutService)	当前目标对象(非AOP对象)实现了 IPointcutService接口的任何方法
    target(cn.javass.spring.chapter6.service.IIntroductionService)	当前目标对象(非AOP对象) 实现了IIntroductionService 接口的任何方法不可能是引入接口
     
    
    模式	描述
    args (java.io.Serializable,..)	任何一个以接受“传入参数类型为 java.io.Serializable” 开头,且其后可跟任意个任意类型的参数的方法执行,args指定的参数类型是在运行时动态匹配的
    F @within
    
    模式	描述
    @within  cn.javass.spring.chapter6.Secure)	任何目标对象对应的类型持有Secure注解的类方法;必须是在目标对象上声明这个注解,在接口上声明的对它不起作用
    G @target
    
    模式	描述
    @target (cn.javass.spring.chapter6.Secure)	任何目标对象持有Secure注解的类方法;必须是在目标对象上声明这个注解,在接口上声明的对它不起作用
    H @args
    
    模式	描述
    @args (cn.javass.spring.chapter6.Secure)	任何一个只接受一个参数的方法,且方法运行时传入的参数持有注解 cn.javass.spring.chapter6.Secure;动态切入点,类似于arg指示符;
    I @annotation
    
    模式	描述
    @annotation(cn.javass.spring.chapter6.Secure  )	当前执行方法上持有注解  cn.javass.spring.chapter6.Secure将被匹配
    J bean
    
    模式	描述
    bean(*Service)	
    匹配所有以Service命名(id或name)结尾的Bean
    

    A execution

    模式 描述
    public * *(…) 任何公共方法的执行

    cn.javass…IPointcutService.() cn.javass包及所有子包下IPointcutService接口中的任何无参方法
    cn.javass….(…) cn.javass包及所有子包下任何类的任何方法
    cn.javass…IPointcutService.() cn.javass包及所有子包下IPointcutService接口的任何只有一个参数方法
    (!cn.javass…IPointcutService+).
    (…) 非“cn.javass包及所有子包下IPointcutService接口及子类型”的任何方法
    cn.javass…IPointcutService+.() cn.javass包及所有子包下IPointcutService接口及子类型的的任何无参方法
    cn.javass…IPointcut
    .test*(java.util.Date) cn.javass包及所有子包下IPointcut前缀类型的的以test开头的只有一个参数类型为java.util.Date的方法,注意该匹配是根据方法签名的参数类型进行匹配的,而不是根据执行时传入的参数类型决定的如定义方法:public void test(Object obj);即使执行时传入java.util.Date,也不会匹配的;
    cn.javass…IPointcut*.test*(…) throws IllegalArgumentException, ArrayIndexOutOfBoundsException cn.javass包及所有子包下IPointcut前缀类型的的任何方法,且抛出IllegalArgumentException和ArrayIndexOutOfBoundsException异常
    (cn.javass…IPointcutService+&& java.io.Serializable+).*(…) 任何实现了cn.javass包及所有子包下IPointcutService接口和java.io.Serializable接口的类型的任何方法
    @java.lang.Deprecated * *(…) 任何持有@java.lang.Deprecated注解的方法
    @java.lang.Deprecated @cn.javass…Secure * *(…) 任何持有@java.lang.Deprecated和@cn.javass…Secure注解的方法
    @(java.lang.Deprecated || cn.javass…Secure) * *(…) 任何持有@java.lang.Deprecated或@ cn.javass…Secure注解的方法
    (@cn.javass…Secure *) (…) 任何返回值类型持有@cn.javass…Secure的方法
    (@cn.javass…Secure ).(…) 任何定义方法的类型持有@cn.javass…Secure的方法
    (@cn.javass…Secure () , @cn.javass…Secure (
    )) 任何签名带有两个参数的方法,且这个两个参数都被@ Secure标记了,如public void test(@Secure String str1,@Secure String str1);
    *((@ cn.javass…Secure ))或 *(@ cn.javass…Secure *) 任何带有一个参数的方法,且该参数类型持有@ cn.javass…Secure;如public void test(Model model);且Model类上持有@Secure注解
    *(@cn.javass…Secure (@cn.javass…Secure *) ,@ cn.javass…Secure (@cn.javass…Secure *)) 任何带有两个参数的方法,且这两个参数都被@ cn.javass…Secure标记了;且这两个参数的类型上都持有@ cn.javass…Secure;
    (java.util.Map<cn.javass…Model, cn.javass…Model>, …) 任何带有一个java.util.Map参数的方法,且该参数类型是以< cn.javass…Model, cn.javass…Model >为泛型参数;注意只匹配第一个参数为java.util.Map,不包括子类型;如public void test(HashMap<Model, Model> map, String str);将不匹配,必须使用“ *(java.util.HashMap<cn.javass…Model,cn.javass…Model>, …)”进行匹配;而public void test(Map map, int i);也将不匹配,因为泛型参数不匹配
    *(java.util.Collection<@cn.javass…Secure >) 任何带有一个参数(类型为java.util.Collection)的方法,且该参数类型是有一个泛型参数,该泛型参数类型上持有@cn.javass…Secure注解;如public void test(Collection collection);Model类型上持有@cn.javass…Secure
    B within
    模式 描述
    within(cn.javass…
    ) cn.javass包及子包下的任何方法执行
    within(cn.javass…IPointcutService+) cn.javass包或所有子包下IPointcutService类型及子类型的任何方法
    within(@cn.javass…Secure *) 持有cn.javass…Secure注解的任何类型的任何方法必须是在目标对象上声明这个注解,在接口上声明的对它不起作用
    C this

    模式 描述
    this(cn.javass.spring.chapter6.service.IPointcutService) 当前AOP对象实现了 IPointcutService接口的任何方法
    this(cn.javass.spring.chapter6.service.IIntroductionService)
    当前AOP对象实现了 IIntroductionService接口的任何方法也可能是引入接口

    D target

    模式 描述
    target(cn.javass.spring.chapter6.service.IPointcutService) 当前目标对象(非AOP对象)实现了 IPointcutService接口的任何方法
    target(cn.javass.spring.chapter6.service.IIntroductionService) 当前目标对象(非AOP对象) 实现了IIntroductionService 接口的任何方法不可能是引入接口

    模式 描述
    args (java.io.Serializable,…) 任何一个以接受“传入参数类型为 java.io.Serializable” 开头,且其后可跟任意个任意类型的参数的方法执行,args指定的参数类型是在运行时动态匹配的
    F @within

    模式 描述
    @within cn.javass.spring.chapter6.Secure) 任何目标对象对应的类型持有Secure注解的类方法;必须是在目标对象上声明这个注解,在接口上声明的对它不起作用
    G @target

    模式 描述
    @target (cn.javass.spring.chapter6.Secure) 任何目标对象持有Secure注解的类方法;必须是在目标对象上声明这个注解,在接口上声明的对它不起作用
    H @args

    模式 描述
    @args (cn.javass.spring.chapter6.Secure) 任何一个只接受一个参数的方法,且方法运行时传入的参数持有注解 cn.javass.spring.chapter6.Secure;动态切入点,类似于arg指示符;
    I @annotation

    模式 描述
    @annotation(cn.javass.spring.chapter6.Secure ) 当前执行方法上持有注解 cn.javass.spring.chapter6.Secure将被匹配
    J bean

    模式 描述
    bean(*Service)
    匹配所有以Service命名(id或name)结尾的Bean

    K reference pointcut
    
    [java] view plaincopy
    
    @Pointcut(value=“bean(*Service)”)
    private void pointcut1(){}
    
    @Pointcut(value="@args(cn.javass.spring.chapter6.Secure)")
    private void pointcut2(){}
    
    @Pointcut(value=“pointcut1()&&pointcut2()”)
    private void pointcut3(){}
    

    ● 通知方法参数注入

    在Spring AOP中,除了execution和bean指示符不能传递参数给通知方法,其他指示符都可以将匹配的相应参数或对象自动传递给通知方法。例如:

    [java] view plaincopy
    
    @Before(value="execution(* test()) && args(param)", argNames=“param”)
    public void before1(String param) {
    System.out.println("===param:" + param);
    }
    

    首先execution( test(*))匹配任何方法名为test,且有一个任何类型的参数;

    args(param)将首先查找通知方法上同名的参数,并在方法执行时(运行时)匹配传入的参数是使用该同名参数类型,即java.lang.String;如果匹配将把该被通知参数传递给通知方法上同名参数。

    其他指示符(除了execution和bean指示符)都可以使用这种方式进行参数绑定。

    ● 综合示例

    [java] view plaincopy
    
    @Before(value=“args(param) && target(bean) && @annotation(secure)”, argNames=“jp,param,bean,secure”)
    public void before5(JoinPoint jp, String param,
    IPointcutService pointcutService, Secure secure) {
    ……
    }
    

    除了上边介绍的普通方式,也可以对使用命名切入点自动获取参数:

    [java] view plaincopy
    
    @Pointcut(value=“args(param)”, argNames=“param”)
    private void pointcut1(String param){}
    
    @Pointcut(value="@annotation(secure)", argNames=“secure”)
    private void pointcut2(Secure secure){}
    
    @Before(value = “pointcut1(param) && pointcut2(secure)”, argNames=“param, secure”)
    public void before6(JoinPoint jp, String param, Secure secure) {
    ……
    

    }
    5). 目标对象(Target Object)

    被一个或者多个切面所通知的对象。例如,AServcieImpl和BServiceImpl,当然在实际运行时,Spring AOP采用代理实现,实际AOP操作的是TargetObject的代理对象。

    6). AOP代理(AOP Proxy)

    在Spring AOP中有两种代理方式,JDK动态代理和CGLIB代理。默认情况下,TargetObject实现了接口时,则采用JDK动态代理,例如:AServiceImpl;反之,采用CGLIB代理,例如:BServiceImpl。强制使用CGLIB代理需要将 aop:config的 proxy-target-class属性设为true。

    XML方式实例:

    文件目录路径如下:

    在这里插入图片描述
    切面类TestAspect.java:
    1
    2

    package AOP;

    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;

    public class TestAspect {

    public void doBefore(JoinPoint jp) {
    System.out.println(“Before :” + jp.getTarget().getClass().getName() + “……” + jp.getSignature().getName());
    }

    public void doAfter(JoinPoint jp) {
    System.out.println(“After :” + jp.getTarget().getClass().getName() + “……” + jp.getSignature().getName());
    }

    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
    long time = System.currentTimeMillis();
    Object retVal = pjp.proceed();
    time = System.currentTimeMillis() - time;
    System.out.println(“Around : process time:” + “……” + time + " ms");
    return retVal;
    }

    public void doThrowing(JoinPoint jp, Throwable ex) {
    System.out.println(“Throwing :” + jp.getTarget().getClass().getName() + “……” + jp.getSignature().getName());
    System.out.println("Throwing : " + ex.getMessage());

    }
    1
    2

    }
      目标对象类:

          AServiceImpl.java实现接口类AService.java(实现了接口,使用jdk动态代理方式)
    

    1
    2

    package AOP;

    public interface AService {

    public void barA();

    public void fooA(String _msg);

    public void mayThrow(int _type);
    1
    2

    package AOP;

    //jdk动态代理方式
    public class AServiceImpl implements AService {

    public void barA() {

    System.out.println("AServiceImpl.barA()");
    

    }

    public void fooA(String _msg) {

    System.out.println("AServiceImpl.fooA(_msg:)" + _msg + ")");
    

    }

    public void mayThrow(int _type) {
    if (_type == 1) {
    throw new IllegalArgumentException(“这是AServiceImpl异常测试”);
    }
    }
    1
    2

    }
    目标对象类:

         BServiceImpl.java(并未实现任何借口,默认cglib方式) 
    

    1
    1

    package AOP;

    //cglib
    public class BServiceImpl {

    public void barB(String _msg, int _type) {
    System.out.println(“BServiceImpl.barB(msg:” + _msg + “)”);
    if (_type == 1) {
    throw new IllegalArgumentException(“这是BServiceImpl异常测试”);
    }
    }

    public void fooB() {
    System.out.println(“BServiceImpl.fooB()”);
    }
    1
    2

    }
    appContext.xml文件:Spring配置文件

    1
    2

    15

    <?xml version="1.0"?>

    aop:config
    <aop:aspect id=“asTestAspect” ref=“testAspect”>
    <aop:pointcut id=“pcService” expression=“execution(* AOP…(…))”></aop:pointcut>
    <aop:before pointcut-ref=“pcService” method=“doBefore”/>
    <aop:after pointcut-ref=“pcService” method=“doAfter”/>
    <aop:around pointcut-ref=“pcService” method=“doAround”/>
    <aop:after-throwing pointcut-ref=“pcService” method=“doThrowing” throwing=“ex”/>
    </aop:aspect>
    </aop:config>

    客户端测试:ClientMain.java

    1
    2

    package AOP;

    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;

    public class ClientMain {

    public static void main(String[] args) {

    ApplicationContext ac = new ClassPathXmlApplicationContext("appContext.xml");
    AService aSerImpl = (AService) ac.getBean("aServiceImpl");
    aSerImpl.barA();
    System.out.println("---------------------------------------");
    aSerImpl.fooA("Client main 测试  AServiceImpl  Jdk动态代理");
    System.out.println("---------------------------------------");
    aSerImpl.mayThrow(1);
    
    System.out.println("*******************************************************");
    
    /*
     * BServiceImpl bSerImpl = (BServiceImpl) ac.getBean("bServiceImpl");
     * bSerImpl.barB("Client main 测试  BServiceImpl  cglib", 1); System.out.println("----------------------");
     * bSerImpl.fooB();
     */
    

    }
    1
    2

    }
      运行结果:

    友情链接

    Spring Aop实例 http://blog.csdn.net/wangpeng047/article/details/8560694

    Spring AOP 的简单例子
    Spring AOP 实现了AOP联盟(Alliance)的制定的接口规范,它基于java的代理机制实现。AOP作为Spring的核心技术之一. 更多关于Spring AOP介绍 可参考:http://oss.org.cn/ossdocs/framework/spring/zh-cn/aop.html 下面给出一个例子来简单介绍Spring AOP具体实现过程

    现假设用户通过login.jsp页面输入相应的用户名和密码之后,首先Spring AOP的环绕通知验证该用户名和密码是否符合要求,若符合要求,则到数据库中查找该用户,若用户存在,将该用户相关的信息写入日志。
    1
    1.BaseLoginAdvice 类实现了 前置通知接口(MethodBeforeAdvice)、环绕通知接口(MethodInterceptor)、后置通知接口(AfterReturningAdvice) 这三个接口

    BaseLoginAdvice.java

    1
    2

    package com.laoyangx.Aop.chapter0;

    import java.lang.reflect.Method;

    import org.aopalliance.intercept.MethodInterceptor;
    import org.aopalliance.intercept.MethodInvocation;
    import org.springframework.aop.AfterReturningAdvice;
    import org.springframework.aop.MethodBeforeAdvice;

    public abstract class BaseLoginAdvice implements MethodBeforeAdvice, MethodInterceptor,
    AfterReturningAdvice {
    /**

    • @param returnValue 目标方法返回值
    • @param method 目标方法
    • @param args 方法参数
    • @param target 目标对象

    */
    @Override
    public void afterReturning(Object returnValue, Method method,
    Object[] args, Object target) throws Throwable {

     throw new UnsupportedOperationException("abstract class CBaseLoginAdvice not implement this method");
    

    }

    /**

    • @param invocation 目标对象的方法
      */
      @Override
      public Object invoke(MethodInvocation invocation) throws Throwable {

      throw new UnsupportedOperationException(“abstract class CBaseLoginAdvice not implement this method”);
      }

    /**

    • @param method 将要执行的目标对象方法

    • @param args 方法的参数

    • @param target 目标对象
      */
      @Override
      public void before(Method method, Object[] args, Object target)
      throws Throwable {

      throw new UnsupportedOperationException(“abstract class CBaseLoginAdvice not implement this method”);
      }
      1
      2
      }
      2.LoginAdviceSupport 类继承 BaseLoginAdvice 类,并重写 BaseLoginAdvice 类的三个方法

    LoginAdviceSupport.java

    1
    2

    package com.laoyangx.Aop.chapter0;

    import java.lang.reflect.Method;

    import org.aopalliance.intercept.MethodInvocation;

    public class LoginAdviceSupport extends BaseLoginAdvice {

    /**

    • 若在数据库中存在指定的用户,将用户登录信息写入日志文件

    • @param returnValue 目标方法返回值

    • @param method 目标方法

    • @param args 方法参数

    • @param target 目标对象
      */
      @Override
      public void afterReturning(Object returnValue, Method method,
      Object[] args, Object target) throws Throwable {

      System.out.println("---------- 程序正在执行 类名: com.laoyangx.Aop.chapter0.LoginAdviceSupport 方法名:afterReturning ----------------");

      //将用户登录信息写入日志文件
      }

    /**

    • 验证用户输入是否符合要求

    • @param invocation 目标对象的方法
      */
      @Override
      public Object invoke(MethodInvocation invocation) throws Throwable {

      System.out.println("---------- 程序正在执行 类名: com.laoyangx.Aop.chapter0.LoginAdviceSupport 方法名:invoke ----------------");

      String username=invocation.getArguments()[0].toString();
      String password=invocation.getArguments()[1].toString();

      //在这里进行相关的验证操作

      //假设验证通过
      return invocation.proceed();
      }

    /**

    • 在数据库中查找指定的用户是否存在

    • @param method 将要执行的目标对象方法

    • @param args 方法的参数

    • @param target 目标对象
      */
      @Override
      public void before(Method method, Object[] args, Object target)
      throws Throwable {

      System.out.println("---------- 程序正在执行 类名: com.laoyangx.Aop.chapter0.LoginAdviceSupport 方法名:before ----------------");

      String username=(String)args[0];
      String passowrd=(String)args[1];

      //在这里进行数据库查找操作
      }
      1
      2

    }
    3. IUser.java

    1
    2

    package com.laoyangx.Aop.chapter0;

    public interface IUser {
    /**

    • 用户登录
    • @param username 用户名
    • @param password 密码
      */
      public void Login(String username,String password);
      }
      4.UserImpl.java

    1
    2

    package com.laoyangx.Aop.chapter0;

    public class UserImpl implements IUser {

    /**

    • 用户登录
    • @param username 用户名
    • @param password 密码
      */
      @Override
      public void Login(String username, String password) {
      System.out.println("---------- 程序正在执行 类名: com.laoyangx.Aop.chapter0.UserImpl 方法名:Login ----------------");
      }
      1
      2

    }
    5. Spring 的配置文件 login.bean.xml

    复制代码
    复制代码

    <?xml version="1.0" encoding="UTF-8"?>

    com.laoyangx.Aop.chapter0.IUser loginAdvice 复制代码 复制代码 6.主程序文件 ConsoleApp.java
    1
    2
    3

    package com.laoyangx.Aop.chapter0;

    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;

    public class ConsoleApp {

    public static void main(String[] args) {

    ApplicationContext ctx=
        new ClassPathXmlApplicationContext("com/laoyangx/Aop/chapter0/login.bean.xml");
     
    IUser user=(IUser)ctx.getBean("user");
    user.Login("username", "123456");
    

    }
    1
    2
    }
    运行程序之后,控制台上输出的结果

    通过结果可以看到每个函数的执行顺序。关于 前置通知、环绕通知、后置通知 这些术语 网上都有相关的介绍

    Spring组成的整体架构:

    Spring 框架是一个分层架构,由 7 个定义良好的模块组成。Spring 模块构建在核心容器之上,核心容器定义了创建、配置和管理 bean 的方式,如图 1 所示。
    图 1. Spring 框架的 7 个模块
    Spring 框架图示

    组成 Spring 框架的每个模块(或组件)都可以单独存在,或者与其他一个或多个模块联合实现。每个模块的功能如下:

    核心容器:核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转 (IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。
    Spring 上下文:Spring 上下文是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。
    Spring AOP: 通过配置管理特性,Spring AOP 模块直接将面向方面的编程功能集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何对象支持 AOP。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖 EJB 组件,就可以将声明性事务管理集成到应用程序中。
    Spring DAO:JDBC DAO 抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写 的异常代码数量(例如打开和关闭连接)。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。
    Spring ORM:Spring 框架插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。
    Spring Web 模块:Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。所以,Spring 框架支持与 Jakarta Struts 的集成。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。
    Spring MVC 框架:MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText 和 POI。
    Spring 框架的功能可以用在任何 J2EE 服务器中,大多数功能也适用于不受管理的环境。Spring 的核心要点是:支持不绑定到特定 J2EE 服务的可重用业务和数据访问对象。毫无疑问,这样的对象可以在不同 J2EE 环境 (Web 或 EJB)、独立应用程序、测试环境之间重用

    展开全文
  • 1 1下面哪一个不是动态网页技术 D ) A.ASP B. JSP C.PHP D.HTML 2 下列关于 Tomcat说法不正确的是 B A.Tomcat是一个Servlet容器 B.Tomcat是一种编程语言 C.Tomcat是一个免费开源的项目 D.Tomcat的默认端口是 8080 3 ...
  • Spring之IOC小结(二)

    2020-08-26 13:09:19
    而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对 象的创建 谁控制谁? IoC 容器控制了对象 控制什么? 那就是主要控制了外部资源获取(不只是对象包括比如文件等) 1.2 为何是反转,
  • 在代码中不直接与对象和服务连接,但在配置文件进行配置,用来描述哪一个组件需要哪一项服务。简单来说就是 容器控制程序直接的关系,不是传统实现那样由代码直接控制。控制权由应用代码转到外部容器,控制权转移即...
  • 很全的Spring学习笔记

    2020-08-09 20:50:49
    在代码中不直接于对象和服务连接,但在配置文件中描述哪一组件需要哪一项服务,容器需要负责将它们联系在一起,这是一种解耦的思想,而不是一种新的技术,将控制权由应用代码转到外部容器中,由容器负责管理. ...
  • Java中的数组

    2021-01-31 07:03:44
    数组与其他种类的容器之间的区别有三方面:效率、类型和保存基本类型的能力。...无论使用种类型的数组,数组标识符只是一个引用,指向在堆中创建的一个真实对象,这个对象用以保存指向其他对象的引用
  • 关于IoC(控制反转,依赖注入)的理解

    千次阅读 2006-06-26 16:19:00
    在代码中不直接与对象 和服务连接,但在配置文件中描述哪一组件需要哪一项服务。容器负责将它们联系在一起。 2.通常,每个对象都要自己负责得到它的合作者(依赖)对象。使用IoC,对象的依赖都是对象创建时由负责...
  • Spring的IoC应用

    2016-08-03 12:03:00
    在代码中可以不直接和对象及服务器进行连接,但是在配置中说明哪一个组件需要哪一项任务,容器会负责将其联系起来。使用反向控制,对象被动接收依赖类而不是自己去创建或者查找其所依赖的对象。  在介绍Spring...
  • IOC

    2014-04-14 09:46:00
    IOC:依赖对象的创建获得被反转,所谓依赖注入,就是由IoC容器在运行期间,动态地将某种依赖关系注入到对象之中。是一种将组件依赖关系...应用方向:工厂模式用的地方,具对象哪一个,全由配置文件来控制了,这个...
  •  SessionBean: Stateless Session Bean 的生命周期是由容器决定的,当客户机发出请求要建立一个Bean的实例时,EJB容器不一定要创建一个新的Bean的实例供客户机调用,而是随便找一个现有的实例提供给客户机。...
  • 在代码中不直接与对象和服务连接,但在配置文件中描述哪一个组件需要哪一项服务。容器负责将这些联系在一起。 IoC 设计模式重点关注组件的依赖性、配置以及生命周期。 Ioc 设计模式实现了 “ 面向接口编程,而...
  • Spring面试题

    2015-05-06 07:19:39
    在代码中不直接与对象和服务连接,但在配置文件中描述哪一个组件需要哪一项服务。容器(在 Spring 框架中是 IOC 容器) 负责将这些联系在一起。 在典型的 IOC 场景中,容器创建了所有对象,并设置必要的属性将它们...
  • 02-Spring3 IoC

    2013-04-01 20:29:52
    在代码中不直接与对象和服务连接,但在配置文件中描述哪一个组件需要哪一项服务,IoC容器负责将这些联系在一起。  IoC设计模式重点关注组件的依赖性、配置以及生命周期。当然IoC也适用于简单类,而不只是组件。...
  • DOM事件模型文档对象模型 (DOM)​developer.mozilla.org事件流DOM是个树形结构,当我们在页面上单击一个按钮,页面上哪些元素会触发这个事件,是发生在这个按钮上,还是这个按钮的容器元素(我们说父元素)也会触发...
  • 自动化测试另外一个重要特点就是快速反馈,反馈越迅速意味着开发效率越高。拿UI组件为例,开发过程都是打开浏览器刷新页面点点点才能确定UI组件工作情况是否符合自己预期。接入自动化测试以后,...
  • +PageManager.Instance应该存在于HttpContext.Current,而不是一个全局变量。 -这个BUG导致Asp.net compatibility中的示例无法完成,现在已经修正。 +去除PageManager中方法AddAjaxAspnetControls,增加属性...
  • 还有个比较傻的问题:用户登录后获得一个session,很多用户对bean进行操作,而bean是单例的,那bean对象中的数据岂不是乱了? :oops: [b]问题补充:[/b] 一楼的朋友好像没有仔细看问题,答非所问啊。 我查资料说...
  • Spring的部分理论知识

    2011-04-14 13:49:22
    什么是Inversion of Control :   控制反转。在Java开发中,IoC意味着将你设计...在代码中不直接与对象和服务连接,但在配置文件中描述哪一个组件需要哪一项服务。容器负责将这些联系在一起。其原理是基于OO...
  • 原创:体验spring(二)

    2011-04-21 20:29:00
    在代码中不直接与对象和服务连接,但在配置文件中描述哪一个组件需要哪一项服务。容器负责将这些联系在一起。IoC设计模式重点关注组件的依赖性、配置以及生命周期。Ioc设计模式实现了“面向接口编程,而不是实现”的...
  • copy

    2015-08-13 14:27:28
    但对于容器而言,你这备份可能是某些地址指针,原对象进行操作,当然也会修改了容易里的指针对应的内容。 网上可能就说他不是深拷贝了。其实完全看你需求。你要这个对象到底实现你的部分需求。比如我为了解决...
  • java 面试题 总结

    2009-09-16 08:45:34
    面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。 4. 多态性: 多态性是指允许不同类的对象对同一消息作出响应。多态性包括参数化多...
  • 框架的主要优势是什么?...Spring框架分为模块,请详述? 答:Spring框架可分为七模块 1.核心容器:核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory,他是工厂模式的实现。BeanF

空空如也

空空如也

1 2 3 4
收藏数 69
精华内容 27
关键字:

哪一个不是容器对象