当前位置: 首页 > news >正文

抓好门户网站建设信用门户网站建设规范

抓好门户网站建设,信用门户网站建设规范,做一个属于自己的网站,淘宝实时优惠券网站怎么做的Java进击框架#xff1a;Spring#xff08;一#xff09;前言创建Spring项目Spring IoC容器和Beans介绍Bean的概述Spring IoC配置元数据实例化Bean依赖注入循环依赖详细配置生命周期回调Bean定义继承基于注解的容器配置Component和进一步的原型注解自动检测类和注册Bean定义… Java进击框架Spring一前言创建Spring项目Spring IoC容器和Beans介绍Bean的概述Spring IoC配置元数据实例化Bean依赖注入循环依赖详细配置生命周期回调Bean定义继承基于注解的容器配置Component和进一步的原型注解自动检测类和注册Bean定义使用JSR 330标准注释ApplicationContext的附加功能前言 Spring 诞生于 2003 年轻量级的 Java 开源框架是对早期 J2EE 规范复杂性的回应。虽然有些人认为Java EE和Spring是竞争但Spring实际上是Java EE的补充。 从整体上看Spring可以分为五个部分从上到下、从左到右Data Access/Integration、Web、AOP、Core Container、Test。 Data Access/Integration数据访问与集成包括 JDBC、ORM、OXM、JMS 和 Transactions 模块主要提供数据库底层操作和事务控制等支持。Web提供了基本web集成特性比如多文件上传功能、资源请求数据绑定、通讯等支持。AOP面向切面编程。比如日志记录、权限控制、性能统计等通用功能和业务逻辑分离的技术。Core Container核心容器。提供控制反转IOC和依赖注入DI上下文配置表达式语言等支持。Test测试模块。使用Junit和TestNG对Spring组件进行测试。 除了Spring Framework之外还有其他项目例如Spring BootSpring SecuritySpring DataSpring CloudSpring Batch等。 创建Spring项目 1以idea为例先创建Maven项目。2然后再main文件下创建resouces文件。 3找到idea最右侧标记为Resource文件。 4然后引入依赖spring5.3.23为例。 dependencies!-- https://mvnrepository.com/artifact/org.springframework/spring-context --dependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactIdversion5.3.23/version/dependency!-- https://mvnrepository.com/artifact/org.springframework/spring-core --dependencygroupIdorg.springframework/groupIdartifactIdspring-core/artifactIdversion5.3.23/version/dependency!-- https://mvnrepository.com/artifact/org.springframework/spring-beans --dependencygroupIdorg.springframework/groupIdartifactIdspring-beans/artifactIdversion5.3.23/version/dependency!-- https://mvnrepository.com/artifact/org.springframework/spring-expression --dependencygroupIdorg.springframework/groupIdartifactIdspring-expression/artifactIdversion5.3.23/version/dependency/dependencies5再resources文件下创建xml文件文件名自定义。 6写入基本配置结构 ?xml version1.0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsd/beans这样就创建完成spring项目后续通过此结构进行讲解。 Spring IoC容器和Beans介绍 在 Spring 中构成应用程序主干并由 Spring IoC 容器管理的对象称为 Bean。 Bean 是由 Spring IoC 容器实例化组装和以其他方式管理的对象。Bean 及其之间的依赖关系反映在容器使用的配置元数据中。配置元数据用XML、Java注释或Java代码表示。它让您能够表达组成应用程序的对象以及这些对象之间丰富的相互依赖关系。 Bean的概述 Spring IoC容器管理一个或多个beans。这些beans是用您提供给容器的配置元数据创建的(例如以XML的形式bean/定义)。 在容器本身中这些bean定义表示为BeanDefinition对象这些对象包含以下元数据(以及其他信息): 包限定类名:通常是正在定义的bean的实际实现类。 Bean行为配置元素声明bean在容器中的行为方式(范围、生命周期回调等)。 对bean完成其工作所需的其他bean的引用。这些引用也称为协作者或依赖者。 要在新创建的对象中设置的其他配置设置例如池的大小限制或在管理连接池的bean中使用的连接数。 这些元数据转化为一组组成每个bean定义的属性。下表描述了这些属性: 属性介绍Class实例化beanName命名beanScopebean范围Constructor arguments构造器参数Dependency Injection依赖注入Autowiring mode自动装配模式Lazy initialization mode延迟初始化的beanInitialization method初始化方法Destruction method销毁方法 Spring IoC IoCInversion of Control控制反转也称为依赖注入DI。 我们可以先来重温一下初学Java时当某个类需要调用其它类的方法直接new这个类再调用方法如代码所示 public class B {public void b(){} } public class A {public static void main(String[] args) {B b new B();b.b();} }这样就很容易导致耦合度太高有了IOC容器后将主动权交给了第三方进行管理。 定义一个容器配置元数据 beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdbean ida classcom.example.Aconstructor-arg refb/constructor-arg/beanbean idb classcom.example.B/bean /beans定义构造类进行注入 public class B {public void b(){} } public class A {private B b;public A(B b) { this.b b; }public void getb(){ b.b(); }public static void main(String[] args) {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);A a applicationContext.getBean(a, A.class);a.getb();} }org.springframework.beans和org.springframework.context包是Spring Framework的IoC容器的基础。 org.springframework.context.ApplicationContext接口代表Spring IoC容器。 你可以创建ClassPathXmlApplicationContext或者FileSystemXmlApplicationContext来启动对元数据的支持。 通过使用IoC这里通过构造器注入还有其它方法使类与类之间耦合性减小所以IoC不是一种技术更多的是一种思想它能指导我们如何设计出松耦合、更优良的程序。 通俗点说IOC容器改变了依赖对象的创建方式反向的向类注入所需要的其它对象 。 配置元数据 Spring IoC容器管理一个或多个beans。这些beans是用您提供给容器的配置元数据创建的(例如以XML的形式bean/定义)。基于XML的配置元数据将这些beans配置为bean/顶层中的元素beans/元素。 ?xml version1.0 encodingUTF-8? !--省略链接地址-- beansbean ida namea,a1;a3 classcom.example.A scopesingleton/beanalias namea aliasas-a/alias /beansid属性标识单个bean定义唯一标识。 public static void main(String[] args) {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);A a applicationContext.getBean(a, A.class);}name属性标识单个bean定义唯一标识可以与id相同指定多个名称可以使用逗号或者分号隔开。 public static void main(String[] args) {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);A a applicationContext.getBean(a1, A.class);}alias属性有时需要为在别处定义的bean引入别名在基于XML的配置元数据中可以使用元素来实现这一点。 public static void main(String[] args) {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);A a applicationContext.getBean(as-a, A.class);}class属性定义bean的类型并使用完全限定的类名。如果id和name都没有想要获取bean可以通过完全限定的类名。 public static void main(String[] args) {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);A a applicationContext.getBean(com.example.A, A.class);}scope属性指定对象的作用范围。最初只有两种singleton和prototype随着版本的不断更新新增类型request、session、application、websocket。Bean的生命周期有三种创建、运行、销毁。 1singleton默认值。Spring容器中只有一个实例。 创建容器创建时对象创建。 运行容器存在一直存活。 销毁容器销毁对象销毁。 示例代码 ?xml version1.0 encodingUTF-8? !--省略链接地址-- beansbean ida classcom.example.A scopesingleton/bean /beanspublic class A {public static void main(String[] args) {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);A a applicationContext.getBean(a, A.class);System.out.println(a);a applicationContext.getBean(a, A.class);System.out.println(a);/** Output:* com.example.Aff5b51f* com.example.Aff5b51f*/} }运行后我们发现当范围为singleton时打印输出的内存地址相同容器只创建了一个实例。 2prototype每次请求Spring容器都会创建一个新的实例。 创建使用时对象创建。 运行对象使用时一直存活。 销毁对象长时间不用且没有别的对象引用时由Java的垃圾回收机制回收。 示例代码 ?xml version1.0 encodingUTF-8? !--省略链接地址-- beansbean ida classcom.example.A scopeprototype/bean /beanspublic class A {public static void main(String[] args) {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);A a applicationContext.getBean(a, A.class);System.out.println(a);a applicationContext.getBean(a, A.class);System.out.println(a);/** Output:* com.example.A6e1567f1* com.example.A5cb9f472*/} }运行后我们发现当范围为prototype时打印输出的内存地址不相同容器只创建了两个实例。 3request每个HTTP请求都有自己的bean实例仅在web有效。 4session将单个bean定义作用于HTTP Session的生命周期仅在web有效。 5application将单个bean定义作用于ServletContext的生命周期仅在web有效。 6websocket将单个bean定义作用于WebSocket的生命周期仅在web有效。 7自定义范围bean作用域机制是可扩展的。您可以定义自己的作用域甚至重新定义现有的作用域尽管后者被认为是不好的做法您需要实现org.springframework.beans.factory.config.Scope接口。 public class NewScope implements Scope {public Object get(String s, ObjectFactory? objectFactory) { return null; }public Object remove(String s) { return null; }public void registerDestructionCallback(String s, Runnable runnable) { }public Object resolveContextualObject(String s) { return null; }public String getConversationId() { return null; } }实例化Bean bean定义本质上是创建一个或多个对象的方法。当被访问时容器查看命名bean的配方并使用由该bean定义封装的配置元数据来创建(或获取)实际对象。 实例化 Bean 有四种方式构造函数实例化、静态工厂方法实例化、实例工厂方法进行实例化、接口实例化。 构造函数实例化 当您通过构造器方法创建一个bean时所有普通的类都可以被Spring使用并与之兼容。Spring IoC容器实际上可以管理您希望它管理的任何类。您还可以在容器中包含更多奇特的非bean样式的类。 使用基于XML的配置元数据您可以按如下方式指定bean类: ?xml version1.0 encodingUTF-8? !--省略链接地址-- beansbean ida classcom.example.A/bean /beans示例代码如下 public class A {public A() {System.out.println(构造方法实例化);}public static void main(String[] args) {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);A a applicationContext.getBean(a, A.class);System.out.println(a);/** Output:* 构造方法实例化* com.example.A462d5aee*/} }静态工厂方法实例化 通过factory-method属性指定工厂方法用静态工厂方法创建的bean。在此示例中getInstance()方法必须是static方法。以下示例显示了如何指定工厂方法: ?xml version1.0 encodingUTF-8? !--省略链接地址-- beansbean ida classcom.example.A factory-methodgetInstance/bean /beans示例代码如下 public class A {public static A getInstance(){System.out.println(静态工厂实例);return new A();}public static void main(String[] args) {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);A a applicationContext.getBean(a, A.class);System.out.println(a);/** Output:* 静态工厂实例* com.example.A148080bb*/} }实例工厂方法进行实例化 实例工厂方法是通过现有非静态方法bean创建新的bean。要使用这种机制将class属性为空并且在factory-bean属性指定当前(或父或祖先)容器中bean的名称该容器包含创建对象时要调用的实例方法。属性设置工厂方法本身的名称factory-method属性。以下示例显示了如何配置这样的bean ?xml version1.0 encodingUTF-8? !--省略链接地址-- beansbean ida classcom.example.A/beanbean ida2 factory-beana factory-methodgetInstance/bean /beans示例代码如下 public class A {public A getInstance(){System.out.println(实例化工厂方法);return new A();}public static void main(String[] args) {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);A a applicationContext.getBean(a2, A.class);System.out.println(a);/** Output:* 实例化工厂方法* com.example.A6e1ec318*/} }接口实例化 BeanFactory接口提供了能够管理任何类型对象的高级配置机制。ApplicationContext是BeanFactory的子接口。 BeanFactory定义了IOC容器的最基本形式并提供了IOC容器应遵守的的最基本的接口也就是Spring IOC所遵守的最底层和最基本的编程规范。 public interface BeanFactory {String FACTORY_BEAN_PREFIX ;//省略部分代码... ...Object getBean(String var1) throws BeansException;T ObjectProviderT getBeanProvider(ClassT var1);boolean containsBean(String var1);boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;boolean isPrototype(String var1) throws NoSuchBeanDefinitionException;boolean isTypeMatch(String var1, Class? var2) throws NoSuchBeanDefinitionException;NullableClass? getType(String var1) throws NoSuchBeanDefinitionException;String[] getAliases(String var1); }如果按照传统的方式则需要在中提供大量的配置信息。Spring提供了一个FactoryBean的工厂类接口FactoryBean是个Bean用户可以通过实现该接口定制实例化Bean的逻辑。 ?xml version1.0 encodingUTF-8? !--省略链接地址-- beansbean ida classcom.example.A/bean /beanspublic class A implements FactoryBeanA {public A getObject() throws Exception {System.out.println(FactoryBean a);return new A();}public Class? getObjectType() {return A.class;}public static void main(String[] args) {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);A a applicationContext.getBean(a, A.class);System.out.println(a);/** Output:* FactoryBean a* com.example.A29ca901e*/}}依赖注入 依赖注入(DI)是一个过程通过构造函数参数、工厂方法的参数等方式在对象实例上设置的属性来定义它们的依赖关系(即它们使用的其他对象)。然后容器在创建bean时注入这些依赖项。这个过程基本上是bean本身的逆过程(因此得名控制反转)。 依赖注入(DI)有三种主要形式基于构造函数的依赖注入和基于Setter的依赖注入、自动注入。 基于构造函数的依赖注入 基于构造函数的依赖注入(DI)是通过容器调用一个带有多个参数的构造函数来实现的每个参数代表一个依赖项。 通过constructor-arg标签进行构造函数注入ref 属性引用了另一个bean定义的名称。id属性和ref属性之间的链接表示协作对象之间的依赖关系 ?xml version1.0 encodingUTF-8? !--省略链接地址-- beansbean ida classcom.example.Aconstructor-arg refc/constructor-argconstructor-arg refb/constructor-arg/beanbean idb classcom.example.B/beanbean idc classcom.example.C/bean /beans示例代码如下 public class B {public void b(){System.out.println(b);} } public class C {public void c(){System.out.println(c);} } public class A {private B b;private C c;public A(B b,C c) {this.b b;this.c c;}public static void main(String[] args) {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);A a applicationContext.getBean(a, A.class);a.b.b();a.c.c();/** Output:* b* c*/} }再Bean中定义的顺序就是实例化bean时提供给相应构造函数的顺序。 如果构造参数为基本类型的有参构造时可以通过type属性指定构造函数参数的类型value属性指定参数值 ?xml version1.0 encodingUTF-8? !--省略链接地址-- beansbean ida classcom.example.Aconstructor-arg typeInteger value123/constructor-argconstructor-arg typeString valuec/constructor-arg/bean /beans示例代码如下 public class A {private Integer b;private String c;public A(Integer b,String c) {this.b b;this.c c;}public static void main(String[] args) {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);A a applicationContext.getBean(a, A.class);System.out.println(a.b);System.out.println(a.c);/** Output:* 123* c*/}}您也可以使用index属性显式指定构造函数参数的索引如下例所示 ?xml version1.0 encodingUTF-8? !--省略链接地址-- beansbean ida classcom.example.Aconstructor-arg index0 value123/constructor-argconstructor-arg index1 valuec/constructor-arg/bean /beans基于Setter的依赖注入属性注入 基于setter的依赖注入(DI)是由容器在调用无参数构造函数或无参数构造函数后调用bean上的setter方法来完成的。 下面的示例通过property标签指定bean的一个或多个属性显示了一个只能通过使用纯setter注入进行依赖注入的类。 ?xml version1.0 encodingUTF-8? !--省略链接地址-- beansbean ida classcom.example.Aproperty nameb refb/property/beanbean idb classcom.example.B/bean /beans示例代码如下 public class A {private B b;public void setB(B b) {System.out.println(setter注入);this.b b;}public static void main(String[] args) {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);A a applicationContext.getBean(a, A.class);System.out.println(a.b);/** Output:* setter注入* com.example.B1990a65e*/} }自动注入 你可以使用autowire属性来达到自动装配。autowire属性提供5中策略 ?xml version1.0 encodingUTF-8? !--省略链接地址-- beans!--no和default默认不装配。--bean ida classcom.example.A autowireno/beanbean ida classcom.example.A autowiredefault/bean!--byType通过属性类型注入。--bean ida classcom.example.A autowirebyType/bean!--byName通过属性的名称注入。--bean ida classcom.example.A autowirebyName/bean!--constructor通过构造函数注入。--bean ida classcom.example.A autowireconstructor/bean /beansbyType和byName都是通过setter()方法注入constructor通过构造函数属性的类型注入。 ?xml version1.0 encodingUTF-8? !--省略链接地址-- beansbean ida classcom.example.A autowirebyType/beanbean idb classcom.example.B/bean /beans示例代码如下 public class B{} public class A{private B b;public void setB(B b) { this.b b; }public static void main(String[] args) {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);A a applicationContext.getBean(a, A.class);System.out.println(a.b);/** Output:* com.example.B4c762604*/} }如果未能匹配到类型或者名称则注入失败 public class A{private C c;public void setC(C c) { this.c c; }public static void main(String[] args) {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);A a applicationContext.getBean(a, A.class);System.out.println(a.c);/** Output:* null*/} }你可以使用Autowired注解减少指定属性或构造函数参数的需要。 示例代码如下 Component public class B {} Component public class A{Autowiredprivate B b;public static void main(String[] args) {ApplicationContext applicationContext new AnnotationConfigApplicationContext(com.example);A a applicationContext.getBean(a, A.class);System.out.println(a.b);/** Output:* com.example.B3c419631*/} }使用方法注入 Spring的方法注入可分为两种查找方法注入和任意方法替换。 1查找方法注入 查找方法会导致IoC容器覆盖给定的方法并返回bean属性中给出的名称。这是方法注入的一种形式。 在bean标签里定义lookup-method标签 ?xml version1.0 encodingUTF-8? !--省略链接地址-- beansbean ida classcom.example.Alookup-method namegetB beanb/lookup-method/beanbean idb classcom.example.B/bean /beansname属性指定方法名bean为返回的类型 示例代码如下 public class B {public void b(){ System.out.println(b); } } public class A{private B b;public B getB() { return b; }public static void main(String[] args) {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);A a applicationContext.getBean(a, A.class);System.out.println(a.getB());/** Output:* com.example.B58c1c010*/}}当然你也可以使用注解Lookup示例代码如下: Component public class A{private B b;// Lookup(getB)查找指定bean方法Lookuppublic B getB() {return b;}public static void main(String[] args) {ApplicationContext applicationContext new AnnotationConfigApplicationContext(com.example);A a applicationContext.getBean(A.class);System.out.println(a.getB());/** Output:* com.example.B58c1c010*/} }Autowired注解会将所有bean范围改为单例Lookup可以保证被引入的组件保持prototype模式。 (2)任意方法替换 与查找方法注入相比方法注入的一个不太有用的形式是用另一个方法实现替换受管bean中的任意方法的能力。 对于基于XML的配置元数据您可以使用replaced-method元素将现有的方法实现替换为另一个方法实现。 ?xml version1.0 encodingUTF-8? !--省略链接地址-- beansbean ida classcom.example.Areplaced-method namemethod replacerAReplace!--参数类型--arg-typeString/arg-type/replaced-method/beanbean idAReplace classcom.example.AReplace/bean /beans你可以通过arg-type/指定多个重写方法的参数类型。 示例代码如下 public class AReplace implements MethodReplacer {public Object reimplement(Object o, Method method, Object[] objects) throws Throwable {System.out.println(替换了objects[0].toString());return null;} } public class A{public void method(String p){}public static void main(String[] args) {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);A a applicationContext.getBean(A.class);a.method(123);/** Output:* 替换了123*/} }大多数Spring用户并不直接使用这些类(即以编程方式)而是使用XMLbean定义、带注释的组件。然后这些源在内部被转换为BeanDefinition并用于加载整个Spring IoC容器实例。 循环依赖 如果您主要使用构造函数注入就有可能创建一个无法解析的循环依赖场景。 比如A类通过构造函数注入需要B类的一个实例B类通过构造函数注入需要A类的一个实例。如果将类A和B的beans配置为相互注入Spring IoC容器会在运行时检测到这种循环引用并抛出一个BeanCurrentlyInCreationException。 ?xml version1.0 encodingUTF-8? !--省略链接地址-- beansbean ida classcom.example.Aconstructor-arg nameb refb/constructor-arg/beanbean idb classcom.example.Bconstructor-arg namea refa/constructor-arg/bean /beans示例代码如下 public class B {private A a;public B(A a) {this.a a;} } public class A {private B b;public A(B b) {this.b b;}public static void main(String[] args) {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);A a applicationContext.getBean(a, A.class);System.out.println(a);/** Output: * Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name a: Requested bean is currently in creation: Is there an unresolvable circular reference?* ... 29 more*/} }您可以使用setter注入配置循环依赖项。 ?xml version1.0 encodingUTF-8? !--省略链接地址-- beansbean ida classcom.example.Aproperty nameb refb/property/beanbean idb classcom.example.Bconstructor-arg namea refa/constructor-arg/bean /beans示例代码如下 public class B {private A a;public B(A a) { this.a a; } } public class A {private B b;public void setB(B b) { this.b b; }public static void main(String[] args) {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);A a applicationContext.getBean(a, A.class);System.out.println(a);/** Output:* com.example.A2fd66ad3*/} }Spring容器在创建容器时验证每个bean的配置。它在容器加载时检测配置问题例如bean由于缺少或无效的属性而抛出一个异常。 详细配置 下面介绍其它的配置标签、属性等。 p命名空间 使用p名称空间可以简洁的XML配置我们先看看原来的配置文件 ?xml version1.0 encodingUTF-8? !--省略链接地址-- beansbean ida classcom.example.Aproperty nameid value123456/propertyproperty nameuserName value张三/propertyproperty nameb refb/property/beanbean idb classcom.example.B/bean /beans使用p名称空间首先再beans标签中加入链接 xmlns:p“http://www.springframework.org/schema/p” 然后我们就可以使用p命名空间来配置XML ?xml version1.0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:phttp://www.springframework.org/schema/pxsi:schemaLocationhttp://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdbean ida classcom.example.Ap:id123456p:userName张三p:b-refb/beanbean idb classcom.example.B/bean /beansp:*-ref表示这不是一个直接的值而是对另一个bean的引用。 示例代码如下 public class A {private int id;private String userName;private B b;public void setId(int id) { this.id id; }public void setUserName(String userName) { this.userName userName; }public void setB(B b) { this.b b; }public static void main(String[] args) {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);A a applicationContext.getBean(a, A.class);System.out.println(a.id,a.userName,a.b);/** Output:* 123456,张三,com.example.B52525845*/} }c命名空间 我们先来看看原始的构造函数注入方式 ?xml version1.0 encodingUTF-8? !--省略链接地址-- beansbeansbean ida classcom.example.Aconstructor-arg refb/constructor-argconstructor-arg namename value张三/constructor-arg/beanbean idb classcom.example.B/bean/beans /beans像p命名空间一样可以使用c命名空间来简化配置构造函数参数首先再beans标签中加入链接。 xmlns:c“http://www.springframework.org/schema/c” 然后我们就可以使用c命名空间来配置XML ?xml version1.0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:chttp://www.springframework.org/schema/cxsi:schemaLocationhttp://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdbeansbean ida classcom.example.Ac:b-refbc:name张三/beanbean idb classcom.example.B/bean/beans /beansc:*-ref表示对于另一个bean引用。 示例代码如下 public class A {private B b;private String name;public A(B b, String name) {this.b b;this.name name;}public static void main(String[] args) {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);A a applicationContext.getBean(a, A.class);a.b.b();System.out.println(a.name);/** Output:* b* 张三*/} }idref标签 idref标签只是传递id(一个字符串值不是引用)配置文件如下 ?xml version1.0 encodingUTF-8? !--省略链接地址-- beansbean ida classcom.example.Aproperty namecontentidref beanb/idref/property/beanbean idb classcom.example.B/bean /beans示例代码如下 public class B {} public class A {private String content;public String getContent() {return content;}public void setContent(String content) {this.content content;}public static void main(String[] args) {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);A a applicationContext.getBean(a, A.class);System.out.println(a.getContent());/** Output:* b*/} }前面的bean定义片段完全等同于(在运行时)下面的片段 ?xml version1.0 encodingUTF-8? !--省略链接地址-- beansbean ida classcom.example.Aproperty namecontent valueb//beanbean idb classcom.example.B/bean /beansidref标签让容器在部署时验证被引用的命名bean是否确实存在。 ref属性标签 前面简单介绍了ref属性标签ref属性标签是constructor-arg/标签或者property/标签定义的元素。您将bean的指定属性值设置为由容器管理的另一个bean(协作者)的引用。 ?xml version1.0 encodingUTF-8? !--省略链接地址-- beansbean ida classcom.example.A!--property nameb refb/property--property namebref beanb/ref/property/beanbean idb classcom.example.B/bean /beansCollections 依赖注入可以注入集合list/ set/map/以及props/元素以下示例显示了如何使用它们 1list 介绍两种用法字符串集合、对象集合 ?xml version1.0 encodingUTF-8? !--省略链接地址-- beansbean ida classcom.example.A!--字符串list--property namelistlistvalueqwe/valuevalueasd/value/list/property!--对象list--property namelistObjectlist!--引用其它对象--ref beanb/refbean classcom.example.Bproperty namename valuea/property nameage value01//bean/list/property/beanbean idb classcom.example.Bproperty namename valueb/property nameage value00//bean /beans示例代码如下 public class B {private String name;private Integer age;public String getName() { return name; }public void setName(String name) { this.name name; }public Integer getAge() { return age; }public void setAge(Integer age) { this.age age; } } public class A {private ListString list;private ListB listObject;public void setList(ListString list) { this.list list; }public void setListObject(ListB listObject) { this.listObject listObject; }public static void main(String[] args) {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);A a applicationContext.getBean(a, A.class);System.out.println(JSONObject.toJSONString(a.list));System.out.println(JSONObject.toJSONString(a.listObject));/** Output:* [qwe,asd]* [{age:0,name:b},{age:1,name:a}]*/} }2set set也有两种用法字符串set、对象set ?xml version1.0 encodingUTF-8? !--省略链接地址-- beansbean ida classcom.example.A!--字符串set--property namesetsetvalueqwe/valuevalueasd/value/set/property!--对象set--property namesetObjectset!--引用其它对象--ref beanb/refbean nameb classcom.example.Bproperty namename valuea/property nameage value01//bean/set/property/beanbean idb classcom.example.Bproperty namename valueb/property nameage value00//bean /beans示例代码如下 public class A {private SetString set;private SetB setObject;public void setSet(SetString set) { this.set set; }public void setSetObject(SetB setObject) { this.setObject setObject; }public static void main(String[] args) {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);A a applicationContext.getBean(a, A.class);System.out.println(JSONObject.toJSONString(a.set));System.out.println(JSONObject.toJSONString(a.setObject));/** Output:* [qwe,asd]* [{age:0,name:b},{age:1,name:a}]*/} }3map ?xml version1.0 encodingUTF-8? !--省略链接地址-- beansbean ida classcom.example.Aproperty namemapmapentry keyname valuea/entryentry keyage value01/entry/map/property/bean /beans示例代码如下 public class A {private MapString,String map;public void setMap(MapString, String map) { this.map map; }public static void main(String[] args) {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);A a applicationContext.getBean(a, A.class);System.out.println(JSONObject.toJSONString(a.map));/** Output:* {name:a,age:01}*/} }4props 本质上是hashtable。 ?xml version1.0 encodingUTF-8? !--省略链接地址-- beansbean ida classcom.example.Aproperty namepropspropsprop keynamea/propprop keyage01/prop/props/property/bean /beans示例代码如下 public class A {private Properties props;public void setProps(Properties props) { this.props props; }public static void main(String[] args) {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);A a applicationContext.getBean(a, A.class);System.out.println(JSONObject.toJSONString(a.props));/** Output:* {age:01,name:a}*/} }映射键或值或设置值的值也可以是以下任何元素 bean | ref | idref | list | set | map | props | value | null Null和空字符串值 如果将值设为null或者空字符串可以这样 ?xml version1.0 encodingUTF-8? !--省略链接地址-- beansbean idb classcom.example.Bproperty namename value/property nameagenull/null/property/bean /beans示例代码如下 public class B {private String name;private Integer age;public void setName(String name) { this.name name; }public void setAge(Integer age) { this.age age; }public static void main(String[] args) {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);B b applicationContext.getBean(b, B.class);System.out.println(b.age,b.name);/** Output:* null,*/} }使用depends-on 如果一个bean是另一个bean的依赖项这通常意味着一个bean被设置为另一个bean的属性。通常您可以使用ref/元素在基于XML的配置元数据中。depends-on属性表示bean之间的依赖关系bean被初始化之前指定强制一个或多个bean被初始化。 ?xml version1.0 encodingUTF-8? !--省略链接地址-- beansbean ida classcom.example.A depends-onb,c/beanbean idb classcom.example.B/beanbean idc classcom.example.C/bean /beans示例代码如下 public class B {public void b(){ System.out.println(b); } } public class C {public void c(){ System.out.println(c); } } public class A {public static void main(String[] args) {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);A a applicationContext.getBean(a, A.class);/** Output:* ... ...Creating shared instance of singleton bean b* ... ...Creating shared instance of singleton bean c* ... ...Creating shared instance of singleton bean a*/} }你也可以使用DependsOn注解进行bean的依赖关系初始化。 Configuration public class Config {Bean(a)DependsOn({b})public A getA(){return new A();}Bean(b)public B getB(){return new B();} }当然也可以再类上面使用注解 Component DependsOn(b) public class A{ } Component public class B { }惰性初始化的Beans 一般情况下启动项目时会初始化所有的bean当不希望出现这种行为时可以通过将bean定义标记为惰性初始化来防止单例bean的预实例化。惰性初始化的bean告诉IoC容器在第一次被请求时创建一个bean实例而不是在启动时。 在bean/元素上加入lazy-inittrue属性 ?xml version1.0 encodingUTF-8? !--省略链接地址-- beansbean ida classcom.example.A lazy-inittrue/beanbean idb classcom.example.B/beanbean idc classcom.example.C/bean /beans当项目启动时bean不会被急切地预实例化示例代码如下 public class A {public static void main(String[] args) {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);//使用时被创建 // A a applicationContext.getBean(a, A.class);/** Output:* ... ...Creating shared instance of singleton bean b* ... ...Creating shared instance of singleton bean c*/} }你也可以使用Lazy注解惰性初始化。 Component public class C extends Base{ } Component public class B extends Base{ } Lazy public class A{public static void main(String[] args) {ApplicationContext applicationContext new AnnotationConfigApplicationContext(com.example);/** Output:* Creating shared instance of singleton bean b* Creating shared instance of singleton bean c*/} }设置主Bean 当注入的Bean有多个候选项时应该给Bean设置一个主bean否则注入时会NoUniqueBeanDefinitionException错误 ?xml version1.0 encodingUTF-8? !--省略链接地址-- beansbean ida classcom.example.A autowirebyType/beanbean idb classcom.example.B/beanbean idc classcom.example.C/bean /beanspublic interface Base {} public class B implements Base {} public class C implements Base {} public class A{private Base base;public void setBase(Base base) { this.base base; }public static void main(String[] args) {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);} }我们可以使用primary属性指定为主bean。 ?xml version1.0 encodingUTF-8? !--省略链接地址-- beansbean ida classcom.example.A autowirebyType/beanbean idb classcom.example.B primarytrue/beanbean idc classcom.example.C/bean /beans示例代码如下 public class A{private Base base;public void setBase(Base base) { this.base base; }public static void main(String[] args) {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);A bean applicationContext.getBean(A.class);System.out.println(bean.base);/** Output:* com.example.B16f7c8c1*/} }也可以使用autowire-candidate属性标记当前bean是否会被注入候选项默认truefalse表示排除候选项。 ?xml version1.0 encodingUTF-8? !--省略链接地址-- beansbean ida classcom.example.A autowirebyType/beanbean idb classcom.example.B autowire-candidatefalse/beanbean idc classcom.example.C/bean /beans你还可以使用Primary注解确定一个主要候选对象。 public interface Base {} Primary Component public class B implements Base {} Component public class C implements Base {} Component public class A{Autowiredprivate Base base;public static void main(String[] args) {ApplicationContext applicationContext new AnnotationConfigApplicationContext(com.example);A bean applicationContext.getBean(A.class);System.out.println(bean.base);/** Output:* com.example.B72a7c7e0*/} }context:annotation-config/标签 通过在基于XML的Spring配置中包含context:annotation-config/标签来隐式注册以下后处理器 ConfigurationClassPostProcessor AutowiredAnnotationBeanPostProcessor CommonAnnotationBeanPostProcessor PersistenceAnnotationBeanPostProcessor EventListenerMethodProcessor ?xml version1.0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxsi:schemaLocationhttp://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsd!--识别相应的注解--context:annotation-config//beans限定符qualifier 您可以将限定符值与特定的参数相关联缩小类型匹配的范围以便为每个参数选择特定的bean。 ?xml version1.0 encodingUTF-8? !--省略链接地址-- beans!--识别相应的注解--context:annotation-config/bean ida classcom.example.A autowirebyType/beanbean idb classcom.example.Bqualifier valueb/qualifier/beanbean idc classcom.example.Cqualifier valuec/qualifier/bean /beansqualifier标签搭配Qualifier注解使用 示例代码如下 public interface Base {} public class B implements Base {} public class C implements Base {} public class A{private Base base;public void setBase(Qualifier(b)Base base) { this.base base; }public static void main(String[] args) {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);A bean applicationContext.getBean(A.class);System.out.println(bean.base);/** Output:* com.example.B7920ba90*/} }你也可以使用Autowired注解搭配Qualifier注解使用示例代码如下 public interface Base {} Component public class B implements Base {} Component public class C implements Base {} Component public class A{AutowiredQualifier(b)private Base base;public static void main(String[] args) {ApplicationContext applicationContext new AnnotationConfigApplicationContext(com.example);A bean applicationContext.getBean(A.class);System.out.println(bean.base);/** Output:* com.example.B70e8f8e*/} }还有一种更简单的方式使用JSR-250Resource注解它在语义上被定义为通过其惟一的名称来标识特定的目标组件声明的类型与匹配过程无关。 public interface Base {} Component public class B implements Base {} Component public class C implements Base {} Component public class A{Resource(name b)private Base base;public static void main(String[] args) {ApplicationContext applicationContext new AnnotationConfigApplicationContext(com.example);A bean applicationContext.getBean(A.class);System.out.println(bean.base);/** Output:* com.example.B769f71a9*/} }生命周期回调 为了与容器对bean生命周期的管理进行交互您可以实现Spring的InitializingBean和DisposableBean接口让bean在初始化和销毁bean时执行某些操作。 初始化回调 1使用XML进行初始化 对于基于XML的配置元数据可以使用init-method属性指定具有void无参数签名的方法的名称。 ?xml version1.0 encodingUTF-8? !--省略链接地址-- beansbean ida classcom.example.A init-methodinit/bean /beans实例代码如下 public class A{public void init(){System.out.println(初始化bean);}public static void main(String[] args) {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);A bean applicationContext.getBean(A.class);System.out.println(bean);/** Output:* 初始化bean* com.example.Ab7dd107*/} }2InitializingBean接口 通过实现org.springframework.beans.factory.InitializingBean接口重写afterPropertiesSet()方法执行初始化工作。 ?xml version1.0 encodingUTF-8? !--省略链接地址-- beansbean ida classcom.example.A/bean /beans示例代码如下 public class A implements InitializingBean{public void afterPropertiesSet() throws Exception {System.out.println(初始化);}public static void main(String[] args) {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);A bean applicationContext.getBean(A.class);System.out.println(bean);/** Output:* 初始化bean* com.example.Ab7dd107*/} }3PostConstruct注解 Component public class A {PostConstructpublic void init(){System.out.println(初始化);}public static void main(String[] args) {ApplicationContext applicationContext new AnnotationConfigApplicationContext(com.example);A bean applicationContext.getBean(A.class);System.out.println(bean);/** Output:* 初始化bean* com.example.Ab7dd107*/} }4使用Bean的initMethod属性 Configuration public class Config {Bean(initMethod init)public A a(){return new A();} } Component public class A {public void init(){System.out.println(初始化bean);}public static void main(String[] args) {ApplicationContext applicationContext new AnnotationConfigApplicationContext(com.example);A bean applicationContext.getBean(A.class);System.out.println(bean);/** Output:* 初始化bean* com.example.Ab7dd107*/} }销毁回调 销毁回调和初始化回调的方式基本一致。你可以调用ApplicationContext类的registerShutdownHook()方法和close()方法进行容器销毁。 1使用XML进行销毁 使用destroy-method属性指定无参方法名。 ?xml version1.0 encodingUTF-8? !--省略链接地址-- beansbean ida classcom.example.A destroy-methoddestroy/bean /beans示例代码如下 public class A {public void destroy(){System.out.println(销毁bean);}public static void main(String[] args) {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);A bean applicationContext.getBean(A.class); // ((ClassPathXmlApplicationContext) applicationContext).registerShutdownHook();((ClassPathXmlApplicationContext) applicationContext).close();/** Output:* 销毁bean*/} }2DisposableBean接口 通过实现org.springframework.beans.factory.DisposableBean接口重写destroy()方法执行销毁工作。 ?xml version1.0 encodingUTF-8? !--省略链接地址-- beansbean ida classcom.example.A/bean /beans示例代码如下 public class A implements DisposableBean {public static void main(String[] args) {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);A bean applicationContext.getBean(A.class); // ((ClassPathXmlApplicationContext) applicationContext).registerShutdownHook();((ClassPathXmlApplicationContext) applicationContext).close();/** Output:* 销毁bean*/}public void destroy() throws Exception {System.out.println(销毁bean);} }3PreDestroy注解 Component public class A {PreDestroypublic void destroy() {System.out.println(销毁bean);}public static void main(String[] args) {ApplicationContext applicationContext new AnnotationConfigApplicationContext(com.example);A bean applicationContext.getBean(A.class); // ((AnnotationConfigApplicationContext) applicationContext).registerShutdownHook();((AnnotationConfigApplicationContext) applicationContext).close();/** Output:* 销毁bean*/} }4使用Bean的destroyMethod属性 Configuration public class Config {Bean(destroyMethod destroy)public A a(){return new A();} } Component public class A {public void destroy() {System.out.println(销毁bean);}public static void main(String[] args) {ApplicationContext applicationContext new AnnotationConfigApplicationContext(com.example);A bean applicationContext.getBean(A.class); // ((AnnotationConfigApplicationContext) applicationContext).registerShutdownHook();((AnnotationConfigApplicationContext) applicationContext).close();/** Output:* 销毁bean*/} }默认初始化和销毁方法 你可以在顶层元素beans/标签上使用default-init-method属性和default-destroy-method属性当创建和组装bean时如果bean类有这样的方法它将在适当的时候被调用。 ?xml version1.0 encodingUTF-8? !--省略链接地址-- beans default-init-methodinit default-destroy-methoddestroybean ida classcom.example.A/beanbean idb classcom.example.B/bean /beans示例代码如下 public class B { } public class A {public void init(){ System.out.println(初始化bean); }public void destroy() { System.out.println(销毁bean); }public static void main(String[] args) {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);A bean applicationContext.getBean(A.class); // ((ClassPathXmlApplicationContext) applicationContext).registerShutdownHook();((ClassPathXmlApplicationContext) applicationContext).close();/** Output:* 初始化bean* 销毁bean*/} }Bean定义继承 子bean定义从父定义继承配置数据。子定义可以根据需要覆盖一些值或添加其他值。使用父bean和子bean定义可以节省大量的输入。实际上这是一种模板形式。 ?xml version1.0 encodingUTF-8? !--省略链接地址-- beansbean ida classcom.example.A parentbproperty namename valuechild/property/beanbean idb classcom.example.B abstracttrueproperty namename valueparent/propertyproperty nameage value28/property/bean /beans子类通过parent属性与父类建立关系且可以覆盖相应的父设置。 示例代码如下 public class B {private String name;private Integer age;public void setName(String name) { this.name name; }public void setAge(Integer age) { this.age age; } } public class A{private String name;private Integer age;public String getName() { return name; }public void setName(String name) { this.name name; }public Integer getAge() { return age; }public void setAge(Integer age) { this.age age; }public static void main(String[] args) {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);A bean applicationContext.getBean(A.class);System.out.println(JSONObject.toJSONString(bean));/** Output:* {age:28,name:child}*/} }如果父定义没有指定类则将父bean定义显式标记为abstract是必需的如下例所示 ?xml version1.0 encodingUTF-8? !--省略链接地址-- beansbean ida classcom.example.A parentbproperty namename valuechild/property/beanbean idb abstracttrueproperty namename valueparent/propertyproperty nameage value28/property/bean /beans当父类显式标记为abstract父bean不能自行实例化因为它是不完整的只能用作纯模板bean定义。 基于注解的容器配置 开发人员不使用XML来描述bean连接而是通过使用相关类、方法或字段声明上的注释将配置移入组件类本身。 对于配置Spring注释比XML更好吗 简短的回答是“视情况而定”最长的答案是每种方法都有其优点和缺点通常由开发人员决定哪种策略更适合他们。无论选择什么Spring都可以容纳两种风格甚至可以将它们混合在一起。 Spring的Java配置支持中的核心构件是Configuration注解的类和Bean注解的方法。Configuration是一个类级别的注释表示一个对象是bean定义的来源Bean注解用于指示一个方法实例化、配置和初始化一个由Spring IoC容器管理的新对象。 Configuration public class Config {Beanpublic A getA(){return new A();} }代码相当于下面的XML beansbean idgetA classcom.example.A/bean /beans我们可以使用Scope注解定义一个范围默认范围是singleton Configuration public class Config {BeanScope(prototype)public A getA(){return new A();} }默认情况下配置类使用Bean方法的名称作为结果bean的名称。但是可以指定name Configuration public class Config {Bean(a)public A getA(){return new A();} }有时为bean提供更详细的文本描述会很有帮助您可以使用Description注释。 Configuration public class Config {Bean(a)Description(this is a test)public A getA(){return new A();} }在前面的章节内容中多次使用AnnotationConfigApplicationContext类启用注解操作 public class A{public static void main(String[] args) {ApplicationContext applicationContext new AnnotationConfigApplicationContext(com.example);} }对于XML可以使用ClassPathXmlApplicationContext类 public class A{public static void main(String[] args) {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);} }spring的Configuration类支持的目标不是100%完全替代Spring XML。一些工具比如Spring XML名称空间仍然是配置容器的理想方式。 定义bean的优先级 如果希望数组或列表中的项按特定顺序排序也可以使用Order或Priority注解。 public abstract class Base { }Component Order(2) //Priority(2) public class B extends Base{ }Component Order(1) //Priority(1) public class C extends Base{ }public class A{Autowiredprivate ListBase baseList;public static void main(String[] args) {ApplicationContext applicationContext new AnnotationConfigApplicationContext(com.example);A bean applicationContext.getBean(A.class);System.out.println(bean.baseList);/** Output:* 没有注解之前[com.example.B76508ed1, com.example.C41e36e46]* 加了注解后[com.example.C15eb5ee5, com.example.B4f209819]*/} } Order是Spring提供的注解Priority是JSR 250标准都是值越小优先级越高。 要注意它们不会影响bean的启动顺序这是由依赖关系和DependsOn声明。 Resource注解 Spring还通过使用JSR-250支持注入Resource注释(jakarta.annotation.Resource)或bean属性setter方法。这是Jakarta EE中的常见模式。对于Spring管理的对象Spring也支持这种模式。 Resource接受名称属性。默认情况下Spring将该值解释为要注入的bean名称。换句话说它遵循按名称语义如以下示例所示 public interface Base {} Component public class B implements Base {} Component public class A{Resource(name b)private Base base;Resourceprivate B b;public static void main(String[] args) {ApplicationContext applicationContext new AnnotationConfigApplicationContext(com.example);A bean applicationContext.getBean(A.class);System.out.println(bean.base);/** Output:* com.example.B769f71a9*/} }如果没有显式指定名称则默认名称是从字段名或setter方法派生的。 使用Value Value通常用于注入外部化的属性 application.properties文件内容 spring.application.namestudy配置属性源 Configuration PropertySource(classpath:application.properties) public class Config {}示例代码如下 Component public class A{Value(${spring.application.name})private String name;public static void main(String[] args) {ApplicationContext applicationContext new AnnotationConfigApplicationContext(com.example);A bean applicationContext.getBean(A.class);System.out.println(bean.name);/** Output:* study*/} }如果找不到属性值可以通过属性名:默认值定义一个默认值。 Component public class A{Value(${spring.aaa:123})private String name;public static void main(String[] args) {ApplicationContext applicationContext new AnnotationConfigApplicationContext(com.example);A bean applicationContext.getBean(A.class);System.out.println(bean.name);/** Output:* 123*/} }spring提供了占位符配置器你可以通过setPlaceholderPrefix()方法和 setPlaceholderSuffix()方法自定义占位符。 Configuration PropertySource(classpath:application.properties) public class Config {Beanpublic static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer(){PropertySourcesPlaceholderConfigurer property new PropertySourcesPlaceholderConfigurer();property.setPlaceholderPrefix(**);property.setPlaceholderSuffix(**);return property;} }Spring提供的内置转换器支持允许简单的类型转换(到Integer或者int例如)被自动处理。 Component和进一步的原型注解 Repository注解是任何实现存储库角色或原型的类的标记(也称为数据访问对象或DAO)。Spring提供了进一步的原型注释:Component, Service以及Controller。Component是任何Spring管理的组件的通用原型。Repository, Service以及Controller是专业化的Component对于更具体的用例(分别在持久层、服务层和表示层)。 您还可以组合元注解来创建“组合注解”。例如在RestControllerSpring MVC的注释由以下部分组成Controller和ResponseBody。 自动检测类和注册Bean定义 要自动检测这些类并注册相应的bean您需要将ComponentScan添加到Configuration类其中basePackages属性是这两个类的公共父包。 ConfigurationRestController ComponentScan(basePackages com.example) public class Config { }XML使用方式 ?xml version1.0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxsi:schemaLocationhttp://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsdcontext:component-scan base-packagecom.example/ /beans使用context:component-scan隐式地启用了context:annotation-config的功能。通常不需要包含context:annotation-config元素。 您可以通过应用自定义过滤器来自定义扫描ComponentScan注解添加includeFilters(包含过滤器) 或者 excludeFilters(忽略过滤器) 的属性(XML在context:component-scan元素中配置子元素context:include-filter /或者context:exclude-filter /) FilterType过滤器类型ANNOTATION(注解)、ASSIGNABLE_TYPE(指定类型)、ASPECTJ(切面)、REGEX(正则表达式)、CUSTOM(自定义)。 public class B {} //自定义过滤 public class DemoFilter implements TypeFilter {public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {AnnotationMetadata annotationMetadata metadataReader.getAnnotationMetadata();System.out.println(annotationMetadata.getClassName());return false;} } Controller public class A{public static void main(String[] args) {ApplicationContext applicationContext new AnnotationConfigApplicationContext(Config.class);/** Output:* com.example.B* com.example.DemoFilter*/} } Configuration ComponentScan(basePackages com.example,includeFilters {ComponentScan.Filter(type FilterType.CUSTOM, classes DemoFilter.class),ComponentScan.Filter(type FilterType.ASSIGNABLE_TYPE, classes B.class)},excludeFilters ComponentScan.Filter(type FilterType.ANNOTATION, classes Component.class)) public class Config { }XML格式如下 ?xml version1.0 encodingUTF-8? beanscontext:component-scan base-packagecom.examplecontext:include-filter typecustom expressioncom.example.DemoFilter/context:include-filtercontext:include-filter typeassignable expressioncom.example.B/context:include-filtercontext:exclude-filter typeannotation expressionorg.springframework.stereotype.Component/context:exclude-filter/context:component-scan /beans您也可以通过注解设置useDefaultFiltersfalse ComponentScan(basePackages com.example,useDefaultFilters false)或component-scan/元素的use-default-filtersfalse属性禁用默认过滤器。 beanscontext:component-scan base-packagecom.example use-default-filtersfalse/ /beans这实际上禁用了Component, Repository, Service, Controller,RestControllerConfiguration。 当在扫描过程中自动检测到一个组件时它的bean名称由BeanNameGenerator扫描器已知策略。默认情况下任何Spring原型注释(Component, Repository, Service以及Controller)包含一个名称value从而将该名称提供给相应的bean定义。如果未设置value值默认bean名称生成器返回未大写的非限定类名。 Controller(value a) public class A{}自动检测的组件的默认且最常见的作用域是singleton但是有时您需要一个不同的范围该范围可以由Scope注解。 Service Scope(prototype) public class A{}使用JSR 330标准注释 Spring支持JSR-330标准注释(依赖注入)。先引入Maven依赖。 dependencygroupIdjakarta.inject/groupIdartifactIdjakarta.inject-api/artifactIdversion1.0/version/dependency使用Named注解代替Component注解Inject注解代替Autowired注解示例代码如下 Named(b) public class B{} Named public class A{Injectprivate B b;public static void main(String[] args) {ApplicationContext applicationContext new AnnotationConfigApplicationContext(com.example);A bean applicationContext.getBean(A.class);System.out.println(bean.b);/** Output:* com.example.B67a20f67*/} }还有其他的注解替换比如ManagedBean注解等价于Component注解Scope(singleton)注解等价于Singleton注解。 ApplicationContext的附加功能 使用MessageSource进行国际化 ApplicationContext接口扩展了一个名为MessageSource的接口因此提供了国际化(“i18n”)功能用于支持信息的国际化和包含参数的信息的替换。 Spring的各种MessageSource实现遵循与标准JDK ResourceBundle相同的语言环境解析和回退规则。 定义两个配置文件语言类别简称结尾。 messages_en.properties spring.msghello,{0}messages_zh.properties spring.msg你好,{0}通过调用MessageSource.getMessage()方法解析示例代码如下 Configuration public class Config {Beanpublic ResourceBundleMessageSource messageSource(){ResourceBundleMessageSource resourceBundleMessageSource new ResourceBundleMessageSource();//指定beannameresourceBundleMessageSource.setBasenames(i18n/messages);//设置字符编码resourceBundleMessageSource.setDefaultEncoding(utf-8);return resourceBundleMessageSource;} } Component public class A{Autowiredprivate MessageSource messageSource;public void test(){String message messageSource.getMessage(spring.msg, new Object[]{world},default, Locale.ENGLISH);System.out.println(message);message messageSource.getMessage(spring.msg, new Object[]{world},default, Locale.CHINESE);System.out.println(message);}public static void main(String[] args) {ApplicationContext applicationContext new AnnotationConfigApplicationContext(com.example);A bean applicationContext.getBean(A.class);bean.test();/** Output:* hello,world* 你好,world*/} }以xml方式创建bean beansbean idmessageSourceclassorg.springframework.context.support.ResourceBundleMessageSourceproperty namebasenameslistvaluemessages_en/valuevaluemessages_zh/value/list/property/bean /beansSpring提供了三个MessageSource实现方式ResourceBundleMessageSource、ReloadableResourceBundleMessageSourc和StaticMessageSource。 标准和自定义事件 ApplicationContext中的事件处理是通过ApplicationEvent类和ApplicationListener接口提供的。如果将实现ApplicationListener接口的bean部署到上下文中那么每当ApplicationEvent发布到ApplicationContext时就会通知该bean。本质上这是标准的观察者设计模式。 Spring提供的标准事件ContextRefreshedEvent、ContextStartedEvent、ContextStoppedEvent、ContextClosedEvent、RequestHandledEvent、ServletRequestHandledEvent您还可以创建和发布自己的自定义事件。 假设创建一个发送通知的功能首先创建事件类继承ApplicationEvent抽象类 public class MyEvent extends ApplicationEvent {public String message;public MyEvent(Object source, String message) {super(source);this.message message;System.out.println(创建MyEvent);} }创建一个发布事件类实现ApplicationEventPublisherAware 接口 public class NotifyService implements ApplicationEventPublisherAware {private ApplicationEventPublisher publisher;public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {publisher applicationEventPublisher;}public void sendMessage(String message){publisher.publishEvent(new MyEvent(this,message));} }容器自动调用setApplicationEventPublisher()。实际上传入的参数是Spring容器本身。 注册bean beansbean idnotifyService classcom.example.NotifyService/bean /beans创建监听类接收自定义ApplicationEvent类可以实现ApplicationListener接口为了更直观观测创建两个监听类 public class Zhangsan implements ApplicationListenerMyEvent {public void onApplicationEvent(MyEvent event) {System.out.println(zhangsan收到消息event.message);} } public class Lisi implements ApplicationListenerMyEvent {public void onApplicationEvent(MyEvent event) {System.out.println(lisi收到消息event.message);} }注册bean beansbean idzhangsan classcom.example.Zhangsan/beanbean idlisi classcom.example.Lisi/bean /beansApplicationListener指定事件类型onApplicationEvent()方法可以保持类型安全避免任何向下转换的需要。您可以注册任意数量的事件监听器但是请注意默认情况下事件侦听器同步接收事件。 执行结果如下所示 public class Test{public static void main(String[] args) {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);NotifyService bean applicationContext.getBean(NotifyService.class);bean.sendMessage(hello world);/** Output:* 创建MyEvent* zhangsan收到消息hello world* lisi收到消息hello world*/} }你也可以使用EventListener注解在bean的任意方法上注册事件侦听器 Component public class NotifyService {Autowiredprivate ApplicationEventPublisher publisher;public void sendMessage(String message){publisher.publishEvent(new MyEvent(this,message));} } Component public class Lisi {EventListenerpublic void onApplicationEvent(MyEvent event) {System.out.println(lisi收到消息event.message);} } Component public class Zhangsan {EventListenerpublic void onApplicationEvent(MyEvent event) {System.out.println(zhangsan收到消息event.message);} }EventListener注解也可以监听多个事件: Component public class Lisi {EventListener({MyEvent.class, MyEvent2.class})public void onApplicationEvent(Object event) {System.out.println(event);} }异步侦听器 假设方法B调用方法A你希望方法B不需要等待方法A执行完成而是继续往下执行可以使用Async注解。 创建任务执行器防止报异常EnableAsync启用异步注解 Configuration EnableAsync public class Config {Beanpublic AsyncTaskExecutor asyncTaskExecutor(){ThreadPoolTaskExecutor asyncTaskExecutor new ThreadPoolTaskExecutor();asyncTaskExecutor.setCorePoolSize(10);asyncTaskExecutor.setMaxPoolSize(10);asyncTaskExecutor.initialize();return asyncTaskExecutor;} }指定异步注解方法 Component public class A{Asyncpublic void a(){System.out.println(thread:Thread.currentThread().getName());try {Thread.sleep(20000);} catch (InterruptedException e) {e.printStackTrace();}} }需要注意Async注解对同一个类中的方法和static方法无效不能通过返回值来进行后续操作。如果引发Exception不会传播到调用方。 测试注解是否生效 Component public class B {AutowiredA a;public void test() {System.out.println(before);this.a.a();System.out.println(after);}public static void main(String[] args) {ApplicationContext applicationContext new AnnotationConfigApplicationContext(com.example);B bean applicationContext.getBean(B.class);bean.test();/** Output:* before* after* thread:asyncTaskExecutor-1*/} }本章内容主要介绍了Spring IoC 容器与Bean之间的关系及基本使用。
http://www.sczhlp.com/news/179970/

