bean_beanutils - CSDN
bean 订阅
EJB是Enterprise Java Bean的缩写,一个Bean扮演着应用程序素材的角色。它包含有一个functional interface,一个life-cycle interface,以及一个实现它所支援的商业方法的类别。 展开全文
EJB是Enterprise Java Bean的缩写,一个Bean扮演着应用程序素材的角色。它包含有一个functional interface,一个life-cycle interface,以及一个实现它所支援的商业方法的类别。
信息
缩    写
Bean
定    义
描述Java的软件组件模型
类    型
应用程序素材的角色
目    的
将可以重复使用的软件代码打包
应用范围
应用于服务器的部件
外文名
Enterprise Java Bean
Bean定义
JavaBean是描述Java的软件组件模型,有点类似于Microsoft的COM组件概念。在Java模型中,通过JavaBean可以无限扩充Java程序的功能,通过JavaBean的组合可以快速的生成新的应用程序。对于程序员来说,最好的一点就是JavaBean可以实现代码的重复利用,另外对于程序的易维护性等等也有很重大的意义。比如说一个购物车程序,要实现购物车中添加一件商品这样的功能,就可以写一个购物车操作的JavaBean,建立一个public的AddItem成员方法,前台Jsp文件里面直接调用这个方法来实现。如果后来又考虑添加商品的时候需要判断库存是否有货物,没有货物不得购买,在这个时候我们就可以直接修改JavaBean的AddItem方法,加入处理语句来实现,这样就完全不用修改前台jsp程序了。一个简单的JavaBeanFirstJavaBean.javaimportjava.io.*;public class FirstJavaBean {private String FirstProperty = new String("");public FirstJavaBean() {}public String getFirstProperty() {return FirstProperty;}public void setFirstProperty(String value) {FirstProperty = value;}public static void main(String[] args){System.out.println("My First JavaBean!");}}如果运行这个程序,就会出现下面的结果:My First JavaBean!这是一个很典型的JavaBean的代表,简单地解释一下,FirstProperty是其中的一个属性(Property),外部通过get/set方法可以对这个属性进行操作,如果您写过VB的class的话,对这个就再也熟悉不过了。Main方法是为了测试程序用的,写JavaBean可以先不必加入到Jsp程序中调用,而直接用main方法来进行调试,调试好以后就可以在Jsp程序中调用了。
收起全文
精华内容
参与话题
  • 什么是Bean

    万次阅读 多人点赞 2018-07-21 21:29:15
    Bean在Spring和SpringMVC中无所不在,将这个概念内化很重要,下面分享一下我的想法:   一、Bean是啥 1、Java面向对象,对象有方法和属性,那么就需要对象实例来调用方法和属性(即实例化);   2、凡是有...

    Bean在Spring和SpringMVC中无所不在,将这个概念内化很重要,下面分享一下我的想法:

     

    一、Bean是啥

    1、Java面向对象,对象有方法和属性,那么就需要对象实例来调用方法和属性(即实例化);

     

    2、凡是有方法或属性的类都需要实例化,这样才能具象化去使用这些方法和属性;

     

    3、规律:凡是子类及带有方法或属性的类都要加上注册Bean到Spring IoC的注解;(@Component , @Repository , @ Controller , @Service , @Configration

     

    4、把Bean理解为类的代理或代言人(实际上确实是通过反射、代理来实现的),这样它就能代表类拥有该拥有的东西了

     

    5、我们都在微博上@过某某,对方会优先看到这条信息,并给你反馈,那么在Spring中,你标识一个@符号,那么Spring就会来看看,并且从这里拿到一个Bean(注册)或者给出一个Bean(使用)

    二、注解分为两类:

    1、一类是使用Bean,即是把已经在xml文件中配置好的Bean拿来用,完成属性、方法的组装;比如@Autowired , @Resource,可以通过byTYPE(@Autowired)、byNAME(@Resource)的方式获取Bean;

     

    2、一类是注册Bean,@Component , @Repository , @ Controller , @Service , @Configration这些注解都是把你要实例化的对象转化成一个Bean,放在IoC容器中,等你要用的时候,它会和上面的@Autowired , @Resource配合到一起,把对象、属性、方法完美组装。

     

    三、@Bean是啥?

     

    1、原理是什么?先看下源码中的部分内容:

     

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    Indicates that a method produces a bean to be managed by the Spring container.

     

     <h3>Overview</h3>

     

     <p>The names and semantics of the attributes to this annotation are intentionally

     similar to those of the {@code <bean/>} element in the Spring XML schema. For

     example:

     

     <pre class="code">

         @Bean

         public MyBean myBean() {

             // instantiate and configure MyBean obj

             return obj;

        }</pre>

      意思是@Bean明确地指示了一种方法,什么方法呢——产生一个bean的方法,并且交给Spring容器管理;从这我们就明白了为啥@Bean是放在方法的注释上了,因为它很明确地告诉被注释的方法,你给我产生一个Bean,然后交给Spring容器,剩下的你就别管了。

     2、记住,@Bean就放在方法上,就是产生一个Bean,那你是不是又糊涂了,因为已经在你定义的类上加了@Configration等注册Bean的注解了,为啥还要用@Bean呢?这个我也不知道,下面我给个例子,一起探讨一下吧:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    3

    package com.edu.fruit;

      //定义一个接口

        public interface Fruit<T>{

            //没有方法

    }

     

    /*

    *定义两个子类

    */

    package com.edu.fruit;

         @Configuration

         public class Apple implements Fruit<Integer>{//将Apple类约束为Integer类型

     

    }

     

    package com.edu.fruit;

         @Configuration

         public class GinSeng implements Fruit<String>{//将GinSeng 类约束为String类型

     

    }

    /*

    *业务逻辑类

    */

    package com.edu.service;

           @Configuration

           public class FruitService {

              @Autowired

              private Apple apple;

              @Autowired

              private GinSeng ginseng;

        //定义一个产生Bean的方法

           @Bean(name="getApple")

           public Fruit<?> getApple(){

           System.out.println(apple.getClass().getName().hashCode);

             System.out.println(ginseng.getClass().getName().hashCode);

           return new Apple();

    }

    }

    /*

    *测试类

    */

    @RunWith(BlockJUnit4ClassRunner.class)

    public class Config {

        public Config(){

            super("classpath:spring-fruit.xml");

        }

        @Test

        public void test(){

            super.getBean("getApple");//这个Bean从哪来,从上面的@Bean下面的方法中来,返回

                                                              的是一个Apple类实例对象

             

        }

    }

    从上面的例子也印证了我上面的总结的内容:

    1、凡是子类及带属性、方法的类都注册Bean到Spring中,交给它管理;

    2、@Bean 用在方法上,告诉Spring容器,你可以从下面这个方法中拿到一个Bean

    展开全文
  • Java Bean详解

    万次阅读 多人点赞 2020-04-01 08:39:30
    JavaBean 是一种JAVA语言写成的可重用组件。为写成JavaBean,类必须是具体的和公共的,并且具有无参数的构造器。JavaBean 通过提供符合一致性设计模式的公共方法将内部域暴露成员属性,set和get方法获取。...

           JavaBean 是一种JAVA语言写成的可重用组件。为写成JavaBean,类必须是具体的和公共的,并且具有无参数的构造器。JavaBean 通过提供符合一致性设计模式的公共方法将内部域暴露成员属性,set和get方法获取。众所周知,属性名称符合这种模式,其他Java 类可以通过自省机制(反射机制)发现和操作这些JavaBean 的属性。

    功能特点

           用户可以使用JavaBean将功能、处理、值、数据库访问和其他任何可以用java代码创造的对象进行打包,并且其他的开发者可以通过内部的JSP页面、Servlet、其他JavaBean、applet程序或者应用来使用这些对象。用户可以认为JavaBean提供了一种随时随地的复制和粘贴的功能,而不用关心任何改变

           JavaBean可分为两种:一种是有用户界面(UI,User Interface)的JavaBean;还有一种是没有用户界面,主要负责处理事务(如数据运算,操纵数据库)的JavaBean。JSP通常访问的是后一种JavaBean。

           JavaBean是可复用的平台独立的软件组件,开发者可以在软件构造器工具中对其直接进行可视化操作。

           软件构造器工具可以是Web页面构造器、可视化应用程序构造器、GUI设计构造器或服务器应用程序构造器。有时,构造器工具也可以是一个包含了一些bean的复合文档的文档编辑器。

           JavaBean可以是简单的GUI要素,如按钮或滚动条;也可以是复杂的可视化软件组件,如数据库视图,有些JavaBean是没有GUI表现形式的,但这些JavaBean仍然可以使用应用程序构造器可视化地进行组合。

           一个JavaBean和一个JavaApplet相似,是一个非常简单的遵循某种严格协议的Java类。每个JavaBean的功能都可能不一样,但它们都必须支持以下特征。

           一个bean没有必须继承的特定的基类或接口。可视化的bean必须继承的类是java.awt.Component,这样它们才能添加到可视化容器中去,非可视化bean则不需要继承这个类。有许多bean,无论是在应用程序构造器工具中,还是在最后创建好的应用程序中,都具有很强的可视化特征,但这并非每个bean必须的特征。

           在使用Java编程时,并不是所有软件模块都需要转换成bean。Bean比较适合于那些具有可视化操作和定制特性的软件组件

           从基本上说,JavaBean可以看成是一个黑盒子,即只需要知道其功能而不必管其内部结构的软件设备。黑盒子只介绍和定义其外部特征和与其他部分的接口,如按钮、窗口、颜色、形状、句柄等。

           通过将系统看成使用黑盒子关联起来的通讯网络,我们可以忽略黑盒子内部的系统细节,从而有效地控制系统的整体性能。

    作为一个黑盒子的模型,JavaBean有3个接口面,可以独立进行开发。

    1. JavaBean可以调用的方法

    2. JavaBean提供的可读写的属性

    3. JavaBean向外部发送的或从外部接收的事件

    组成

    一个JavaBean由3部分组成:
      
      (1) 属性(properties)
      JavaBean提供了高层次的属性概念,属性在JavaBean中不只是传统的面向对象的概念里的属性,它同时还得到了属性读取和属性写入的API的支持。属性值可以通过调用适当的bean方法进行。比如,可能bean有一个名字属性,这个属性的值可能需要调用String getName()方法读取,而写入属性值可能要需要调用void setName(String str)的方法。
      每个JavaBean属性通常都应该遵循简单的方法命名规则,这样应用程序构造器工具和最终用户才能找到JavaBean提供的属性,然后查询或修改属性值,对bean进行操作。JavaBean还可以对属性值的改变作出及时的反应。比如一个显示当前时间的JavaBean,如果改变时钟的时区属性,则时钟会立即重画,显示当前指定时区的时间。
      (2) 方法(method)
      JavaBean中的方法就是通常的Java方法,它可以从其他组件或在脚本环境中调用。默认情况下,所有bean的公有方法都可以被外部调用,但bean一般只会引出其公有方法的一个子集。
      由于JavaBean本身是Java对象,调用这个对象的方法是与其交互作用的唯一途径。JavaBean严格遵守面向对象的类设计逻辑,不让外部世界访问其任何字段(没有public字段)。这样,方法调用是接触Bean的唯一途径。
      但是和普通类不同的是,对有些Bean来说,采用调用实例方法的低级机制并不是操作和使用Bean的主要途径。公开Bean方法在Bean操作中降为辅助地位,因为两个高级Bean特性--属性和事件是与Bean交互作用的更好方式。
      因此Bean可以提供要让客户使用的public方法,但应当认识到,Bean设计人员希望看到绝大部分Bean的功能反映在属性和事件中,而不是在人工调用和各个方法中。
      (3) 事件(event)
      Bean与其他软件组件交流信息的主要方式是发送和接受事件。我们可以将bean的事件支持功能看作是集成电路中的输入输出引脚:工程师将引脚连接在一起组成系统,让组件进行通讯。有些引脚用于输入,有些引脚用于输出,相当于事件模型中的发送事件和接收事件。
      事件为JavaBean组件提供了一种发送通知给其他组件的方法。在AWT事件模型中,一个事件源可以注册事件监听器对象。当事件源检测到发生了某种事件时,它将调用事件监听器对象中的一个适当的事件处理方法来处理这个事件。
      由此可见,JavaBean确实也是普通的Java对象,只不过它遵循了一些特别的约定而已。

    范围

           JavaBean 的范围 Scope 是一个具有生命时间的变量。JavaBean的范围在<jsp:useBean scope=”….>标志中右边进行表示。将产生一个JavaBean的快捷参考。

    说明:jsp服务器引擎将剥离<jsp。。。。标记。并且在最终用户的浏览器上无法显示实际代码。

    存在下面四种范围: 页面page、 请求request、 对话session、 应用application。

    对话范围

    对话范围的JavaBean 主要应用于跨多个页面和时间段: 例如填充 用户信息。 添加信息并且接受回馈,保存用户最.近执行页面的轨迹。对话范围JavaBean保留一些和用户对话 ID 相关的信息。这些信息来自临时的对话cookie,并在当用户关闭浏览器时,这个cookie将从客户端和服务器删除。

    请求范围

    页面和请求范围的JavaBean有时类似表单的bean , 这是因为 他们大都用于处理表单。表单需要很长的时间来处理用户的输入,通常情况下用于页面接受HTTP/POST或者GET请求。另外页面和请求范围的bean可以用于减少大型站点服务器上的负载,如果使用对话bean,耽搁的处理就可能会消耗掉很多资源。

    应用范围

    应用范围通常应用于服务器的部件,例如 JDBC连接池、应用监视、用户计数和其他参与用户行为的类。

    在Bean中限制HTML的产生:

    理论上,JavaBean 将不会产生任何HTML,因为这是jsp层负责的工作;然而,为动态消息提供一些预先准备的格式是非常有用的。产生的HTML将被标注的 JavaBean方法返回。

    这里有一些非常重要的事情:

    1. 不要试图在JavaBean返回的HTML中放置任何字体尺寸。

    并不是所有的浏览器都相同。很多浏览器无法处理完整的字体尺寸。

    2. 不要试图在JavaBean返回的HTML中放置任何脚本或者DHTML。

    向页面直接输出脚本或者DHTML相当于自我毁灭,因为某些浏览器版本在处理不正确的脚本时会崩溃(非常少但是有)。如果用户的JavaBean在运行时是动态的推出复杂的HTML语言,用户将陷入调试的噩梦。另外,复杂的HTML将限制JavaBean的寿命和灵活性。

    3. 不要提供任何的选择。

    如果用户使用不同的系统浏览页面,可以提供一种可以替换的方法。

    按着Sun公司的定义,JavaBean是一个可重复使用的软件组件。实际上JavaBean是一种Java类,通过封装属性和方法成为具有某种功能或者处理某个业务的对象,简称bean。由于javabean是基于java语言的,因此javabean不依赖平台,具有以下特点:

    1. 可以实现代码的重复利用

    2. 易编写、易维护、易使用

    3. 可以在任何安装了Java运行环境的平台上的使用,而不需要重新编译。

    编写javabean就是编写一个java的类,所以你只要会写类就能编写一个bean,这个类创建的一个对象称做一个bean。为了能让使用这个bean的应用程序构建工具(比如JSP引擎)知道这个bean的属性和方法,只需在类的方法命名上遵守以下规则:

    1. 如果类的成员变量的名字是xxx,那么为了更改或获取成员变量的值,即更改或获取属性,在类中可以使用两个方法:

    getXxx(),用来获取属性xxx。

    setXxx(),用来修改属性xxx.。

    2. 对于boolean类型的成员变量,即布尔逻辑类型的属性,允许使用"is"代替上面的"get"。

    3. 类中访问属性的方法都必须是public的,一般属性是private的。

    4. 类中如果有构造方法,那么这个构造方法也是public的并且是无参数的。

    任务

           JavaBean的任务就是: “Write once, run anywhere, reuse everywhere”,即“一次性编写,任何地方执行,任何地方重用”。这个任何实际上就是要解决困扰软件工业的日益增加的复杂性,提供一个简单的、紧凑的和优秀的问题解决方案。

    1. 一个开发良好的软件组件应该是一次性地编写,而不需要再重新编写代码以增强或完善功能。因此,JavaBean应该提供一个实际的方法来增强现有代码的利用率,而不再需要在原有代码上重新进行编程。除了在节约开发资源方面的意义外,一次性地编写JavaBean组件也可以在版本控制方面起到非常好的作用。开发者可以不断地对组件进行改进,而不必从头开始编写代码。这样就可以在原有基础上不断提高组件功能,而不会犯相同的错误。

    2. JavaBean组件在任意地方运行是指组件可以在任何环境和平台上使用,这可以满足各种交互式平台的需求。由于JavaBean是基于Java的,所以它可以很容易地得到交互式平台的支持。JavaBean组件在任意地方执行不仅是指组件可以在不同的操作平台上运行,还包括在分布式网络环境中运行。

    3.JavaBean组件在任意地方的重用说的是它能够在包括应用程序、其他组件、文档、Web站点和应用程序构造器工具的多种方案中再利用。这也许是JavaBean组件的最为重要的任务了,因为它正是JavaBean组件区别于Java程序的特点之一。Java程序的任务就是JavaBean组件所具有的前两个任务,而这第3个任务却是JavaBean组件独有的。

    设计目标

    JavaBean的一些具体的主要设计目标:

    1.紧凑而方便的创建和使用

    JavaBean紧凑性的需求是基于JavaBean组件常常用于分布式计算环境中,这使得JavaBean组件常常需要在有限的带宽连接环境下进行传输。显然,为了适应传送的效率和速度,JavaBean组件必须是越紧凑越好。另外,为了更好地创建和使用组件,就应该使其越简单越好。通常为了提高组件的简易性和紧凑性,设计过程需要投入相对较大的功夫。

    现已有的组件软件技术通常是使用复杂的API,这常常搞得开发者在创建组件时晕头转向。因此,JavaBean组件必须不仅容易使用,而且必须便于开发。这对于组件开发者而言是至关重要的,因为这可以使得开发者不必花大量功夫在使用API进行程序设计上,从而更好地对组件进行润饰,提高组件的可观赏性。

    JavaBean组件大部分是基于已有的传统Java编程的类结构上的,这对于那些已经可以熟练地使用Java语言的开发者非常有利。而且这可以使得JavaBean组件更加紧凑,因为Java语言在编程上吸收了以前的编程语言中的大量优点,已经使开发出来的程序变得相当有效率。

    2.完全的可移植性

    JavaBean API与操作基础的独立于平台的Java系统相结合,提供了独立于平台的组件解决方案。因此,组件开发者就可以不必再为带有Java applet平台特有的类库而担心了。最终的结果都将是计算机界共享可重复使用的组件,并在任何支持Java的系统中无需修改地执行。

    3.继承Java的强大功能

    现有的Java结构已经提供了多种易于应用于组件的功能。其中一个比较重要的是Java本身的内置类发现功能,它可以使得对象在运行时彼此动态地交互作用,这样对象就可以从开发系统或其开发历史中独立出来。

    对于JavaBean而言,由于它是基于Java语言的,所以它就自然地继承了这个对于组件技术而言非常重要的功能,而不再需要任何额外开销来支持它。

    JavaBean继承在现有Java功能中还有一个重要的方面,就是持久性,它保存对象并获得对象的内部状态。通过Java提供的序列化(serialization)机制,持久性可以由JavaBean自动进行处理。当然,在需要的时候,开发者也可以自己建立定制的持久性方案。

    4.应用程序构造器支持

    JavaBean的另一个设计目标是设计环境的问题和开发者如何使用JavaBean创建应用程序。JavaBean体系结构支持指定设计环境属性和编辑机制以便于JavaBean组件的可视化编辑。这样开发者可以使用可视化应用程序构造器无缝地组装和修改JavaBean组件。就像Windows平台上的可视化开发工具VBX或OCX控件处理组件一样。通过这种方法,组件开发者可以指定在开发环境中使用和操作组件的方法。

    5.分布式计算支持

    支持分布式计算虽然不是JavaBean体系结构中的核心元素,但也是JavaBean中的一个主要问题。

    JavaBean使得开发者可以在任何时候使用分布式计算机制,但不使用分布式计算的核心支持来给自己增加额外负担。这正是出于JavaBean组件的紧凑性考虑的,无疑分布式计算需要大量的额外开销。

    需求

    JavaBean是java类,属于某些特定的译码指导方针,并且扩展了适应性和范围,允许用户访问内部的属性和方法。通过这些,JavaBean类可以用于下列方法:

    1. 在IDE中,JavaBean的功能允许应用开发者浏览其中的方法,即JavaBean是被编译的,并且无法利用原始的源文件。

    2. 在 Remote Method Invocation(RMI) 的分布式风格中,这项功能听起来并不让人兴奋,但是在未来的包含企业版的JavaBean后,将改变这种情况。

    3. 为了JavaBean的属性值和状态可以保存到磁盘上。

    界限

           虽然JavaBean和Java之间已经有了明确的界限,但在某些方面JavaBean和Java之间仍然存在着非常明显的混淆。Java确实是能够为用户创建可重用的对象,但它却没有管理这些对象相互作用的规则或标准。JavaBean通过指定定义对象之间交互作用的机制,以及大部分对象需要支持的常用行为,如持久性和实际处理等,建立了自己需要的组件模型

           虽然当前的Java组件模型也可以运行得很好,但在传送真正的可重用性和交互操作性上仍然非常有限,Java用户需要做的最多的一件事就是创建applet并使得它们在Web 页面上相互通讯,这并非易事。JavaBean提供了一个框架包,使用这个包进行通讯就容易得多了。

           JavaBean组件能够通过定义好的标准属性改进性能。总体而言,JavaBean充分发展了Java applet的功能,并结合了JavaAWT组件的紧凑性和可重用性。

    三大构件

    Java bean:编程语言java中的术语,行业内通常称为java豆,带点美哩口味,飘零着咖啡的味道,在计算机编程中代表java构件(EJB的构件),通常有Session bean,Entity bean,MessageDriven Bean三大类。

    Session bean:会话构件,是短暂的对象,运行在服务器上,并执行一些应用逻辑处理,它由客户端应用程序建立,其数据需要自己来管理。分为无状态和有状态两种。

    Entity bean:实体构件,是持久对象,可以被其他对象调用。在建立时指定一个唯一标示的标识,并允许客户程序,根据实体bean标识来定位beans实例。多个实体可以并发访问实体bean,事务间的协调由容器来完成。

    MessageDriven Bean:消息构件,是专门用来处理JMS(Java Message System)消息的规范(EIB2.0)。JMS是一种与厂商无关的API,用来访问消息收发系统,并提供了与厂商无关的访问方法,以此来访问消息收发服务。JMS客户机可以用来发送消息而不必等待回应。

    发展

    最初,JavaBean的目的是为了将可以重复使用的软件代码打包标准。特别是用于帮助厂家开发在综合开发环境(IDE)下使用的java软件部件。这些包括如Grid控件,用户可以将该部件拖放到开发环境中。从此,JavaBean就可以扩展为一个java web 应用的标准部件,并且JavaBean部件框架已经扩展为企业版的 Bean(EJB)。

    开发环境

    普通JavaBean组件是要分布在各自环境中,所以它们应该能够适应各种环境。虽然我们无法事先预知JavaBean要运行的确切环境,但以下两点是可以确定的:

    1. bean必须能够在一个应用程序构造器工具中运行。

    2. bean必须可以在产生的应用程序的运行环境中使用。

    设计环境

    第一点说明的是bean必须可以在设计环境(design environment)中运行。在设计环境中,bean应该提供设计信息给应用程序构造器工具并允许终端用户制定bean的外观和行为。

    在传统的软件构造活动中,必须通过编译、链接之后才能看到应用程序的最终运行结果;而利用JavaBean设计的软件中,则没有这种明确的界限。使用JavaBean,就可以非常直观地设计应用程序软件,在设计过程中赋予软件主机。而且,这个过程更加容易重复开发,设计思想更加容易变成原型。

    运行环境

    第二点说明的是bean必须可以在运行环境(run-time environment)中使用。在这个环境中,对设计信息和定制的需求并不重要。一个组件的设计环境信息和设计环境中编写的代码通常可能是非常巨大的。

    因此,我们可能需要在bean的设计环境方面和运行环境方面作一个明确的区分,这样,就可能需要在运行环境中不使用bean的任何设计环境代码来配置这个bean。所以,JavaBean就必须分别支持运行环境接口的类库和设计环境接口的类库。

    编程入门

    一般要求

    首先,您必须有一个不带有参数的公用构造器此构造器也应该通过调用各个特性的设置方法来设置特性的默认,例如:

    public Fireworks()
    
    {
    
    setAutoStart(true);
    
    setBackground(Color.black);
    
    setSpeed(10);
    
    setRadius(40);
    
    }

    如果 bean 是一个从 java.awt.Component 类继承而来的可视 bean,您就应该为 bean 定义一个默认的首选大小,例如:

    public Dimension getPreferredSize()
    
    {
    
    return (new Dimension(radius*3, radius*3));
    
    }
    
    public Dimension getMinimumSize()
    
    {
    
    return getPreferredSize();
    
    }

    特性

    对于您需要的每个特性,您应该有一个带有匹配公用 getter 和 setter 方法的专用实例变量,例如:

    private int speed;
    
    public int getSpeed()
    
    {
    
    return speed;
    
    }
    
    public void setSpeed(int s)
    
    {
    
    speed = s;
    
    }

    此 get 和 set 方法必须有与实例变量相同的名称,但是第一个字母要大写并以 get 和 set 开头。

    由于连接而在任何时候更改它们的特性时,确认 Bean 在运行时行为正确也是很重要的。如果特性的更改影响到 Bean 的可视外观,您应该以此特性设置的方法来调用

    repaint();。

    同样,如果特性的更改影响到 bean 的大小和位置,您需要确认获得验证的事物。我们建议编写您自己的 validateAll 方法,如下所示:

    private void validateAll()
    
    {
    
    if (isValid())
    
    {
    
    Component self = this;
    
    self.invalidate();
    
    Component myParent = self.getParent();
    
    if (myParent != null)
    
    {
    
    myParent.invalidate();
    
    self = myParent;
    
    }
    
    self.validate();
    
    }
    
    }

    然后以此特性设置的方法调用

    validateAll();。

    bean 类将无法进行关于调用特性设置方法命令的假设。您应该写 bean 以便可以初始构造它,然后在不引起错误的同时在任何命令中设置其特性。

    操作

    对于每个您需要的操作,您应该有一个公用方法,例如:

    public void start()
    
    {
    
    if(thread==null)
    
    {
    
    thread=new Thread(this);
    
    thread.start();
    
    }
    
    }

    您为操作写的方法应该在无须期待用户创建连接或设置很多特性的情况下独立操作。 例如,如果您写了一个音频 Bean,您希望通过播放操作处理打开声音的所有步骤、完成您需要的所有设置并播放声音。同样,即使声音未播放,停止操作也应起作用。

    事件

    对于您需要的每个事件或事件设置,您应该定义事件和侦听器类。对于此例,查看 FireworksEvent.java 源文件以及 Fireworks.java 文件。此事件类的源应该如同这样:

    import java.awt.*;
    
    import java.util.*;
    
    publicclassFireworksEvent extends EventObject
    
    {
    public static final int EXPLODED = 1;
    int id = 0;
    
    public FireworksEvent(Component source, int id)
    
    {
    super(source);
    id = id;
    }
    
    public int getID()
    
    {
    return id;
    }
    
    }

    您应该为此事件设置中的每个事件定义一个公用静态结束事件标识符,例如在此例子中的 EXPLODED。

    对于侦听器类的源,查看 FireworksListener.java源文件

    import java.util.*;
    
    public interface FireworksListener extends EventListener
    
    {
    
    public abstract void exploded(FireworksEvent e);
    
    }

    您应该为此事件设置中的每个事件定义一个公用抽象方法,例如在此例子中的 exploded。 而且,侦听器类必须扩展 EventListener ,以使 JAR 向导能够找到它。

    然后,如果由 bean 类播送事件,它必须跟踪侦听事件的对象。要这样做,您需要定义侦听器实例变量以及 addListener 和 removeListener 方法。返回 Fireworks.java 源,例如,您将查看到:

    private Vector listeners = new Vector();
    
    public void addFireworksListener(FireworksListener f)
    
    {
    
    listeners.addElement(f);
    
    }
    
    public void removeFireworksListener(FireworksListener f)
    
    {
    
    listeners.removeElement(f);
    
    }

    最后,bean 类需要以正确的次数将事件实际播送到所有的侦听器。要这样做,您需要定义 processEvent 方法并以适当的次数调用它,例如:

    public void processFireworksEvent(FireworksEvent e)
    
    {
    
    for (Enumeration enum = listeners.elements(); enum.hasMoreElements(); )
    
    ((FireworksListener)enum.nextElement()).exploded(e);
    
    }
    
    public void run()
    
    {
    
    processFireworksEvent(new FireworksEvent(this, FireworksEvent.EXPLODED));
    
    }

    注意事项

    实际应用中,在表现对象或者处理前扩展JavaBean的设计非常有用。通常认为如果提供信息,web开发者将在功能上满足用户对JavaBean的需求。例如: HTML中显示敏感的数据时,用户可以屏蔽的条目,如密码、电话号码等。

    良好规划设计的JavaBean是值得信赖的。

    Java 中的 null 不同于SQL中的 null

    看这样一道测试程序

    public class NullTest
    
    {
    
    public static void main(String[] args)
    
    {
    
    int I = 0;
    
    // int I = null;// not a valid initialization;
    
    String str = null;
    
    String strZeroOutValue = "";
    
    StringBuffer sb = new StringBuffer("Null test: String initialized as null =");
    
    sb.append(str);
    
    sb.append(" String representing a Zero Out Value:")
    
    sb.append(strZeroOutValue);
    
    System.out.println(sb.toString());
    
    }
    
    }

    这个程序将产生下面的结果:

    Null test: String initialized as null = null

    n String representing a Zero Out Value:

    在JavaBean中, 我们将 I变量声明为一个 int, 我们必须处理与该变量相关的值,因为I 默认的没有值,int类型无法初始化为 null, 如果int 值没有进行明确的初始化,编译器将提示错误。

    执行 NullTest程序,将验证在文本中空字符串是空值的替代,用于显示 SQL 的插入和更新。如果我们需要删除一些信息,通过删除表单区域的文本,需要将数据库发送长度为0的字符串。

    尽管大多数数据库将空字符串作为空值进行操作,如果我们使用的数据库不支持处理空字符串的话,我们必须写入附加的java代码,来创建自己的SQL插入声明。

    例如:

    if(test.length==0)
    
    {
    
    sb.append("null");
    
    }
    
    else
    
    {
    
    sb.append(test);
    
    }

    区别EJB

    JavaBean 和 Server Bean(通常称为Enterprise JavaBean(EJB))有一些基本相同之处。它们都是用一组特性创建,以执行其特定任务的对象,获得其它特性的能力。这使得 bean 的行为根据特定任务和所在环境的不同而有所不同。

    Enterprise Bean 与 JavaBean 不同。JavaBean 是使用java.beans包开发的,它是 Java 2 标准版的一部分。JavaBean 是一台机器上同一个地址空间中运行的组件。JavaBean 是进程内组件Enterprise Bean 是使用 javax.ejb 包开发的,它是标准JDK的扩展,是 Java 2 Enterprise Edition 的一部分。Enterprise Bean 是在多台机器上跨几个地址空间运行的组件。因此 Enterprise Bean 是进程间组件。JavaBean 通常用作 GUI 窗口小部件,而 Enterprise Bean 则用作分布式商业对象。

    一个可以让你快速了解JavaBean的例子

    Javabean就是Java类。从表示层的处理来考虑,Javabean就是一个个的service类。
    现在就用一个实际的例子来说明javabean是怎样工作的,建立一个用户注册登陆小模块
    --------------------------------------------------------------------------------------
    /*1,建立一个javabean封装用户的信息(姓名和密码)UserInfo.java,其中的方法有
    setter方法来设置用户的信息,getter方法来获取用户的信息*/
    
    package user;//存放UserInfo.java的包,该包中放在web-inf目录下
    public class UserInfo
    {
    private String password;
    private String name;
    
    //获取信息
    public String getPassword()
    {
    return this.password;
    }
    public String getName()
    {
    return this.name;
    }
    //设置信息
    public void setPassword(String p)
    {
    this.password=p;
    }
    public void setName(String n)
    {
    this.name=name;
    }
    }
    
    --------------------------------------------------------------------------------------------------
    /*2,现在做的事就是建立一个javabean处理数据库操作以及一些简单的逻辑操作UserRegist.java*/
    
    package user;//同理也放在这个包中
    import java.sql.*;
    
    public class UserRegist
    {
    private UserInfo userInfo;//在此javabean中把UserInfo.java这个javabean引进来
    private Connection conn=null;
    
    //连接数据库
    public UserRegist()
    {
    try
    {
    Class.forName("com.mysql.jdbc.Driver");
    conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/joke?user=root");
    }
    catch(Exception e)
    {
    e.printStackTrace();
    }
    }
    
    public void setUserInfo(UserInfo userInfo)
    {
    this.userInfo=userInfo;
    }
    
    
    //进行注册
    public void regist()throws Exception
    {
    String reg="insert into user_Info values(?,?)";
    try
    {
    PreparedStatement pstmt=conn.prepareStatement(reg);
    //create a preparestatement sentence ,then to set their name
    pstmt.setString(1,userInfo.getPassword());
    pstmt.setString(2,userInfo.getName());
    //excute update
    pstmt.executeUpdate();
    }
    catch(Exception e)
    {
    e.printStackTrace();
    throw e;
    }
    }
    }
    
    -----------------------------------------------------------------------------------------------------------------
    /*3,好了,我们的要用到的javbean就建立完了,现在就是做一个简单的表单html页面了,login.html,接受用户输入的信息*/
    
    <form  action="regist.jsp" name="form1">
    
    <table>
    
    <tr>
    
    <td> username:</td>
    
    <td><input name="name"></input></td>
    
    </tr>
    
    <tr>
    
    <td>userpassword:</td>
    
    <td><input  type="password" name="password"></input></td>
    
    </tr>
    
    <tr>
    
    <td><input type="submit" value="go"></td>
    
    <td><input type="reset" value="reset"></td>
    
    <table>
    
    </form>
    
    ----------------------------------------------------
    
    /*4,最后我们做的事就是用一个简单的jsp页面让两个javabean工作起来,regist.jsp*/
    
    
    
    <%@page contentType="text/html;charset=GB2312"%>
    
    //利用此标签来调用UserInfo.java
    
    <jsp:useBean id="userInfo" class="user.UserInfo" scope="page">
    
    //利用此标签来用UserInfo.java接受并保存表单中的信息
    
    <jsp:setProperty name="userInfo" property="*"/>
    
    </jsp:useBean>
    
    //来调用UserRegist.java
    
    <jsp:useBean id="regist" class="user.UserRegist" scope="page"/>
    
    
    
    <%
    
    regist.setUserInfo(userInfo);//调用UserRegist.java中的setUserInfo()方法获取保存在serInfo.java中的信息
    
    regist.regist( );//调用UserRegist.java中的regist( )方法进行注册
    
    out.println("registed ok!");
    
    %>
    
    <br><hr><br>
    
    <a href="login.jsp">back</a>

     

    展开全文
  • Spring中的bean的理解

    万次阅读 2019-03-12 12:45:43
    首先看一下spring中创建bean的方式 1. 使用构造器创建Bean实例 使用构造器来创建Bean实例是最常见的情况,如果不采用构造注入,Spring底层会调用Bean类的无参构造器来创建实例,因此要求该Bean提供无参的构造器。...

    首先看一下spring中创建bean的方式
    1. 使用构造器创建Bean实例
    使用构造器来创建Bean实例是最常见的情况,如果不采用构造注入,Spring底层会调用Bean类的无参构造器来创建实例,因此要求该Bean提供无参的构造器。在这种情况下,class元素是必须的,class属性的值就是Bean实例的实现类。Spring对Bean实例的所有属性执行默认初始化,即所有基本类型为0或false,引用类型为null。
    接下来,BeanFactory会根据配置文件决定依赖关系,先实例化被依赖的Bean实例然后为注入依赖关系,最后将一个完整的Bean实例返回给程序。
    如果采用构造注入,则要求配置文件为bean元素添加constructor-arg子元素,每个constructor-arg子元素配置一个构造器参数,Spring容器使用带对应参数的构造器来创建Bean实例。Spring调用构造器传入的参数即可用于初始化Bean的实例变量,最后也将一个完成的Bean实例返回给程序。
    2. 使用静态工厂方法创建Bean
    使用静态工厂方法创建Bean实例时,class属性也必须指定,但此时class属性并不是指定Bean实例的实现类,而是静态工厂类。除此之外,还需要使用factory-method属性来指定静态工厂方法,Spring将调用静态工厂方法返回一个Bean实例,得到Bean实例后,Spring后面的处理步骤与采用普通方法创建Bean完全一样。
    下面示例一个Bean通过静态工厂来创建,所以这个bean元素的class属性就是指定的静态工厂类,factory-method指定工厂的静态方法。如果factory-method需要参数,则需要使用constructor-arg元素传入。

    //定义一个宠物接口类
    
    public interface Pet {
    	public void testPet();
    }
    
    //定义两个宠物实现类
    
    public class Dog implements Pet {
    	private String name;
    	public void setName(String name){
    		this.name = name;
    	}
    	@Override
    	public void testPet() {
    		System.out.println(name+":狗喜欢吃骨头!");
    	}
    }
    
    
    public class Cat implements Pet {
    	private String name;
    	public void setName(String name){
    		this.name = name;
    	}
    	@Override
    	public void testPet() {
    		System.out.println(name+":猫喜欢吃鱼!");
    	}
    }
    
    //定义一个静态工厂类
    
    public class PetFactory {
    	public static Pet getPet(String arg){
    		if("dog".equals(arg)){
    			return new Dog();
    		}else{
    			return new Cat();
    		}
    	}
    
    //测试方法
    public static void main(String[] args) throws Exception {
    		ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
    		Pet p1 = ctx.getBean("dog", Pet.class);
    		p1.testPet();
    		Pet p2 = ctx.getBean("cat", Pet.class);
    		p2.testPet();
    	}
    

    接下来看重点配置文件写法,beans.xml:
    之前提到:这个bean元素的class属性就是指定的静态工厂类,factory-method指定工厂的静态方法。如果factory-method需要参数,则需要使用constructor-arg元素传入。

    <bean id = "dog" class = "com.my.factory.PetFactory" factory-method="getPet">
    <constructor-arg value="dog" />
    <property name="name" value = "大黑" />
    </bean>
    <bean id = "cat" class = "com.my.factory.PetFactory" factory-method="getPet">
    <constructor-arg value="cat" />
    <property name="name" value = "小花" />
    </bean>
    

    3. 调用实例工厂方法创建Bean
    实例工厂方法与静态工厂方法只有一点不同:调用静态工厂方法只需要工厂类即可,而调用实例工厂方法则需要工厂实例。所以配置实例工厂方法与配置静态工厂方法基本相似,只有一点区别:配置静态工厂方法使用class指定静态工厂类,而配置实例工厂方法则使用factory-bean指定工厂实例。
    采用实例工厂方法创建Bean的bean元素时需要指定如下两个属性:
    factory-bean:该属性的值为工厂Bean的id。
    factory-method:该属性指定实例工厂的工厂方法。
    在这里插入图片描述
    上面的PetOneFactory就是一个简单的Pet工厂,getPet方法就是负责生产Pet的工厂方法。单独定义一个bean来生成工厂对象,在下面的bean定义中使用factory-bean属性引用上面的工厂Bean。其他跟静态工厂方式创建Bean完全一致。
    接下来 深入看一下 容器中的Bean
    深入理解容器中的Bean

    1. 抽象Bean与子Bean
      在实际开发中,有可能会出现这样的情况:随着项目越来越大,Spring配置文件出现了多个bean,配置具有大致相同的配置信息,只有少量信息不同,这将导致配置文件出现很多重复的内容。如果保留这些配置,则可能导致的问题是:
      配置文件臃肿。
      后期难以修改、维护。
      为了解决上面问题,可以考虑把多个bean配置中相同的信息提取出来,集中成配置模板——这个配置模板并不是真正的Bean。因此Spring不应该创建该配置模板,于是需要为该bean配置增加abstract属性值为true表示这是个抽象Bean。
      抽象Bean不能被实例化,Spring容器不会创建抽象Bean实例。抽象Bean的价值在于被继承,抽象Bean通常作为父Bean被继承。抽象Bean只是配置信息的模板,指定abstract为true即可阻止Spring实例化该Bean,因此抽象Bean可以不指定class属性。
      将大部分相同信息配置成抽象Bean之后,将实际的Bean实例配置成该抽象Bean的子Bean即可。子Bean定义可以从父Bean继承实现类、构造参数、属性值能配置信息,除此之外,子Bean配置可以增加新的配置信息,并可以指定新的配置信息覆盖父Bean的定义。
      通过为一个bean元素指定parent属性即可指定该Bean是一个子Bean,parent属性指定该Bean所继承的父Bean的id。子Bean无法从父Bean继承如下属性:depends-on、autowire、singleton、scope、lazy-init,这些属性只能从子Bean定义中获取,或采用默认值。
    <bean id=”steelAxe” class=”com.langsin.impl.SteelAxe” />
    <bean id=”personTemplete” abstract=”true”>
    	<property name=”name” value=”zhangsan” />
    	<property name=”axe” ref=”steelAxe” />
    </bean>
    <bean id=”chinese” class=”com.langsin.impl.Chinese” parent=”personTemplete”/>
    <bean id=”american” class=”com.langsin.impl.American” parent=”personTemplete”/>
    

    在配置文件中chinese和americanBean都指定了parent=“personTemplete”,表明这两个Bean都可以从父Bean那里继承得到配置信息。虽然这两个Bean没有直接指定proerty子元素,但他们会从personTemplete模板那里继承得到两个property子元素。

    那么bean继承和Java继承有什么区别呢?
    Spring中的Bean继承与Java中的继承截然不同,前者是实例与实例之间参数的延续,后者则是一般到特殊的细化。前者是对象与对象之间的关系,后者则是类与类之间的关系。Spring中Bean的继承和Java中Bean的继承有如下区别:
    Spring中的子Bean和父Bean可以是不同类型,但Java中的继承则可保证子类是一种特殊的父类。
    Spring中Bean的继承是实例之间的关系,因此主要表现为参数值的延续;而Java中的继承是类之间的关系,主要表现为方法、属性的延续。
    Spring中的子Bean不可作为父Bean使用,不具备多态性;Java中的子类实例完全可以当成父类实例使用。

    容器中的工厂Bean
    此处的工厂Bean,与前面介绍的实例工厂Bean,或者静态工厂Bean有所区别:前面那些Bean是标准的工厂模式,Spring只是负责调用工厂方法来创建Bean的实例;此处的工厂Bean是Spring的一种特殊Bean,这种工厂Bean必须实现FactoryBean接口。
    FactoryBean接口是工厂Bean的标准接口,把实现FactoryBean接口的工厂Bean部署在容器中后,如果程序通过getBean方法来获取它时,容器返回的不是FactoryBean实现类的实例,而是返回FactoryBean的产品。(即通过工厂所创建的对象被返回)
    FactoryBean接口提供如下三个方法:
    T getObject():负责返回该工厂Bean生成的Java实例。
    Class<?> getObjectType():返回该工厂Bean生成的Java实例的实现类。
    boolean isSingleton():表示该工厂Bean生成的Java实例是否是单例模式。
    配置FactoryBean与配置普通Bean的定义没有区别,但当程序向Spring容器请求获取该Bean时,容器返回该FactoryBean的产品,而不是返回该FactoryBean本身。所以,实现FactoryBean接口的最大作用在于:Spring容器返回的是该Bean实例的getObject()方法的返回值。而getObject()方法由开发者负责实现,所以返回什么类型就由开发者自己决定。

    import org.springframework.beans.factory.FactoryBean;
    public class GetMyObjectFactoryBean implements FactoryBean<Object> {
    	private String targetClass;
    	public void setTargetClass(String targetClass){
    		this.targetClass = targetClass;
    	}
    	@Override
    	public Object getObject() throws Exception {
    		Class<?> clazz = Class.forName(this.targetClass);
    		return clazz.newInstance();
    	}
    	@Override
    	public Class<?> getObjectType() {
    		return Object.class;
    	}
    	@Override
    	public boolean isSingleton() {
    		return false;
    	}
    }
    

    上面的GetMyObjectFactoryBean是一个标准的工厂Bean,从配置文件来看,部署工厂Bean与部署普通Bean其实没有任何区别,同样只需要为该Bean配置id、class属性即可。但Spring对FactoryBean接口的实现类的处理有所不同。Spring容器会自动检测容器中所有的Bean,如果发现某个Bean实现了FactoryBean接口,Spring容器就会在实例化该Bean、根据property执行setter方法之后,额外要调用该Bean的getObject方法,并将返回值作为容器中的Bean。

    测试代码
    public static void main(String[] args) throws Exception {
    		ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
    		System.out.println(ctx.getBean("myframe"));
    		System.out.println(ctx.getBean("&myframe"));
    		//在Bean id前面加&符号,会返回FactoryBean本身
    	}
    

    强制初始化Bean
    在大多数情况下,Bean之间的依赖非常直接,Spring容器返回Bean实例之前,先要完成Bean依赖关系的注入。假如Bean A依赖于Bean B,程序请求Bean A时,Spring容器会自动先自动初始化Bean B,再将Bean B注入Bean A,最后将具备完整依赖的BeanA返回给程序。
    在极端的情况下,Bean之间的依赖关系不够直接。比如某个类的初始化块中使用其他Bean,Spring总是先初始化主调Bean,当执行初始化块时,被依赖的Bean可能还没有实例化,此时将引发异常。
    为了显示指定被依赖Bean在目标Bean之前初始化,可以使用depends-on属性,该属性可以在初始化主调Bean之前,强制初始化一个或多个Bean。配置文件如下:

    <bean id="one" class="com.langsin.factory.One" />
    <bean id="two" class="com.langsin.factory.Two" />
    

    如上述没有设置Bean one与Bean two之间的依赖关系,所以Spring容器根据配置的先后关系先加载one再加载two,One、Two两个类中只有构造器,并且只是做了简单的输出操作,代码如下:

    示例1:
    package com.langsin.factory;
    public class One {
    	public One(){
    		System.out.println("打印One。。。。。。。。");
    	}
    }
    示例2:
    package com.langsin.factory;
    public class Two {
    	public Two(){
    		System.out.println("打印Two。。。。。。。。。。");
    	}
    }
    

    结果为:
    在这里插入图片描述
    在Bean one中加入强制依赖为two,例如加载关系后,则执行效果如下:
    在这里插入图片描述
    容器中的Bean生命周期
    Spring可以管理singleton作用域的Bean的生命周期,Spring可以精确地知道该Bean何时被创建、何时被初始化完成、容器何时准备销毁该Bean实例。
    对于prototype作用域的Bean,Spring容器仅仅负责创建,当容器创建Bean实例之后,Bean实例完全交给客户端代码管理,容器不再跟踪其生命周期。每次客户端请求prototype作用域的Bean时,Spring都会产生一个实例交给客户端程序,就不再过问了。
    对于singleton作用域的Bean,每次客户端代码请求时都返回同一个共享实例,客户端代码不能控制Bean的销毁,Spring容器负责跟踪Bean实例的产生、销毁。Spring容器可以在创建Bean之后,进行某些通用资源申请;还可以在销毁Bean实例之前,先回收某些资源,比如数据库连接。
    对于singleton作用域的Bean,Spring容器知道Bean何时实例化结束、何时销毁,Spring可以管理实例化结束之后和销毁之前的行为,即Bean的存活期间的行为。
    具体的行为请看 https://www.cnblogs.com/zrtqsk/p/3735273.html
    依赖关系注入之后的行为
    Spring提供两种方式在Bean全部属性设置成功后执行特定情况。
    1.使用init-method属性。
    2.实现InitializingBean接口。
    第一种方式,使用init-method属性指定某个方法应在Bean全部依赖关系设置结束后自动执行。使用这种方式不需要将代码与Spring的接口耦合在一起,代码污染小。
    第二种方式,让Bean类实现InitializingBean接口,该接口提供一个方法,afterPropertysSet(),Spring容器会在为该Bean注入依赖关系之后,调用该Bean所实现的afterPropertysSet方法。
    下面示例中的Bean既实现了InitializingBean接口,也包含了一个普通的初始化方法——在配置文件中将该方法配置成初始化方法。

    public class InitActionBean implements InitializingBean,ApplicationContextAware {
    	private String name;
    	//name对应的get set 方法
    	public InitActionBean(){
    		System.out.println("InitActionBean的构造器被调用。。。。");
    	}
    	public void setName(String name){
    		this.name = name;
    		System.out.println("调用setName方法完成赋值操作。。。。。");
    	}
    	@Override
    	public void setApplicationContext(ApplicationContext arg0)
    			throws BeansException {
    		System.out.println("设置Spring容器的对象。。。。。");
    	}
    	@Override
    	public void afterPropertiesSet() throws Exception {
    		System.out.println("初始化结束后,调用afterPropertiesSet方法。。。。");
    	}
    	public void init(){
    		System.out.println("调用指定的init方法完成初始化之后的操作。。。。");
    	}
    }
    

    Bean销毁之前的行为
    与定制初始化行为相似,Spring也提供两种方式定制Bean实例销毁之前的特定行为,这两种方式如下:
    使用destroy-method属性。
    实现DisposableBean接口。
    让Bean类实现DisposableBean接口,需实现接口中声明的destroy方法,该方法在Bean被销毁前调用,第二种方式同样为侵入式设计,不推荐采用。销毁之前的行为与依赖关系注入之后的行为原理一样,不再进行详细解释。
    协调作用域不同步的Bean
    当两个singleton作用域的Bean存在依赖关系时,或者当prototype作用域的Bean依赖singleton作用域的Bean时,使用Spring提供的依赖注入进行管理即可。
    singleton作用域的Bean只有一次初始化的机会,它的依赖关系也只在初始化阶段被设置,当singleton作用域的Bean依赖prototype作用域的Bean时,Spring容器会在初始化singleton作用域的Bean之前,先创建被依赖的prototype Bean,然后才初始化singleton Bean,并将prototype Bean注入到singleton Bean中,这就会导致任何时候通过singleton Bean去访问prototype Bean时,得到的永远是最初那个prototype Bean,任何人访问都将得到相同的信息,这就会产生不同步的现象。解决该问题又如下两种思路:
    放弃依赖注入:singleton作用域的Bean每次需要prototype作用域的Bean时,主动向容器请求一个新的Bean实例,即可保证每次注入的的都是最新的实例。
    使用lookup-method元素:使用该元素指定方法注入。
    第一种方式显然不合适,将会造成代码的耦合,在通常情况下,推荐采用第二种做法,使用方法注入。
    使用lookup子元素可以让Spring容器重写容器中Bean的抽象或者具体方法,返回查找容器中其他Bean的结果,被查找的Bean通常是一个prototype Bean。Spring通过使用JDK动态代理或cglib库修改客户端的二进制码,从而实现上述要求。
    为了使用lookup方法注入,大致需要如下两步。
    1、将调用者Bean的实现类定义为抽象类,并定义一个方法来获取被依赖的Bean。
    2、在bean元素中添加lookup-method子元素让Spring容器为调用者Bean提供一个实现类,并实现指定的抽象方法。

    singleton Bean:
    public abstract class Hunter {
    	private Dog dog;
    	public abstract Dog getDog();
    	public void hunt(){
    		System.out.println("我的猎狗为:"+this.getDog());
    	}
    }
    
    被依赖的prototype Bean:
    public class Dog implements Pet {
    	private String name;
    	public void setName(String name){
    		this.name = name;
    	}
    	public String getName(){
    		return this.name;
    	}
    	@Override
    	public void testPet() {
    		System.out.println(name+":狗喜欢吃骨头!");
    	}
    }
    

    配置文件:

    <bean id="hunDog" class="com.langsin.factory.Dog" scope="prototype"/>
    <bean id="hunter" class="com.langsin.init.Hunter">
    		<lookup-method name="getDog" bean="hunDog"/>
    </bean>
    

    测试代码:

    public static void main(String[] args) throws Exception {
    		ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
    		Hunter hun = ctx.getBean("hunter", Hunter.class);
    		hun.hunt();
    		hun = ctx.getBean("hunter", Hunter.class);
    		hun.hunt();
    	}
    

    在这里插入图片描述

    展开全文
  • Spring Bean详细讲解 什么是Bean?

    万次阅读 多人点赞 2018-11-19 15:45:37
    什么是Bean? Spring Bean是被实例的,组装的及被Spring 容器管理的Java对象。 Spring 容器会自动完成@bean对象的实例化。 创建应用对象之间的协作关系的行为称为:装配(wiring),这就是依赖注入的本质。 Spring ...

    什么是Bean?

    Spring Bean是被实例的,组装的及被Spring 容器管理的Java对象。

    Spring 容器会自动完成@bean对象的实例化。

    创建应用对象之间的协作关系的行为称为:装配(wiring),这就是依赖注入的本质。

    Spring 三种配置方案

    1.在XML中进行显示配置
    2.使用Java代码进行显示配置
    3.隐式的bean发现机制和自动装配
    推荐方式: 3>2>1

    一、自动化装配bean

    1.组件扫描(component scanning):Spring 会自动发现应用上下文中所创建的bean。
    2.自动装配(autowiring):Spring自动满足bean之间的依赖。

    package com.stalkers;
    
    /**
     * CD唱片接口
     * Created by stalkers on 2016/11/17.
     */
    public interface ICompactDisc {
        void play();
    }
    
    package com.stalkers.impl;
    
    import com.stalkers.ICompactDisc;
    import org.springframework.stereotype.Component;
    
    /**
     * Jay同名专辑
     * Created by stalkers on 2016/11/17.
     */
    @Component
    public class JayDisc implements ICompactDisc {
    
        private String title = "星晴";
    
        public void play() {
            System.out.println(title + ":一步两步三步四步,望着天上星星...");
        }
    }
    

    Component注解作用:
    表明该类会作为组件类。

    不过,组件扫描默认是不开启用的,我们还需要显示配置下Spring,从而命令它去寻找带有@Component注解的类,并为其创建bean。

    1.java code开启组件扫描:
    其中,如果CompoentScan后面没有参数的话,默认会扫描与配置类相同的包

    @Configuration
    @ComponentScan
    public class CDPlayerConfig {
        @Bean
        public ICompactDisc disc() {
            return new JayDisc();
        }
    }
    

    2.xml启动组件扫描

    <?xml version="1.0" encoding="utf-8" ?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/context
              http://www.springframework.org/schema/context/spring-context.xsd">
        <context:component-scan base-package="com.stalkers.impl"/>
    </beans>

    测试代码

    package com.stalkers;
    
    import com.stalkers.config.CDPlayerConfig;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    /**
     * Created by stalkers on 2016/11/18.
     */
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes = CDPlayerConfig.class)
    public class TestPlay {
        @Autowired
        private ICompactDisc jayDisc;
    
        @Test
        public void play() {
            jayDisc.play();
        }
    }
    

    在ComponentScan扫描的包中,所有带有@Component注解的类都会创建为bean

    为组件扫描的bean命名

    Spring应用上下文种所有的bean都会给定一个ID。在前面的例子中,尽管我们没有明确地为JayDisc bean设置ID,但是Spring会默认为JayDisc设置ID为jayDisc,也就是将类名的第一个字母变成小写

    如果想为这个bean设置不同的ID,那就将期望的值传递给@Component注解

    @Component("zhoujielun")
    public class JayDisc implements ICompactDisc {
      ...
    }

    如果不使用@Component注解的话,则使用Java依赖注入规范(Java Dependency Injection)中所提供的@Named注解bean的ID。

    需要引入:

       <dependency>
                <groupId>javax.inject</groupId>
                <artifactId>javax.inject</artifactId>
                <version>1</version>
            </dependency>
    
    @Named("zhoujielun")
    public class JayDisc implements ICompactDisc {
      ....
    }

    设置组件扫描的基础包

    前面再给CDPlayerConfig类设置@ComponentScan,我们并没有设置任何属性,这个时候默认扫描默认包是:CDPlayerConfig类所在包及其包的子包。

    如果是下图这种情况,DisConfig与其这时候就需要设置@ComponentScan的扫描的包。

    image

    @Configuration
    @ComponentScan(basePackages = {"com.stalkers.soundsystem"})
    public class DiscConfig {
    }
    

    basePackages使用的是复数,则意味着可以设置多个基础包。

    但是basePackages后面跟的是String类型,这种类型并不安全。可以使用basePackageClasses有下面这种写法:

    @Configuration
    @ComponentScan(basePackageClasses = {com.stalkers.soundsystem.JayCompactDisc.class})
    public class DiscConfig {
    }

    通过为bean添加注解实现自动装配

    如果所有的对象都是独立的,彼此之间没有任何依赖,那么使用组件扫描就能自动化装配bean。

    但是实际工作中,很多对象会依赖其他对象完成任务。这时候就需要能够将组件扫描得到的bean和他们依赖装配在一起。这就是自动装配(autowiring)

    使用Spring的Autowired

    public interface IMediaPlayer {
        void play();
    }
    @Component
    public class CDPlayer implements IMediaPlayer {
    
        private ICompactDisc cd;
        
        @Autowired
        public CDPlayer(ICompactDisc cd) {
            this.cd = cd;
        }
    
        public void play() {
            System.out.println("cd Play:");
            cd.play();
        }
    }

    CDPlayer类的构造器上添加了@Autowired注解,表明当Spring创建CDPlayerbean的时候,会通过这个构造器来进行实例化

    Autowired的多种方式
    1.构造器注解(constructor)

    2.属性setter注解

    3.field注解

    不管使用上面3中的哪个方法,Spring都会满足声明的依赖。假如有且只有一个bean匹配依赖的话,那么这个bean将会被装配进来。

    如果使用2,3方式注解,有多个bean的话,则用Qualifier指定。

    如果没有匹配的bean,那么在应用上下文创建的时候,Spring会抛出一个异常。为了避免异常的出现,可以使用

    @Autowired(required = false)
    private IMediaPlayer CDPlayer;

    required=false表示如果没有匹配的话,Spring会让bean处于未装配的样子。使用未装配的属性,会出现NullPointerException

    总结:
    所以在使用开发的时候一般建议使用Resource(package javax.annotation)进行注解。但是Resource不支持构造器注解

    二、通过Java代码装配Bean

    尽管在很多场景下通过组件扫描和自动装配实现Spring的自动化更为推荐,但是有时候行不通。比如引用第三方组件,没办法在它的类上添加@Component及@Autowired。所以就需要JavaConfig或者XML配置

    在进行显示配置的时候,JavaConfig是更好的解决方案。

    JavaConfig与其他的Java代码又有所区别,在概念上它与应用程序中的业务逻辑和领域代码又有所不同。JavaConfig是配置相关代码,不含任何逻辑代码。通常会将JavaConfig放到单独的包中。

    创建JavaConfig类

    @Configuration
    public class CDPlayerConfig {
    }

    使用@Configuration表明CDPlayerConfig是一个配置类

    声明简单的bean

    @Bean
    public IMediaPlayer cdplayer() {
        return new VCDPlayer(new JayCompactDisc());
    }

    @Bean注解会告诉Spring将返回一个对象。

    默认情况下,@Bean的Id与带有@Bean的方法名一样。当然也可以通过@Bean的name属性指定额外的方法名。

    借助JavaConfig注入

    在上面的例子中,初始化个VCDPlayer都需要new一个JayCompactDisc对象。如果其他的对象的也需要JayCompactDisc,所以优化如下:

    @Bean
    public IMediaPlayer cdplayer() {
        return new VCDPlayer(disc());
    }
    
    @Bean
    public ICompactDisc disc() {
        return new JayCompactDisc();
    }

    单独抽出disc()方法,在其方法上加上Bean注解,Spring上加@Bean注解的都是默认单例模式,不管disc()被多个方法调用,其disc()都是同一个实例。

    当然上面的初始化可以优化如下:

    @Bean
    public IMediaPlayer cdplayer(ICompactDisc disc) {
        return new VCDPlayer(disc);
    }

    三、通过XML装配Bean

    在xml配置中,创建一个xml文件,并且要以元素为根。

    <?xml version="1.0" encoding="utf-8" ?>
    <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.xsd">
       
    </beans>

    在使用xml的时候,需要在配置文件顶部声明多个xml模式(XML Schema Definition xsd)文件

    对于我们需要配置bean的则在spring-beans模式中。

    <?xml version="1.0" encoding="utf-8" ?>
    <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.xsd">
        <bean id="jayCompactDisc" class="com.stalkers.soundsystem.JayCompactDisc"></bean>
    </beans>

    1.借助构造器注入初始化bean

    构造器注入的方案:
    1.元素

    <?xml version="1.0" encoding="utf-8" ?>
    <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.xsd">
        <bean id="jayCompactDisc" class="com.stalkers.soundsystem.JayCompactDisc"></bean>
        <bean id="cdPlayer" class="com.stalkers.soundsystem.VCDPlayer">
            <constructor-arg ref="jayCompactDisc"/>
        </bean>
    </beans>

    2.使用Spring3.0所引入的c-命名空间

    使用c-命名空间,需要引入:

    xmlns:c="http://www.springframework.org/schema/c"
    <?xml version="1.0" encoding="utf-8" ?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:c="http://www.springframework.org/schema/c"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd">
        <bean id="jayCompactDisc" class="com.stalkers.soundsystem.JayCompactDisc"></bean>
        <bean id="cdPlayer" class="com.stalkers.soundsystem.VCDPlayer" c:cd-ref="jayCompactDisc">
        </bean>
    </beans>

    解析:c-命名空间的语法:

    c:cd-ref="jayCompactDisc"

    1.c 代表命名空间前缀

    2.cd 代表VCDPlayer类的构造器参数名。当然我们也可以使用参数在整个参数列表的位置 c:_0-ref

     <bean id="cdPlayer" class="com.stalkers.soundsystem.VCDPlayer" c:_0-ref="jayCompactDisc">

    使用下划线因为参数不能以数字开头,所以加下划线。

    3.-ref 代表注入bean引用

    4.jayCompactDisc 要注入的bean的id

    注意:

    c-命名需要写在标签内,与constructor-arg写法差别很大

    将字面量注入到构造器中

    上面我们所做的DI通常指的是类型的装配,也就是将对象的引用装配到依赖他们的其他对象中,但是有时候我们传的只是一个字面量值

    public class VaeCompactDisc implements ICompactDisc {
        private String title;
    
        public VaeCompactDisc(String title) {
            this.title = title;
        }
    
        public void play() {
            System.out.println("大家好,我是Vae,下面这首:" + title + "献给大家的");
        }
    }
    <bean id="cdPlayer" class="com.stalkers.soundsystem.VCDPlayer" c:_0-ref="vaeCompactDisc">
    </bean>
    <bean id="vaeCompactDisc" class="com.stalkers.soundsystem.VaeCompactDisc">
        <constructor-arg value="浅唱"></constructor-arg>
    </bean>

    c-命名空间的写法

    <bean id="cdPlayer" class="com.stalkers.soundsystem.VCDPlayer" c:_0-ref="vaeCompactDisc">
    </bean>
    <bean id="vaeCompactDisc" class="com.stalkers.soundsystem.VaeCompactDisc" c:title="城府">
        <!--<constructor-arg value="浅唱"></constructor-arg>-->
    </bean>

    装配集合

    public class VaeCompactDisc implements ICompactDisc {
        private String title;
    
        private List<String> tracks;
    
        public VaeCompactDisc(String title, List<String> tracks) {
            this.title = title;
            this.tracks = tracks;
        }
    
        public void play() {
            System.out.println("大家好,我是Vae,下面这专辑:" + title + "献给大家的");
            for (String s : tracks) {
                System.out.println(s);
            }
        }
    }

    Spring配置使用constructor-arg。而c-命名的是无法使用装配集合的功能

    <bean id="cdPlayer" class="com.stalkers.soundsystem.VCDPlayer" c:_0-ref="vaeCompactDisc">
    </bean>
    <bean id="vaeCompactDisc" class="com.stalkers.soundsystem.VaeCompactDisc">
        <constructor-arg name="title" value="自定义"></constructor-arg>
        <constructor-arg name="tracks">
            <list>
                <value>有何不可</value>
                <value>多余的解释</value>
            </list>
        </constructor-arg>
    </bean>

    2.使用属性Setter方法注入

    public class CDPlayer implements IMediaPlayer {
    
        private ICompactDisc cd;
    
        @Autowired
        public void setCd(ICompactDisc cd) {
            this.cd = cd;
        }
        
        public CDPlayer(ICompactDisc cd) {
            this.cd = cd;
        }
    
        public void play() {
            System.out.println("cd Play:");
            cd.play();
        }
    }
    

    Spring.xml配置里面

    <bean id="cdPlayer" class="com.stalkers.soundsystem.VCDPlayer">
        <property name="cd" ref="jayCompactDisc"></property>
    </bean>

    元素为属性的Setter方法所提供的功能与元素为构造器所提供的功能是一样的。

    与c-命名空间的类似的作为property的替代方案:p-命名空间。使用p-命名空间需要引入:

    xmlns:p="http://www.springframework.org/schema/p"

    Spring.xml配置如下

    <bean id="cdPlayer" class="com.stalkers.soundsystem.VCDPlayer" p:cd-ref="vaeCompactDisc">

    语法解析:

    p:cd-ref="vaeCompactDisc"

    1.p-:命名空间的前缀

    2.cd:属性名称

    3.-ref:注入bean引用

    4.vaeCompactDisc:所注入的bean的id

    将字面量注入到属性中

    字面量注入到属性与上面将字面量注入到构造方法中方式一样。只不过标签名改成了property。

    装配list也是与上面的构造器的装配list一样。

    虽然我们无法使用c-及p-命名空间装配list,但是我们可以使用

    <bean id="vaeCompactDisc" class="com.stalkers.soundsystem.VaeCompactDisc" c:title="自定义" c:tracks-ref="songs">
    </bean>
    <util:list id="songs">
        <value>有何不可</value>
        <value>多余的解释</value>
    </util:list>

    Spring util命名空间的中的元素:

    元素 描述
    util:constant 引用某个类型的public static 域
    util:list 创建一个java.util.List类型的bean,其中包含值或引用
    util:map 创建一个java.util.Map类型的bean,其中包含值或引用
    util:properties 创建一个java.util.Properties类型的bean
    util:property-path 引用一个bean的属性
    util: set 创建一个java.util.Set类型的bean

    在此我向大家推荐一个架构学习交流群。交流学习群号:895244712 里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化、分布式架构等这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

    四、导入和混合配置

    在Spring应用中,我们可以同时使用自动化和显示配置。

    如果一个JavaConfig配置太臃肿,我们可以把其进行拆分,然后使用@Import将拆分的类进行组合。

    如果希望在JavaConfig里引用xml配置。则可以使用@ImportResource

     

    展开全文
  • 一切都要从Bean开始

    万次阅读 2018-03-23 19:15:17
    在Spring应用中,我们经常会遇到如下的报错字样,本文将介绍传统Spring项目以及SpringBoot项目如何定义Bean以及配置Bean的依赖关系,并结合这些错误出现的场景加以说明其原理。 java.lang.NullPointerException ...
  • @bean

    千次阅读 2018-10-29 14:35:14
    Spring帮助我们管理Bean分为两个部分,一个...在自动配置的方式中,使用@Component去告诉Spring,我是一个bean,你要来管理我,然后使用@AutoWired注解去装配Bean(所谓装配,就是管理对象直接的协作关系)。然后在Jav...
  • bean:write用法

    千次阅读 2019-10-23 18:05:36
    bean:write&amp;amp;amp;amp;amp;gt;是什么 &amp;amp;amp;amp;amp;lt;bean:write&amp;amp;amp;amp;amp;gt;是struts标签中bean中的一种,&amp;amp;amp;amp;amp;lt;bean:write name=“key”&amp;...
  • bean的理解

    2018-07-05 09:34:53
    Bean在Spring和SpringMVC中无所不在,将这个概念内化很重要,下面分享一下我的想法: 一、Bean是啥1、Java面向对象,对象有方法和属性,那么就需要对象实例来调用方法和属性(即实例化); 2、凡是有方法或属性的...
  • Annotation-specified bean name 'DistrictServiceImpl' for bean class [com.qiu.service.impl.DoctorDetailServiceImpl] conflicts with existing, non-compatible bean definition of same...
  • spring中配置 对服务自动扫描 public interface PersonService {} @Service("personService") public class PersonServiceImpl implements ...Annotation-specified bean name 'personService' f
  • Singleton bean creation not allowed
  • spring 配置时 bean id 与bean name 的区别

    万次阅读 2011-09-07 00:59:38
    简单的说:id用来标识bean,是唯一的,且只有一个;name定义的是bean的alias,可以有多个,并可能与其他的bean重名。 详细的说: id是唯一标识bean.不能用特殊字符:×#@ ,不能用数字开头。在bean引用的时候只能用...
  • 解决spring的bean同名冲突

    万次阅读 2017-05-18 13:41:43
    今天工作发现当不同模块下有相同bean然后又被同一个模块引用的话就会导致bean同名冲突,如下: 解决方案很简单,如果是xml配置直接修改bean的名称即可,如果是注解形式修改如下: 只要在service后面加上bean的...
  • Spring解析,加载及实例化Bean的顺序(零配置)

    万次阅读 多人点赞 2018-10-29 09:24:41
    Spring零配置下@Bean,@Import,@ComponentScan形式定义Bean的解析,加载及实例化顺序
  • /** * 声明队列交换机等 * @param connectionFactory ... @Bean public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) { System.out.println(String.format("-----------getRabbitAd...
  • 启动tomcat时如下报错严重: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListenerorg.springframework.beans.factory....
  • Spring中的Bean是线程安全的吗?

    万次阅读 多人点赞 2020-08-16 00:36:56
    Spring容器中的Bean是否线程安全,容器本身并没有提供Bean的线程安全策略,因此可以说Spring容器中的Bean本身不具备线程安全的特性,但是具体还是要结合具体scope的Bean去研究。 Spring 的 bean 作用域(scope)类型...
  • 老生常谈的问题,没写spring bean的注解(@service,@Repository..),所以无法完成自动装配。
  • Spring中Bean的五个作用域

    万次阅读 2020-04-22 18:21:56
    当通过Spring容器创建一个Bean实例时,不仅可以完成Bean实例的实例化,还可以为Bean指定特定的作用域。Spring支持如下5种作用域: singleton:单例模式,在整个Spring IoC容器中,使用singleton定义的Bean将只有...
  • spring的自动装配

    万次阅读 2012-04-11 22:59:27
    自动装配,官方给出的定义是这样: Spring IoC容器可以自动装配(autowire)相互协作bean之间的关联关系。...autowire可以针对单个bean进行设置,因此可以让有些bean使用autowire,有些bean不采用。autowire的
1 2 3 4 5 ... 20
收藏数 803,264
精华内容 321,305
关键字:

bean