spring容器

spring容器
BeanFactory容器
new XmlBeanFactory(new ClassPathResource("Beans.xml"));
ApplicationContext容器,包括BeanFactory
FileSystemXmlApplicationContext:该容器从 XML 文件中加载已被定义的 bean。在这里,你需要提供给构造器 XML 文件的完整路径。
new FileSystemXmlApplicationContext("C:/Users/ZARA/workspace/HelloSpring/src/Beans.xml");
ClassPathXmlApplicationContext:该容器从 XML 文件中加载已被定义的 bean。在这里,你不需要提供 XML 文件的完整路径,只需正确配置 CLASSPATH 环境变量即可,因为,容器会从 CLASSPATH 中搜索 bean 配置文件。
WebXmlApplicationContext:该容器会在一个 web 应用程序的范围内加载在 XML 文件中已被定义的 bean。
Spring Bean定义
定义方式:
基于 XML 的配置文件 Beans.xml
xmlns:

属性 描述
class 这个属性是强制性的,并且指定用来创建 bean 的 bean 类。
name 这个属性指定唯一的 bean 标识符。在基于 XML 的配置元数据中,你可以使用 ID 和/或 name 属性来指定 bean 标识符。
scope 这个属性指定由特定的 bean 定义创建的对象的作用域,它将会在 bean 作用域的章节中进行讨论。
constructor-arg 它是用来注入依赖关系的,并会在接下来的章节中进行讨论。
properties 它是用来注入依赖关系的,并会在接下来的章节中进行讨论。
autowiring mode 它是用来注入依赖关系的,并会在接下来的章节中进行讨论。
lazy-initialization mode 延迟初始化的 bean 告诉 IoC 容器在它第一次被请求时,而不是在启动时去创建一个 bean 实例。
initialization 方法 在 bean 的所有必需的属性被容器设置之后,调用回调方法。它将会在 bean 的生命周期章节中进行讨论。
destruction 方法 当包含该 bean 的容器被销毁时,使用回调方法。它将会在 bean 的生命周期章节中进行讨论。
基于注解的配置
基于 Java 的配置(这个不知道怎么弄的)
spring Bean 作用域:
作用域 描述
singleton 在spring IoC容器仅存在一个Bean实例,Bean以单例方式存在,默认值
prototype 每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时,相当于执行newXxxBean()
request 每次HTTP请求都会创建一个新的Bean,该作用域仅适用于WebApplicationContext环境
session 同一个HTTP Session共享一个Bean,不同Session使用不同的Bean,仅适用于WebApplicationContext环境
global-session 一般用于Portlet应用环境,该运用域仅适用于WebApplicationContext环境
Spring Bean 生命周期:
Bean的定义——Bean的初始化——Bean的使用——Bean的销毁
<bean id="helloWorld"
class="com.tutorialspoint.HelloWorld"
init-method="init" destroy-method="destroy">
<property name="message" value="Hello World!"/>
</bean>
默认的初始化方法:
在<beans xlms...中添加
default-init-method="init"
default-destroy-method="destroy"

Spring Bean 后置处理
1、实现java类继承BeanPostProcessor
1) postProcessBeforeInitialization 初始化函数之前的处理
2) postProcessAfterInitialization 初始化函数之后的处理
2、在Beans.xml中注册类
<bean class="com.tutorialspoint.InitHelloWorld" />

Spring 定义继承:
在<bean>定义parent,在<property>中新增字段为重写或者新增字段
<bean id="helloIndia" class="com.tutorialspoint.HelloIndia" parent="beanTeamplate">
<property name="message1" value="Hello India!"/>
<property name="message3" value="Namaste India!"/>
</bean>
如在<bean>中添加abstract = "true" 就不可以实例化父类bean,只能作为模板被后代继承


Spring 依赖注入
基于构造函数,且构造函数有参数
public class Foo {
public Foo(Bar bar, Baz baz) {
// ...
}
}
<beans>
<bean id="foo" class="x.y.Foo">
<constructor-arg ref="bar"/>
<constructor-arg ref="baz"/>
</bean>

<bean id="bar" class="x.y.Bar"/>
<bean id="baz" class="x.y.Baz"/>
</beans>

