Spring学习第一步 配置环境
spring
spring配置:
-
创建spring工程
-
在pom.xml导入spring依赖和单元测试依赖
-
创建pojo包---> 在里面创建实体类
-
创建applicationContext配置文件 ---->写bean相关的id 和class
id: 唯一标识符
class:bean所对应的类型的具体包名
-
创建测试包test---->Test类
-
获取容器:ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
-
//获取容器的对象bean 注意强制类型转换 直接在前面加上(强制类型转换符)
Helloword helloword =(Helloword) applicationContext.getBean("helloSpring");
-
调用方法
helloword.run();
-
//一共改了几个点//1.setting 里maven 的配置 maven RUN里的编译 //2.POM里的rescouce资源过滤(这个步骤可以没用什么时候target里面没有再加) //3.maven右侧test步骤的禁用,POM里打包方式为jar
-
根据类型来获取bean时,在满足bean唯一性的前提下,其实只是看:『对象instanceof 指定的类型』
的返回结果,只要返回的是true就可以认定为和类型匹配,能够获取到l
1.两种属性赋值的方法:
<!-- 通过set方法注入的方式 -->
<!-- name: 属性-->
<!-- value:属性值-->
<!-- <property name="sex" value="男">
-->
区别在于:
一个是通过sett方法赋值
一个是通过构造方法传参数
属性赋值:
-
字面值:通过value赋值
-
另一个类的类型:
(1) ref="另一个类的 类型的bean的id"
(2)
(1) ref="另一个类的 类型的bean的id"** (用的最多)
(2)二级联动方式:在第一个的基础上
加上<property name=" 属性.属性" value= “属性值">
作用不大 只是修改了原来的属性值
注意:级联的方式,要保证提前为sClass属性赋值或者实例化
<property name="sClass" ref="class">
</property><property name="sClass.classname" value="软件工程"></property>
<property name="sClass.classid" value="1"></property>
另一个类的id
/bean>
<bean id="class" class="pojo.Class">
<property name="classid" value="1"></property>
<property name="classname" value="计算机科学与技术"></property>
<property name="students" ref="student"></property>
</bean>
(3)内部bean的方式
<property name="sClass">
<!-- 出bug:.NosuchBeanDefinitionException:-->
<!-- 原因 这是内部bean 只能在bean 内部使用 不能被IOC 容器获取-->
<bean id="class" class="pojo.Class">
<property name="classid" value="2"></property>
<property name="classname" value="计算机科学与技术"></property>
<property name="students" ref="student">
</property>
</bean>
</property>
给属性对象赋值小结:
用的最多是第一种和第三种方式
-
数组赋值
在property 中添加 array标签 1,字面值就用 value 2.属性对象 用 ref <property name="a"> <array> <value >1</value> <value >1</value> <value >2</value> <value >3</value> <value >4</value> </array> </property>
-
list集合赋值
注意事项:
获取bean无论是通过id还是name获取,如果无法获取到,将抛出异常NoSuchBeanDefinitionExceptionNoSuchBeanDefinitionException: No bean named 'bookServiceImpl' available
属性赋值总结:
-
在bean里面都由
中设置小标签 数组用array
List集合用 list
set 集合用 set
map集合用 entry 小标签 中key =” “ value=”“>
properties 用 pro标签
<bean id="user" class="pojo.User">
<property name="address" value="重庆市"> </property>
<property name="age" value="29"></property>
<property name="classes">
<list>
<null></null>
</list>
</property>
<property name="hobby">
<array>
<value>唱个歌</value>
<value>跳舞</value>
<value>看书</value>
</array>
</property>
<property name="gendes">
<set>
<value>qq</value>
<value>123</value>
</set>
</property>
<property name="maps">
<map>
<entry key="001" value-ref="student"></entry>
</map>
</property>
<property name="properties">
<props>
<prop key="username"> 小王</prop>
<prop key="password">123</prop>
<prop key="url">3306@qq.com</prop>
</props>
</property>
</bean>
</beans>
命名空间注入
p 命名空间注入: 通过属性
c命名空间注入 :通过构造器 const
注意:使用的时候要导入约束
bean作用域
bean作用范围:
默认score 是单例模式
工具类
自动装配:
1.autowire 属性
作用: 为类类型,接口类型赋值 就是省略了bean 标签中ref=" "
就不需要写 简单的< property 是ref=" ">
自动在容器中找到对应的bean类型的对象
bytype: 根据类型 确保class=" 全局唯一" . bytype的时候,需要保证所有bean的class唯一,并且这个bean需要和自动注入的属性的类型一致
byName: 根据bean id 来配置 确保id 唯一 需要保证所有bean的id唯一,并且这个bean需要和自动注入的属性的set方法的值一致
所谓的自动装配就是原来两行代码改成了autowire="byName"
l
<bean id="student" class="com.hqq.pojo.Student" p:sname="王新瑞" p:age="1" >
<property name="cat" ref="cat"></property>
<property name="dog" ref="dog"></property>
</bean>
autowire="byName"
2.标识为组件的
省略了原来
@autowired 通过byType的方式实现
@controller:
括号里面的表示自定义bean标签中 id
@Controller("controller")
public class UserController {
}
小结:
Resource和@ Autowired 的区别:
·都是用来自动装配的,都可以放在属性字段上
。@Autowired 通过byType的方式实现,而且必须要求这个对象存在!【常用】
@Resource默认通过byname的方式实现,如果找不到名字,则通过byType实现!如果两个都找不到的情况下,就报错!【常用】
·执行顺序不同:@Autowired通过byType的方式实现
注解开发
注意:使用注解开发要导入注解的支持:
在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"
记得加入context
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p" xmlns:http="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
这是扫描组件的包 最好写详细点 节约扫描时间
<!--指定要扫描的包,这个包下的注解就会生效-->
<context:component-scan base-package="com.hqq.pojo"></context:component-scan>
<context:annotation-config/>
扫描包
springmvc 负责控制层
spring 扫描全部的层次 就会出现重复扫描的情况
为了避免该情况
出现了
```
exclude-filter: 除了某个文件
type:
annotation 通过注解来进行排除(常用)
expression:需要复制排除注解的全类名
<context:component-scan base-package="com.hqq.pojo">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
基于注解的自动装配
注解加扫描的方式
@Autowired:作用:为beam管理的成员变量赋值:
@Autowired:实现自动装配功能的注解
1,@Autowired注解能够标识的位置(用的最多)
-
α>标识在成员变量上,此时不需要设置成员变量的set方法* b>标识在set方法上
-
标识在为当前成员变量赋值的有参构造上
2、@Autowired注解的原理
默认通过byType的方式,在IOC容器中通过类型匹配某个bean为属性赋值
b>若有多个类型匹配的bean,此时会自动转换为byName的方式实现自动装配的效果即将要赋值的属性的属性名作为bean的id匹配某个bean为属性赋值
*c>若byType和byName的方式都无妨实现自动装配,即IOC容器中有多个类型匹配的bean
且这些bean的id和要赋值的属性的属性名都不一致,此时抛异常:NoUniqueBeanDefinitionExceptiond>此时可以在要赋值的属性上,添加一个注解@QualifierI
*通过该注解的value属性值,指定某个bean的id,将这个bean为属性赋值
自动装配小结
-
对于简单的一些属性赋值 比如字面量 和类类型 接口类型赋值
-
通过扫描加注解的方式 就要记得在 bean 头文化加上
注解 context 相关
记得加入context xmlns:context="http://www.springframework.org/schema/context" http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"> 这是扫描组件的包 最好写详细点 节约扫描时间 <!--指定要扫描的包,这个包下的注解就会生效--> <context:component-scan base-package="com.hqq.pojo"></context:component-scan> <context:annotation-config/>
-
组件相关
@component 设置为组件
@value 成员变量属性赋值
@Autoried 给成员变量属性赋值 类似:ref 作用 通过byType方式
Java配置类
spring boot中用的比较多
设计模式
数据源jdbc.properties
写了jdbc.properties 以后:对比上下两幅图
测试类
三层架构
数据访问层(dao)
业务逻辑层(Service)
界面层(contraller) 大佬指挥别人做事 对外提供访问功能,只需要在测试类中创建界面层的对象
注意:
业务逻辑层的实现类中一定有数据访问层的对象
不管是xml 配置或者是注解配置 交给ioc容器管理的对象一定是实现类,而不是接口,因为实现类变化的快,而接口不会那么快
如何在界面层访问业务逻辑层: 在界面层创建业务逻辑层的对象,看上谁就去创建谁的对象
界面层一定有业务逻辑层的对象
靠对象之间相互关联
AOP
面向切面编程
公共的 通用的 重复的代码快 单独拿出来 ,在需要调用的方法中通过动态代理的方式进行
静态代理
/*
有接口和实现类时 先写接口
静态代理
一个接口
实现类和代理都要实现接口
实现类(目标对象)中实现具体业务功能
代理类中 :成员变量为接口类型 为了实现目标对象的灵活切换
在构造方法参数用成员变量写入 是为了实现目标对象和代理的联系
重写的接口中
1.实现切面功能
2.调用目标对象的方法
3.实现切面功能
测试类调用
注意:是调用代理类(括号里是目标对象的实例)
*/
第三个版本:
该静态方法实现了业务功能的灵活切换
未实现切面功能的灵活切换
public void test2(){
Service service = new Agent(new ProductService());
service.buy();
}
第四个版本的实现
缺点:没有实现业务的动态代理
优点 实现了切面的灵活切换
上接口就是上灵活
该思想最大的特点就是
提取接口出来
在一个实现类中和接口灵活连接是通过 成员变量的引入,而不是直接实现接口
通过构造方法实现目标对象的注入
jdk8之后有个接口默认实现
接口默认实现 :加了大括号,表示方法的空实现 做到不用实现全部方法,想实现那个接口就实现那个接口
defalt 返回值 方法名() { }
*/
public interface Aop {
default void before(){}
default void after(){ }
default void exception(){}
}
测试类:
public void test3(){
Service service = (Service) new com.test4.service.Agent(new com.test4.service.BookService(),new TranctionAop());
Service service1 = new Agent(service,new RiziAop());
这行代码实现了切面功能的添加 不断累加切面功能 即实现日志功能又实现事务功能
service1.buy();
}
}