相关文章:

  • 网页设计与网站建设课后习题答案wordpress related
  • 淘客手机端网站建设做家教网站赚钱么
  • 仿牌网站安全推广普通话的故事
  • 网站建设硬件需求视频推广计划
  • 建设环境竣工验收网站企业自建站
  • 校园网站建设必要性网站谁做的比较好看的
  • 手机商城网站建设拉新接单网
  • 网站排名seo培训久久建设集团有限公司
  • 中山网站建设文化效果嘉兴服饰网站建设
  • 平面设计可以做网站wordpress 获取用户名
  • 网站备案需要资料flash属于网页制作平台吗
  • 巴南市政建设网站成年男女做羞羞视频网站
  • discuz网站名称舟山网站设计
  • 环球资源网的优势珠海做网站优化
  • 长沙网站开发培训建设网站如何索要素材
  • 天津深圳网站开发定制小说一键生成动漫
  • 做一个网站可以卖东西嘛兰州道路建设情况网站
  • 骄傲 孔雀羽翎上的暗槽 从最肮脏裂缝开凿 被爱意和现实击倒 停止创造
  • 10.9 CSP-S模拟28 改题记录
  • 所以相信我初登场 不会让任何人失望 无论地位不管成败 全都逃不出神的覆掌
  • 被彼此笼罩 任歌声将我们缠绕 立下誓言后再自嘲 重复仲夏夜的舞蹈 吞下这毒药
  • 朝圣显像 不及那人将门扉轻轻叩响 欢迎来到我的城市 嗅玫瑰绽放
  • 做网站投诉要钱吗上海网站建设方案托管
  • 企业电子商务网站的建设方式专业网站建设价格
  • 为什么大型网站都用php网站建设推广有用吗
  • 怎么做网站前台龙华、宝安最新通告
  • 网站做的关键词被屏蔽网站建设业务员主动话术
  • 龙岩任做网站的哪几个比较好wordpress 活动报名
  • 广东省住房和城乡建设厅网站进不去营销类网站有哪些
  • 惠州网站建设 翻译6zhi做网站