初学者主要掌握4个方面的功能
- Ioc
- Aop
- 事务
- JdbcTemplate
Ioc
Ioc概念
Ioc,中文称为控制反转,实际上就是指对一个对象控制权的反转。
class People(){
Book book = new book();
}
class Book(){
}
book对象的控制权在people对象中,别的对象想要使用book对象就需要重新创建。即对象的创建、初始化、销毁由开发者去完成,spring将这些操作交给Ioc容器去完成,项目启动时创建对象,需要时去容器“要”而不是去new。
Ioc初体验
- 创建Maven项目,导入spring-context依赖
- 在resources目录下创建spring配置文件,在配置文件中注册bean
<bean class = " ",id = " "/>
class表示注册bean的全路径,id表示bean的唯一标识
- 主方法加载配置文件
加载配置文件后,spring容器调用类的无参构造方法进行bean对象的创建
- 加载方式1: ClasspathXmlAplicationContext(去resources下查找配置文件)
- 加载方式2: FileSystemXmlAplicationContext (绝对路径下查找配置文件)
最后可通过getbean方法获取对象
bean的获取
- getbean(" id ")
- getbean( 类.class)
一般采用第一种,第二种若类有多个实例,则会报错,Ioc无法确认是哪一个
属性注入
简单属性注入
构造方法注入
index中123对应参数中的第123个,index与value要对应
<bean class="" id="">
<constructor-arg index="0" value=""></constructor-arg>
<constructor-arg index="1" value=""></constructor-arg>
<constructor-arg index="2" value=""></constructor-arg>
</bean>
根据参数名进行注入,name写参数名即可
<bean class="" id="">
<constructor-arg name="" value=""></constructor-arg>
<constructor-arg name="" value=""></constructor-arg>
<constructor-arg name="" value=""></constructor-arg>
</bean>
set方法注入
name对应get/set方法中的属性名
<bean class="" id="">
<property name="" value=""></property>
<property name="" value=""></property>
<property name="" value=""></property>
</bean>
p名称空间注入
本质上也是调用了set方法
复杂属性注入
对象注入
可以通过xml来注入对象,通过ref来引用对象
<bean class="" id="">
<property name="cat" ref="lanmao"></property>
</bean>
<bean class="Cat" id="lanmao">
<property name="" value=""></property>
<property name="" value=""></property>
</bean>
集合注入
通过array或list标签进行,value标签代表值
//数组
<bean class="" id="">
<property name="">
<array>
<value>wq</value>
<value>lya</value>
<value>szm</value>
</array>
</property>
</bean>
//List
<bean class="" id="">
<property name="">
<list>
<value>wq</value>
<value>lya</value>
<value>szm</value>
</list>
</property>
</bean>
array或者list节点中也可以是对象
<bean class="" id="">
<property name="">
<list>
<ref bean="cat"></ref>
<ref bean="cat2"></ref>
<bean class="Cat" id="cat3">
<property name="name" value="jzc"></property>
<property name="age" value="3"></property>
</bean>
</list>
</property>
</bean>
<bean class="Cat" id="cat">
<property name="name" value="wq"></property>
<property name="age" value="3"></property>
</bean>
<bean class="Cat" id="cat2">
<property name="name" value="szm"></property>
<property name="age" value="3"></property>
</bean>
可以通过ref去引用外部定义好的bean,也可以直接在list或者array节点中去定义bean
map注入
<property name="map">
<map>
<entry key="" value=""></entry>
<entry key="" value=""></entry>
<entry key="" value=""></entry>
</map>
</property>
properties注入
<property name="info">
<props>
<prop key="name">szm</prop>
<prop key="age">22</prop>
</props>
</property>
Java配置
在Spring中,将一个Bean注册到Spring容器中,有三种方式
- xml配置
- Java配置(通过Java代码将Bean注册到Spring容器中)
- 自动化扫描
- People类
public class People {
public void peopleSay(){
System.out.println("haha...");
}
}
- 编写配置类
@Configration注解表明该类是配置类,相当于applicationContext.xml,方法上添加@Bean注解,表示将方法的返回值注入到Spring容器中
@Configuration
public class JavaConfig {
@Bean
People people(){
return new People();
}
}
- 主方法测试
配置类的加载使用AnnotationConfigApplicationContext来实现的
public class main {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(JavaConfig.class);
People people = ctx.getBean(People.class);
people.peopleSay();
}
}
这里存在一个问题,即Bean的名字是什么?
通常,Bean的名称是被@Bean注解所标注的方法的方法名,但是也可以在@Bean(" ")中修改
自动化配置
自动化配置分为Java实现与xml实现
假设有一个类UserService,我们希望自动化扫描时,这个类能够自动注册到Spring容器中去,那么可以给该类添加一个@Service作为标记
与Service相似的注解如下
- @Service Service 层
- @Component 在其他组件上使用
- @Repository Repository层
- @Controller Controller层
添加完成后,即进行自动化扫描
- Java代码配置自动扫描
@Configuration
@ComponentScan(basePackages = "扫描的包名")
public class JavaConfig {
}
如果不指定扫描的包名,则默认扫描配置类所在包下的bean以及配置类所在包的子包下的类
- xml文件配置自动扫描
<context:component-scan base-package=""></context:component-scan>
注意:bean的名字是类名首字母的小写,如UserService就是userService,也可在@Service(" ")注解里去指定
- 对象注入
-
Autowired
根据类型注入对象,当有多个实例时,不可注入 -
Resource
根据变量名去进行查找注入
条件注解
条件注解就是在满足某一个条件的情况下,生效的配置
条件注解
案例:当系统运行在Windows上时打印dir,在Linux时打印ls
- 定义接口
public interface ShowCmd {
String showCmd();
}
- 然后实现Windows下的实例和Linux下的实例:
public class WinShowCmd implements ShowCmd {
@Override
public String showCom() {
return "dir";
}
}
public class LinuxShowCmd implements ShowCmd {
@Override
public String showCom() {
return "ls";
}
}
- 接下来定义Windows和Linux下的条件
public class WindowsCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
String osName = (String) conditionContext.getEnvironment().getProperty("os.name");
boolean win = osName.toLowerCase().contains("win");
return win;
}
}
public class LinuxCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
String osName = (String) conditionContext.getEnvironment().getProperty("os.name");
boolean ls = osName.toLowerCase().contains("ls");
return ls;
}
}
- 接下来,在定义Bean的时候,就可以去配置条件注解了:
@Configuration
@ComponentScan(basePackages = "org.javaboy.ioc")
public class JavaConfig {
@Bean("showCmd")
@Conditional(WindowsCondition.class)
ShowCmd winCmd() {
return new WinShowCmd();
}
@Bean("showCmd")
@Conditional(LinuxCondition.class)
ShowCmd LinuxCmd(){
return new LinuxShowCmd();
}
}
- 需要给两个Bean取一样的名字,这样在调用时才可以自动匹配。然后给每一个Bean加上条件注解,当条件中matches方法返回true的时候,这个Bean的定义就会生效
public class JavaMain {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(JavaConfig.class);
ShowCmd showCmd = (ShowCmd) ctx.getBean("showCmd");
System.out.println(showCmd.showCom());
}
}
Aop
Aop,面向切面编程,就是在程序运行时,不改变程序源码的情况下,动态的增强方法的功能,常见的使用场景
- 日志
- 事务
- 数据库操作
- …
具有一些模板化的代码来解决问题
在Aop中的一些常见概念
Aop的实现
Aop基于Java的动态代理来实现
Java中动态代理实现的两种方式:
- cglib
- jdk
动态代理通过反射完成
Aop中的5种通知类型
- 前置通知
- 后置通知
- 返回通知
- 异常通知
- 环绕通知