spring结构介绍
1.核心配置文件applicationContext.xml 用来实例bean 注入属性 加载配置文件 引入其他applicationContext.xml
通过bean标签来进行实例对象
实例对象的三种方式
1.
2.
创建一个工厂类 在类中创建 静态方法 用于创建实体类
3.
创建一个工厂类 在类中创建 普通方法 用于创建实体类
2.IOC (inverse of control )控制反转
控制反转==对象控制权交给别人来完成 发生了“主从换位”的变化 应用程序变成被动等待IoC容器来创建并注入它所需要的资源
BeanFactory 才是 Spring 容器中的顶层接口。ApplicationContext 是它的子接口。
3.依赖注入
-set方法注入 实体类中属性必须有set方法
-name 指定属性名称
-value 给属性赋的值
-构造方法注入
通过构造方法给属性赋值
1. 支持按照参数名注入 name value
2. 支持按照类型注入 type value
3. 支持按照索引注入 index value
4. 支持按照顺序注入 value
-注入引用数据类型
<bean id="birthday" class="java.util.Date"></bean>
<bean id="account5" class="com.itheima.pojo.Account">
<property name="birthday" ref="birthday"></property>
</bean>
-p名称空间注入 在头文件中需要映入指定 命名空间
xmlns:p="http://www.springframework.org/schema/p"
<bean id="account6"
class="com.itheima.pojo.Account"
p:birthday-ref="birthday" p:id="6" p:name="马云" p:money="999999999">
</bean>
-注入复杂类型 list,set, map ,array
<property name="myStrs">
<array>
<value>mybatis</value>
<value>spring</value>
<value>springMVC</value>
</array>
</property>
<property name="myList">
<list>
<value>表现层</value>
<value>业务层</value>
<value>持久层</value>
</list>
</property>
<property name="mySet">
<set>
<value>模型层</value>
<value>视图层</value>
<value>控制层</value>
</set>
</property>
<property name="myMap">
<map>
<entry key="M" value="Model"></entry>
<entry key="V" value="View"></entry>
<entry key="C" value="Controller"></entry>
</map>
</property>
<property name="myProps">
<props>
<prop key="M">Model</prop>
<prop key="V">View</prop>
<prop key="C">Controller</prop>
</props>
</property>
-SpEL表达式 用于规范注入
通过 #{} 提供了一种统一的注入方式, 统一使用value属性即可
需要注意的是, 注入字符串需要手动添加 单引号
4.加载Properties 需要引入头文件 写出下列标签自动引入
需要配置:
<contxt:property-placeholder location="classpath:data.properties"
file-encoding="UTF-8"></contxt:property-placeholder>
5.多配置文件三种方式共同加载
1. 方法一:如果有多个配置文件,可以在创建容器时加载多个配置文件
ApplicationContext context = new ClassPathXmlApplicationContext("spring-01.xml","spring-02.xml");
2. 方法二:也可以在spring-02.xml 中引入spring-01.xml文件,此时测试类只需要加载spring-02.xml即可
引入标签<import resource="classpath:spring-01.xml"></import>
3. 方法三:也可以直接创建一个新的配置文件,同时引入spring-01.xml和spring-02.xml ,测试测试类只需要加载新的配置文件即可
新的配置文件,同时引入spring-01.xml和spring-02.xml
4. 注意:如果有多个配置文件,不同的配置文件中有相同的id,后面加载的配置文件会覆盖前面的对象。
spring-mybatis整合:
整合过程就是将原有的mybatis信息 会在spring中进行替换
需要引入依赖
1.加载属性文件:
-mybatis中加载属性文件 在核心配置文件中使用
整合后
-在applicationContext.xml中使用<context:property-placeholer location="classpath:.properties"></context:property-placeholer>来进行加载
2.配置数据源 dataSource
mybatis:
整合后
applicationContext.xml中配置bean
//注意使用${jdbc.driver}需要加载jdbc.properties文件
3.因为在mybatis中需要 SqlSessionFactoryBuilder通过核心配置文件流来 创建工厂:SqlSessionFactory
在spring-mybatis整合后 将SqlSessionFactoryBean注入容器中即可 并将其中属性 dataSource typeAliasesPackage mapperLocations都注入
4.在mybatis中需要获取接口的动态代理对象 来执行相应的方法
mybatis之前通过sqlsession来获取动态代理 getMapper(Class
整合后 注入到bean中
5.mybatis核心配置文件中
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
accountDao = context.getBean(AccountDao.class);用来动态代理对象
6.spring5 系列默认支持 log4j2 版 日志依赖
spring注解开发配合xml《重点常用》
Bean标签会非常多,难以维护
在applicationContext。xml中启动注解扫描
<context:component-scan base-package="包名"/>
1. @Component @Controller @Service @Repository 类定义上方 代替xml中的bean
@Controller @Service @Repository的出现时为了区分三层架构 效果是一样的
相关属性:value="" 定义bean的访问id
2.对属性注入 定义在属性上 代替xml中 bean的属性注入 这里复习下注入方式 set 构造 p(原理还是set)
@Autowired、@Qualifier、@Resource
@Autowired
required:定义该属性是否允许为null,默认true
@Qualifier
value:需要注入的bean的id 配合@Autowired一起使用 因为@Autowired自动装配 若是有两个实现类就必须使用这个注解来指定id
@Resource jdk提供相当于同时指定了@Autowired和@Qualifier
----
3.@Scope @Primary 类注解
@Scope 指定作用范围 代替xml中的一些scope属性
@Primary 设置bean的优先级出现多个相同的bean会优先使用这个注解的bean
4.@PostConstruct @PreDestroy
代替xml中bean 的 初始销毁 属性
@PostConstruct替代 init-method
@PreDestroy 替代 destrop-method
这里提一下bean的生命周期
scope为单例时会在bean容器初始化时进行加载 并调用 init-method指定的方法 实例对象会随着bean的销毁而销毁
scope为原型时会延迟加载 在调用时进行初始化 并每次都会执行init-method方法 销毁由java的垃圾回收机制来进行判断 不随着容器销毁而销毁
spring零配置(纯注解)
spring零配置也就是使用注解完全替代applicationContext.xml配置文件
就想零配置到时候怎么加载bean容器 之前都是用ClassPathXmlApplicationContext("配置文件")进行加载
这里可以使用AnnotationconfigApplicationContext(
@Configuration 类注解
作用等同于xml配置文件,当前注解声明的类中,编写配置信息,所以我们把**使用@Configuration的类称之为配置类
@ComponentScan("com.itheima") 类注解 扫描注解
等效于 xml中 <context:component-scan base-package="com.itheima"/>
@Bean注解 方法注解 将方法的返回值存储到Spring IOC容器中
// bean的id可以指定,默认是方法名
@Bean("user1")
public User user(){
return new User(1,"xiaoming",new Date(),"male","china");
}
@PropertySource 标记在类 引入外部属性文件 比如jdbc.properties
@Value注解 属性注解 方法注解 注入非引用类型,设置属性的值或对方法进行传参
@Value("${jdbc.username}")
private String username;
@Import注解 类注解 导入其他配置类(对象) 相当于XML配置文件中的`<import>`标签
@Import(RedisConfig.class)
public class SpringConfig{
}
---零配置IOC容器
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
Spring整合Junit
需要引入坐标
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
替换
//创建容器
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring01.xml");
//创建容器
Account account = applicationContext.getBean(Account.class);
@RunWith 类上 spring的单元测试运行器替换原有运行器
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration 类上 注解作用:指定配置类或者配置文件所在位置
@ContextConfiguration(classes = SpringConfiguration.class)注解版配置文件
@ContextConfiguration(locations = "classpath:spring01.xml")xml版配置文件
Spring AOP xml方式
介绍 SpringAOP是底层是动态代理(jdk动态代理 cglib动态代理)
静态代理:
运行前就编译好,且我们只能对这一个接口进行代理。
如果我们要对更多的接口进行代理就需要使用动态代理了。
jdk动态代理:必须要有接口 所有具有局限性
代理对象是在运行期,通过反射机制创建动态代理对象。能够代理各种类型的期对象。
代理对象的字节码文件,随用随创建,随用随加载。
CGLIG动态代理:需要 引入第三方的依赖。不需要接口也可以代理,基于子类代理,有无接口均可
代理类是目标对象的子类对象
依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
AOP:面向切面编程 AOP是OOP(面向对象)的延续 aop面向多个对象对多个对象进行横切增强处理
Joinpoint(连接点):所有方法都是连接点
Pointcut(切入点):指定对那个Joinpoint进行拦截哪个连接点就是切入点
Advice(通知/增强):增强方法
Introduction: Introduction可以在运行期为类动态地添加一些方法或Field。 【了解】
Target(目标对象):代理的目标对象。
Weaving(织入):创建代理对象的过程
Proxy(代理):代理类
Aspect(切面):Pointcut+advice 切入点和增强方法
入门: 依赖 spring-context spring-test junit
<context:component-scan base-package="com.itheima"></context:component-scan>
<!--创建通知对象-->
<bean id="advice" class="com.itheima.aop.AOPAdvice"></bean>//指定的类
<!--aop配置-->
<aop:config>
<!--配置切入点表达式-->
<aop:pointcut id="pc" expression="execution(* com.itheima.service..*.*(..))"></aop:pointcut>
<!--切面配置-->
<aop:aspect ref="advice">//上面有说明切面=advice(通知)+pointcut(切入点)
<!--前置增强-->
<aop:before method="before" pointcut-ref="pc"></aop:before>
<!--最终增强-->
<aop:after method="after" pointcut-ref="pc"></aop:after>
<!--后置增强-->
<aop:after-returning method="afterReturning" pointcut-ref="pc"></aop:after-returning>
<!--异常增强-->
<aop:after-throwing method="afterThrowing" pointcut-ref="pc"></aop:after-throwing>
</aop:aspect>
</aop:config>
这里讲解上面代码
<aop:config></aop:config>必须配置
<aop:pointcut id="pc" expression="execution(* com.itheima.service..*.*(..))"></aop:pointcut>expression 指定切入点表达式
<aop:before method="before" pointcut-ref="pc"></aop:before>
method指定前置通知 所要执行类中的方法
pointcut-ref 指定切入点 有指定切入点表达式
execution()中 //切点
//返回值 *
//com.itheima.service
//当前包及其子包 。。
//任意类 *
//任意方法 *
//任意参数个数顺序(..)
增强类型:
Before AfterReturning AfterThrowing After
Around 可替代上面四个
举例:
public Object around(ProceedingJoinPoint joinPoint){
try {
System.out.println("前置增强");
Object result = joinPoint.proceed(joinPoint.getArgs());
System.out.println("后置增强");
return result;
} catch (Throwable throwable) {
throwable.printStackTrace();
System.out.println("异常增强");
}finally {
System.out.println("最终增强");
}
return null;
}
application中配置:
<!--aop配置-->
<aop:config>
<!--切面配置-->
<aop:aspect ref="advice">
<!--配置切入点表达式-->
<aop:pointcut id="pc" expression="execution(* com.itheima.service..*.*(..))"></aop:pointcut>
<!--配置环绕增强-->
<aop:around method="around" pointcut-ref="pc"></aop:around>
</aop:aspect>
</aop:config>
环绕通知第二种方式:
实现MethodInterceptor 重写invoke(MethodInvocation invocatio)
invocation.proceed();来执行真实方法
一些细节:
JoinPoint可以作为参数:
System.out.println("参数数组:" + joinPoint.getArgs());
System.out.println("目标对象:" + joinPoint.getTarget());
System.out.println("方法签名:"+joinPoint.getSignature());
System.out.println("方法名:" + joinPoint.getSignature().getName());
异常增强需要在方法中打印异常信息 :
就需要在配置文件中 通过属性throwing="e" 传递参数e
e.getMassage()
环绕增强参数:必须使用ProceedingJoinPoint 类型参数
proceed()可以调用真实方法
Spring AOP 注解方式
注意配置文件需要开启aop:aspectj-autoproxy</aop:aspectj-autoproxy>
@Component 修饰类 注入到容器中
@Aspect 修饰类 切面=(切点+增强方法)
@Pointcut("execution(* com.itheima.service..*.*(..))")//定义切点
public void pc(){}
@Before("pc()") @After("pc()") @AfterReturning("pc()") @AfterThrowing("pc()") @Around("pc()")
扩展:开启aop的注解支持,纯注解时
@EnableAspectJAutoProxy 开启aop注解支持
spring AOP的底层主要是通过两种动态代理控制。
优先默认使用jdkProxy,如果没有实现接口则使用cglib进行代理。
当然我们也可以通过配置修改为cglib。
xml模式: <aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
半xml半注解: <aop:config proxy-target-class="true"></aop:config>
纯注解模式: @EnableAspectJAutoProxy(proxyTargetClass = true)