在bean中可以加type="int等简单类型",也可以加index告诉构造函数,这是第几个参数,0表示第一个参数,
基于构造函数无参数
<bean id="textEditor" class="com.tutorialspoint.TextEditor">
<property name="spellChecker" ref="spellChecker"/>
</bean>
使用p-namespace实现XML:
<!-- 1、普通青年 -->
<bean id="order" class="twm.spring.start.Order">
<property name="customer.name" value="陈先生" />
<property name="customer.address" value="深圳南山区" />
<property name="orderno" value="201799777799"></property>
<property name="notifyservice" ref="notify2"></property>
</bean>
<!-- 2、文艺青年 -->
<bean id="order2" class="twm.spring.start.Order" p:customer.name="陈先生123"
p:customer.address="深圳南山区123" p:orderno="201799777799"
p:notifyservice-ref="notify" />
name-value的直接写p:name=value ref的就写p:name-ref=refvalue
还有一个c-namespace实现xml
注入内部bean
<bean id="outerBean" class="...">
<property name="target">
<bean id="innerBean" class="..."/>
</property>
</bean>
在new applicationcontext的时候就已经实例化innerBean,然后outerBean了
注入集合:
元素 描述
<list> 它有助于连线,如注入一列值,允许重复。
<set> 它有助于连线一组值,但不能重复。
<map> 它可以用来注入名称-值对的集合,其中名称和值可以是任何类型。
<props> 它可以用来注入名称-值对的集合,其中名称和值都是字符串类型。
<bean id="javaCollection" class="com.tutorialspoint.JavaCollection">

<!-- results in a setAddressList(java.util.List) call -->
<property name="addressList">
<list>
<value>INDIA</value>
<value>Pakistan</value>
<value>USA</value>
<value>USA</value>
</list>
</property>

<!-- results in a setAddressSet(java.util.Set) call -->
<property name="addressSet">
<set>
<value>INDIA</value>
<value>Pakistan</value>
<value>USA</value>
<value>USA</value>
</set>
</property>

<!-- results in a setAddressMap(java.util.Map) call -->
<property name="addressMap">
<map>
<entry key="1" value="INDIA"/>
<entry key="2" value="Pakistan"/>
<entry key="3" value="USA"/>
<entry key="4" value="USA"/>
</map>
</property>

<!-- results in a setAddressProp(java.util.Properties) call -->
<property name="addressProp">
<props>
<prop key="one">INDIA</prop>
<prop key="two">Pakistan</prop>
<prop key="three">USA</prop>
<prop key="four">USA</prop>
</props>
</property>

</bean>
Spring自动装配
自动装配模式:
模式 描述
no 这是默认的设置,它意味着没有自动装配,你应该使用显式的bean引用来连线。你不用为了连线做特殊的事。在依赖注入章节你已经看到这个了。
byName 由属性名自动装配。Spring 容器看到在 XML 配置文件中 bean 的自动装配的属性设置为 byName。然后尝试匹配,并且将它的属性与在配置文件中被定义为相同名称的 beans 的属性进行连接。
byType 由属性数据类型自动装配。Spring 容器看到在 XML 配置文件中 bean 的自动装配的属性设置为 byType。然后如果它的类型匹配配置文件中的一个确切的 bean 名称,它将尝试匹配和连接属性的类型。如果存在不止一个这样的 bean,则一个致命的异常将会被抛出。
constructor 类似于 byType,但该类型适用于构造函数参数类型。如果在容器中没有一个构造函数参数类型的 bean,则一个致命错误将会发生。
autodetect Spring首先尝试通过 constructor 使用自动装配来连接,如果它不执行,Spring 尝试通过 byType 来自动装配。
ByName:
它尝试将它的属性与配置文件中定义为相同名称的 beans 进行匹配和连接。如果找到匹配项,它将注入这些 beans,否则,它将抛出异常。
<!-- Definition for textEditor bean -->
<bean id="textEditor" class="com.tutorialspoint.TextEditor"
autowire="byName">
<property name="name" value="Generic Text Editor" />
</bean>

