j2ee
第二章
快捷键
sout
psvm
bean :alt+insert
ctrl+o:创建无参的构造函数
iter :生成增强for循环
ctrl+alt+t:选中要执行异常处理的代码段,执行快捷键弹出选项
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dEc2E6TH-1586743224653)(…/image/捕获.PNG)]
使用配置类
- 组件扫描
- @Component:表示这个类需在应用程序中被创建
- @ComponentScan:自动发现应用程序中创建的类
- 自动装配
- @Autowired:自动满足bean之间的依赖
- 定义配置类
- @Configuration:表示当前类是一个配置类
e.g:
@Configuration
@ComponentScan
public class AppConfig {
}
e.g:
ApplicationContext context=new AnnotationConfigApplicationContext(AppConfig.class);
CDPlayer player=context.getBean(CDPlayer.class);
使用junit4单元测试
public class AppTest {
@Test
public void textplay()
{
ApplicationContext context=new AnnotationConfigApplicationContext(AppConfig.class);
CDPlayer player=context.getBean(CDPlayer.class);
player.play();
}
}
-
引入Spring 单元测试模块
- Maven:junit、spring-test
- @Runwith(SpringJUnit4ClassRunner.class)
-
加载配置类
- @ContextConfiguration(classes=AppConfig.class)
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes =AppConfig.class)
public class AppTest {
@Autowired
private CDPlayer player;
@Test
public void textplay()
{
// ApplicationContext context=new AnnotationConfigApplicationContext(AppConfig.class);
// CDPlayer player=context.getBean(CDPlayer.class);
player.play();
}
}
@Autowired的应用场景
- 用在构造函数上
- 多个依赖的情况
- 用在成员变量上
- 用在setter方法上
- 用在任意方法上
required属性
- @Autowired(required=false)
- 表示注入的对象是可选的
e.g:
@Autowired(required = false)
private CompactDisc cd;
@Autowired
private Power power;
e.g:
//@Component
public class CompactDisc {
public CompactDisc() {
super();
System.out.println("CompactDisc无参构造函数");
}
public void play()
{
System.out.println("正在播放音乐.....");
}
}
使用接口
处理自动装配的歧义性
- 首选bean
- 再声明类的时候使用@Primary
- 只能定义一个@Primary
- 使用限定符
- 在声明的时候和装配的时候分别使用@Qualifier
- 使用限定符和bean id
- 在声明的时候指定bean的id(默认的id是首写字母小写的类名)
- 在装配的时候使用@Qualifier
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IoRNP5Uk-1586743224656)(…/image/捕获1.png)]
组件扫描的基础包(配置类)
3种方式
@Configuration
//@ComponentScan("com.qfedu.demo")
//@ComponentScan(basePackages ={"com.qfedu.demo.web","com.qfedu.demo.service","com.qfedu.demo.dao"})
@ComponentScan(basePackageClasses = {UserController.class, UserService.class, UserDao.class})
public class AppConfig {
}
- @ComponentScan(“com.qfedu.demo”)
- @ComponentScan(basePackages ={“com.qfedu.demo.web”,“com.qfedu.demo.service”,“com.qfedu.demo.dao”})
- @ComponentScan(basePackageClasses = {UserController.class, UserService.class, UserDao.class})
注:AppConfig配置类文件一般放在一个包名为config下。
xml启动组件扫描(xml文件)
-
这里的applicationContext.xml文件替代了上面的配置类,通过
<context:component-scan base-package=“包名”/>的格式配置
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--<context:component-scan base-package="com.qfedu.demo"/>-->
<context:component-scan base-package="com.qfedu.demo.service"/>
<context:component-scan base-package="com.qfedu.demo.dao"/>
<context:component-scan base-package="com.qfedu.demo.web"/>
</beans>
- 测试类修改如下:
@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration(classes = AppConfig.class)
//修改如下
@ContextConfiguration("classpath:applicationContext.xml")
public class UserControllerTest {
@Autowired
private UserController userController;
@Test
public void testAdd()
{
userController.add();
}
}
总结
-
定义配置
- @Configuration
- @ComponentScan
-
定义组件
- @Conponent
- @Autowired
- @Autowired(required=false)
-
自动装配歧义性
- @Primary (spring提供)
- @Qualifier (spring提供)
- @Resource (jdk提供)
-
分层架构中定义组件
- @Controller
- @Service
- @Repository
-
Spring测试环境
- @RunWith
- @ContextConfiguration
-
使用xml启动组件扫描
- <context:component-scan base-package="…"/>
第三章
在用到第三方库的组件装配到应用程序中,没办法通过类上添加
@Component和@Autowired等注解来自动装配
只能显示装配(通过编程的方式进行依赖注入即手动装配)
解释:
- 就是类上不加上**@Component和@Autowired**,配置类上只保留**@Configuration**,不保留**@ComponentScan**,配置类内通过声明@Bean的方法来完成自动装配。
- 该方式的自动装配与前面的自动装配歧义性一样采用相同的方法
总结
- JavaConfig
- @Configuration
- @Bean
- 依赖注入
- 构造函数
- setter
- 任意方法
- 装配过程的歧义性
第四章 xml装配bean
name和id属性
-
name和id属性的作用是一样的,但有区别
-
name可取多个别名比如name=“c1 c2”,而id="c1 c2"就不行
通过构造函数依赖注入(构造方法)
- 元素
<bean id="compactDisc1" class="com.qfedu.demo.soundsystem.CompactDisc"></bean>
<bean id="cdPlayer1" class="com.qfedu.demo.soundsystem.CDPlayer">
<constructor-arg ref="compactDisc1"/>
通过c名称空间依赖注入
- c- 名称空间
- 引入命名空间,在
xmlns:c="http://www.springframework.org/schema/c"
<bean id="cdPlayer2" class="com.qfedu.demo.soundsystem.CDPlayer" c:cd-ref="compactDisc2">
<!-- cd为构造函数中的参数名 -->
</bean>
<bean id="cdPlayer3" class="com.qfedu.demo.soundsystem.CDPlayer" c:_0-ref="compactDisc2">
<!--_0表示第一个参数,以此类推 -->
</bean>
注入简单类型
-
第一种(name可选,最常用)
public class CompactDisc { private String title; private String artist; }
<bean id="compactDisc1" class="com.qfedu.demo.soundsystem.CompactDisc">
<constructor-arg name="title" value="I Do"/>
<constructor-arg name="artist" value="莫文蔚"/>
</bean>
- 第二种(index)
<bean id="compactDisc1" class="com.qfedu.demo.soundsystem.CompactDisc">
<constructor-arg index="0" value="I Do"/>
<constructor-arg index="1" value="莫文蔚"/>
</bean> <!--0代表第一个变量-->
- 第三种(type)
<bean id="compactDisc1" class="com.qfedu.demo.soundsystem.CompactDisc">
<constructor-arg type="java.lang.String" value="I Do"/>
<constructor-arg type="java.lang.String" value="莫文蔚"/>
</bean><!-- type相同的话,按简单变量定义的顺序对应,相当于第四种-->
- 第四种(只写value)
<bean id="compactDisc1" class="com.qfedu.demo.soundsystem.CompactDisc">
<constructor-arg value="I Do"/>
<constructor-arg value="莫文蔚"/>
- 第五种(通过c名称空间)
<bean id="compactDisc2" class="com.qfedu.demo.soundsystem.CompactDisc" c:title="周杰伦的床边故事"
c:artist="周杰伦"></bean>
注入list类型
- 基本类型(如String)
public class CompactDisc {
private String title;
private String artist;
private List<String> tracks;//添加list
}
<bean id="compactDisc1" class="com.qfedu.demo.soundsystem.CompactDisc">
<constructor-arg type="java.lang.String" value="I Do"/>
<constructor-arg type="java.lang.String" value="莫文蔚"/>
<constructor-arg name="tracks">
<list>
<value>I Do 1</value>
<value>I Do 2</value>
<value>I Do 3</value>
</list>
</constructor-arg>
</bean>
2引用类型 (自定义类型)
public class Music {
private String title;
private Integer duration;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Integer getDuration() {
return duration;
}
public void setDuration(Integer duration) {
this.duration = duration;
}
public Music() {
super();
}
public Music(String title, Integer duration) {
this.title = title;
this.duration = duration;
}
}
<bean id="music1" class="com.qfedu.demo.soundsystem.Music">
<constructor-arg value="I Do 1"/>
<constructor-arg value="270"/>
</bean>
<bean id="music2" class="com.qfedu.demo.soundsystem.Music">
<constructor-arg value="I Do 2"/>
<constructor-arg value="270"/>
</bean>
<bean id="music3" class="com.qfedu.demo.soundsystem.Music">
<constructor-arg value="I Do 3"/>
<constructor-arg value="270"/>
</bean>
<bean id="compactDisc1" class="com.qfedu.demo.soundsystem.CompactDisc">
<constructor-arg type="java.lang.String" value="I Do"/>
<constructor-arg type="java.lang.String" value="莫文蔚"/>
<constructor-arg name="tracks">
<list>
<!--<value>I Do 1</value>-->
<!--<value>I Do 2</value>-->
<!--<value>I Do 3</value>-->
<ref bean="music1"/>
<ref bean="music2"/>
<ref bean="music3"/>
</list>
</constructor-arg>
</bean>
注入Set
LinkedHashSet(类似如上list)
注:使用c名称空间不能对集合装配
注入map类型
private Map<String,Music> tracks;
<map>
<!--<entry key="m1" value="I Do 1"/>-->
<entry key="m1" value-ref="music1"/>
<entry key="m2" value-ref="music2"/>
<entry key="m3" value-ref="music3"/>
</map>
注入数组
类似注入list
private Music[] tracks;
<array>
<!--<value>I DO</value>--> <!--普通类型-->
<ref bean="music1"/>
<ref bean="music2"/>
<ref bean="music3"/> <!-- 引用类型 -->
</array>
通过属性依赖注入(set方法)
<bean id="music2" class="com.qfedu.demo.soundsystem.Music">
<property name="title1" value="爱情废柴"/>
<property name="duration" value="305"/>
</bean>
private String title;
private Integer duration;
public String getTitle() {
return title;
}
public void setTitle1(String title) {
this.title = title;
}
注:以上的属性是指title1,即setTitle1方法的‘title1’,不是指向私有变量title,就是说name=""取决于set方法。
注入列表/数组属性
与构造方式的类似,见构造函数依赖的注入list类型。
注入对象引用
<bean id="CDPlayer1" class="com.qfedu.demo.soundsystem.CDPlayer"> <property name="cd" ref="conpactDisc1"/>
</bean>
通过p名称空间依赖注入
- p- 名称空间
- 引入命名空间,在
xmlns:p="http://www.springframework.org/schema/p"
通过util名称空间注入
- util- 名称空间
- 引入命名空间和schemaLocation(增加网址)
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<bean id="compactDisc1" class="com.qfedu.demo.soundsystem.CompactDisc"
p:title="周杰伦的床边故事"
p:artist="周杰伦"
p:tracks-ref="trackList">
<!--<property name="title" value="周杰伦的床边故事"/>-->
<!--<property name="artist" value="周杰伦"/>--> <!--<property name="tracks">-->
<!--<array>-->
<!--<ref bean="music1"/>-->
<!--<ref bean="music2"/>-->
<!--</array>-->
<!--</property>-->
</bean>
<util:list id="trackList">
<ref bean="music1"/>
<ref bean="music2"/>
</util:list>
<util:set></util:set><!--适用-->
<util:map></util:map><!--适用-->
第五章
Spring中的单例bean
/**
* (1)无论我们是否主动获取或注入bean对象,Spring对象上下文一加载就会创建bean对象
* (2)无论获取多少次,拿到的都是同一个对象
*/
bean的作用域
- 单例(Sinleton)
- 在整个应用程序中,只创建bean的一个实例
- 原型(Prototype)
- 每次注入或通过Spring上下文获取的时候,都会创建一个新的bean实例
- 会话(Session)(搭建web应用程序)
- 在Web应用中,为每一个会话创建一个bean实例
- 请求(request)(搭建web应用程序)
- 在Web应用中,为每一个请求创建一个bean实例
/**
* scope="singleton"
* (1)无论我们是否主动获取或注入bean对象,Spring对象上下文一加载就会创建bean对象
* (2)无论获取多少次,拿到的都是同一个对象
*
*
* scope="prototype"
* (1)Spring上下文加载的时候不会创建bean对象
* (2)每次获取或注入,都会拿到不同的bean对象
*/
<bean id="notepad" class="com.qfedu.demo.Notepad" scope="prototype"></bean>
自动装配中定义bean作用域
- 需要在配置文件中添加
<context:component-scan basepackage="com.qfedu.demo"/>
- 添加@Scope(4种方式)
@Component
//@Scope("singleton")
//@Scope("prototype")
//@Scope(scopeName="prototype")
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class Notepad2 {
public Notepad2() {
super();
System.out.println("Notepad2的构造函数。。。。"+this.toString());
}
}
javaconfig装配中定义bean
@Configurationpublic
class AppConfig {
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public Notepad3 notepad3()
{
return new Notepad3();
}
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=AppConfig.class)//javaconfig
public class NotepadTest3 {
@Autowired
private Notepad3 notepad1;
@Autowired
private Notepad3 notepad2;
@Test
public void test01()
{
System.out.println(notepad1==notepad2);
}
}
延迟加载/按需加载
<bean id="notepad" class="com.qfedu.demo.Notepad" scope="singleton" lazy-init="true"></bean>
@Component
@Scope("singleton")
//@Scope("prototype")
//@Scope(scopeName = "prototype")
//@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Lazy//自动装配时使用
public class Notepad2 {
public Notepad2() {
super();
System.out.println("Notepad2的构造函数。。。。"+this.toString());
}
}
- lazy-init="true"程序需要对象时加载
- 延迟加载只与singoleton才有效
@Configuration
public class AppConfig {
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
@Lazy
public Notepad3 notepad3()
{
return new Notepad3();
}
}
bean对象的初始化和销毁
- 获取方式装配
public void test01()
{
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
Notepad notepad1=(Notepad) context.getBean("notepad");
// Notepad notepad2=(Notepad)context.getBean("notepad");
// System.out.println(notepad1==notepad2);
//context.destroy();
context.close();//关闭容器,自动调用销毁
}
<bean id="notepad" class="com.qfedu.demo.Notepad" scope="singleton"
lazy-init="true"
destroy-method="destroy"
init-method="init"></bean>
- 自动装配
@Component
@Scope("singleton")
//@Scope("prototype")
//@Scope(scopeName = "prototype")
//@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Lazy
public class Notepad2 {
public Notepad2() {
super();
System.out.println("Notepad2的构造函数。。。。"+this.toString());
}
@PostConstruct
public void init()
{
System.out.println("Notepad的初始化方法");
}
@PreDestroy
public void destroy() {
System.out.println("Notepad的销毁方法");
}
}
- javaconfig
public class Notepad3 {
public Notepad3() {
super();
System.out.println("Notepad3的构造函数。。。。"+this.toString());
}
@PostConstruct
public void init()
{
System.out.println("Notepad的初始化方法");
}
@PreDestroy
public void destroy() {
System.out.println("Notepad的销毁方法");
}
}
工厂方法创建bean对象
<!--静态工厂工厂-->
<bean id="person1"class="com.qfedu.demo.PersonFactory"factory-method="createPersonl"/>
<!--实例工厂-->
<bean id="personFactory"
class="com.qfedu.demo.PersonFactory"/>
<bean id="person2"
factory-bean="personPactory"
factory-method="createPerson2"/>
public class PersonFactory{
//静态工厂方法
public static Person createPersonl(){
System.out.println("静态工厂创建Person..…");
return new Person();
}
//动态工厂方法
public Person createPerson2(){
System.out.println("实例工厂创建Person...");
return new Person
}
}
总结
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AZzcqSsR-1586743224658)(…/image/捕获2.PNG)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-muIPu8ax-1586743224658)(…/image/捕获3.PNG)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lJsPOMfz-1586743224660)(…/image/捕获4.PNG)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y4v6pVQk-1586743224661)(…/image/捕获5.PNG)]
方法");
}
}
## 工厂方法创建bean对象
~~~xml
<!--静态工厂工厂-->
<bean id="person1"class="com.qfedu.demo.PersonFactory"factory-method="createPersonl"/>
<!--实例工厂-->
<bean id="personFactory"
class="com.qfedu.demo.PersonFactory"/>
<bean id="person2"
factory-bean="personPactory"
factory-method="createPerson2"/>
public class PersonFactory{
//静态工厂方法
public static Person createPersonl(){
System.out.println("静态工厂创建Person..…");
return new Person();
}
//动态工厂方法
public Person createPerson2(){
System.out.println("实例工厂创建Person...");
return new Person
}
}
总结
[外链图片转存中…(img-AZzcqSsR-1586743224658)]
[外链图片转存中…(img-muIPu8ax-1586743224658)]
[外链图片转存中…(img-lJsPOMfz-1586743224660)]
[外链图片转存中…(img-y4v6pVQk-1586743224661)]