<!-- Definition for spellChecker bean -->
<bean id="spellChecker" class="com.tutorialspoint.SpellChecker">
</bean>
ByType:
如果它的 type 恰好与配置文件中 beans 名称中的一个相匹配,它将尝试匹配和连接它的属性。如果找到匹配项,它将注入这些 beans,否则,它将抛出异常。
代码同上:
constructor:
它尝试把它的构造函数的参数与配置文件中 beans 名称中的一个进行匹配和连线。如果找到匹配项,它会注入这些 bean,否则,它会抛出异常。
Spring 注解:
在配置中添加:<context:annotation-config/>
@Required:
@Required 注释应用于 bean 属性的 setter 方法,它表明受影响的 bean 属性在配置时必须放在 XML 配置文件中,否则容器就会抛出一个 BeanInitializationException 异常
还必须在配置中写上:
<bean id="student" class="com.tutorialspoint.Student">
<property name="name" value="Zara" />
<property name="age" value="11"/>
</bean>
@Autowired 注释:
Setter 方法中的 @Autowired:
当 Spring遇到一个在 setter 方法中使用的 @Autowired 注释,它会在方法中视图执行 byType 自动连接。
@Autowired
public void setSpellChecker( SpellChecker spellChecker ){
属性中的 @Autowired:
不用写这个属性的setter方法了
属性中使用 @Autowired 注释来除去 setter 方法。当时使用 为自动连接属性传递的时候,Spring 会将这些传递过来的值或者引用自动分配给那些属性
@Autowired
private SpellChecker spellChecker;
构造函数中的 @Autowired:
即使在 XML 文件中没有使用 元素配置 bean ,构造函数也会被自动连接。
@Autowired
public TextEditor(SpellChecker spellChecker){
@Autowired 的(required=false)选项:
默认情况下,@Autowired 注释意味着依赖是必须的,它类似于 @Required 注释,然而,你可以使用 @Autowired 的 (required=false) 选项关闭默认行为。
@Autowired(required=false)
public void setAge(Integer age) {
@Qualifier 注释:
可能会有这样一种情况,当你创建多个具有相同类型的 bean 时,并且想要用一个属性只为它们其中的一个进行装配,
在这种情况下,你可以使用 @Qualifier 注释和 @Autowired 注释通过指定哪一个真正的 bean 将会被装配来消除混乱。
@Autowired
@Qualifier("student1")
private Student student;
Spring JSR-250 注释:
@PostConstruct 和 @PreDestroy 注释:
为了定义一个 bean 的安装和卸载,我们使用 init-method 和/或 destroy-method 参数简单的声明一下 。init-method 属性指定了一个方法,该方法在 bean 的实例化阶段会立即被调用。同样地,destroy-method 指定了一个方法,该方法只在一个 bean 从容器中删除之前被调用。
你可以使用 @PostConstruct 注释作为初始化回调函数的一个替代,@PreDestroy 注释作为销毁回调函数的一个替代,其解释如下示例所示。
PostConstruct在构造函数之后执行,init()方法之前执行。PreDestroy()方法在destroy()方法执行执行之后执行,
@Resource 注释:
如果没有指定name属性,当注解写在字段上时,默认取字段名进行按照名称查找,如果注解写在setter方法上默认取属性名进行装配。 当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。
@Resource(name= "spellChecker")
public void setSpellChecker( SpellChecker spellChecker ){
基于 Java 的配置:
@Configuration 和 @Bean 注解
@Configuration用于类,表明这个类是beans定义的源。
@Bean只能用于注解方法和注解的定义。
@Configuration
public class AppConfig {
@Bean
public MyService myService() {
相当于在 XML 文件中配置:
<beans>
<bean id="myService" class="com.acme.services.MyServiceImpl"/>
</beans>
注入 Bean 的依赖性
@Bean
public Foo foo() {
return new Foo(bar());
}
@Bean
public Bar bar() {
return new Bar();
}
@Import 注解:
@import 注解允许从另一个配置类中加载 @Bean 定义
@Configuration
public class ConfigA {
@Bean
public A a() {
return new A();
}
}
你可以在另一个 Bean 声明中导入上述 Bean 声明,如下所示:
@Configuration
@Import(ConfigA.class)
public class ConfigB {
@Bean
public B a() {
return new A();
}
}
生命周期回调:
@Configuration
public class AppConfig {
@Bean(initMethod = "init", destroyMethod = "cleanup" )
事件处理:
Spring 内置事件 & 描述
ContextRefreshedEvent ApplicationContext 被初始化或刷新时,该事件被发布。这也可以在 ConfigurableApplicationContext 接口中使用 refresh() 方法来发生。
ContextStartedEvent 当使用 ConfigurableApplicationContext 接口中的 start() 方法启动 ApplicationContext 时,该事件被发布。你可以调查你的数据库,或者你可以在接受到这个事件后重启任何停止的应用程序。
ContextStoppedEvent 当使用 ConfigurableApplicationContext 接口中的 stop() 方法停止 ApplicationContext 时,发布这个事件。你可以在接受到这个事件后做必要的清理的工作。
ContextClosedEvent 当使用 ConfigurableApplicationContext 接口中的 close() 方法关闭 ApplicationContext 时,该事件被发布。一个已关闭的上下文到达生命周期末端;它不能被刷新或重启。
RequestHandledEvent 这是一个 web-specific 事件,告诉所有 bean HTTP 请求已经被服务。
监听上下文:
监听类:
package com.tutorialspoint;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextStartedEvent;
public class CStartEventHandler
implements ApplicationListener<ContextStartedEvent>{
public void onApplicationEvent(ContextStartedEvent event) {
System.out.println("ContextStartedEvent Received");
}
}
主函数调用:
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
context.start();
Beans.xml:
<bean id="cStartEventHandler" class="com.tutorialspoint.CStartEventHandler"/>
自定义事件:
定义事件类:
定义事件接听者
....
AOP
术语:
https://blog.csdn.net/changudeng1992/article/details/80625134
通知类型:
通知 描述
前置通知 在一个方法执行之前,执行通知。
后置通知 在一个方法执行之后,不考虑其结果,执行通知。
返回后通知 在一个方法执行之后,只有在方法成功完成时,才能执行通知。
抛出异常后通知 在一个方法执行之后,只有在方法退出抛出异常时,才能执行通知。
环绕通知 在建议方法调用之前和之后,执行通知。
实现自定义方面:
方法 描述
XML Schema based 方面是使用常规类以及基于配置的 XML 来实现的。
@AspectJ based @AspectJ 引用一种声明方面的风格作为带有 Java 5 注释的常规 Java 类注释。
基于AOP的XML架构:
<aop:config>
<aop:aspect id="log" ref="logging">
<aop:pointcut id="selectAll"
expression="execution(* com.tutorialspoint.*.*(..))"/>
<aop:before pointcut-ref="selectAll" method="beforeAdvice"/>
<aop:after pointcut-ref="selectAll" method="afterAdvice"/>
<aop:after-returning pointcut-ref="selectAll"
returning="retVal"
method="afterReturningAdvice"/>
<aop:after-throwing pointcut-ref="selectAll"
throwing="ex"
method="AfterThrowingAdvice"/>
</aop:aspect>
</aop:config>
Spring 中基于 AOP 的 @AspectJ
声明一个 aspect
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class AspectModule {
}
它们将在 XML 中按照如下进行配置,就和其他任何 bean 一样:
<bean id="myAspect" class="org.xyz.AspectModule">
<!-- configure properties of aspect here as normal -->
</bean>
声明一个切入点
import org.aspectj.lang.annotation.Pointcut;
@Pointcut("execution(* com.xyz.myapp.service.*.*(..))") // expression
private void businessService() {} // signature
声明建议:
@Before("businessService()")
public void doBeforeTask(){
...
}
@After("businessService()")
public void doAfterTask(){
...
}
@AfterReturning(pointcut = "businessService()", returning="retVal")
public void doAfterReturnningTask(Object retVal){
// you can intercept retVal here.
...
}
@AfterThrowing(pointcut = "businessService()", throwing="ex")
public void doAfterThrowingTask(Exception ex){
// you can intercept thrown exception here.
...
}
@Around("businessService()")
public void doAroundTask(ProceedingJoinPoint pjp){
this.printLog("已经记录下操作日志@Around 方法执行前");
pjp.proceed();
this.printLog("已经记录下操作日志@Around 方法执行后");
}

posted @ 2019-03-12 09:12  周sir搞人工  阅读(144)  评论(0编辑  收藏  举报