Spring
1. IoC控制反转
IOC(Inversion of Control),控制反转。
就是指将对象的创建,对象的存储(map),对象的管理(依赖查找,依赖注入)交给了spring容器。
1. 1xml配置IoC
创建hello类
package cn.tedu.pojo
public class Hello() {
public void hi() {
System.out.println("hi spring ioc");
}
}
创建spring-config.xml文件
<!-- 在框架里开始了ioc ,会把每个类创建对象,并存起来 Map<id的值,对象>
Map<String,Object> 存的是 {"hello" = new Hello()}
框架只会拿到class文件,需要反射创建对象:
{"hello" = Class.forName("cn.tedu.pojo.Hello").newInstance() }
-->
<bean class="cn.tedu.pojo.hello" id="hello"></bean>
创建测试类
@Test
public void ioc() {
//读取核心配置文件
ClassPathXmlApplicationContext spring =
new ClassPathXmlApplicationContext("spring-config.xml");
//根据核心配置文件中,id属性的值,获取对应对象
Object o = spring.getBean("hello");
Hello h = (Hello)o;
h.hi();
}
1.1 注解IoC
@Componet注解
spring框架提供,用来完IoC,存入map{ “person” = new Person() }
创建Person类
package cn.tedu.pojo
@Component
public class Person() {
public String name = "djh";
}
配置扫描器
配置扫描器是为了让spring框架知道哪些类上面使用了@Component注解,指定扫描那个包里的资源
<context:component-scan base-package="cn.tedu.pojo"></context>
扫描cn.tedu.pojo本包及子包带@Component注解的类
创建测试类
@Test
public void iocanno() {
//读取核心配置文件
ClassPathXmlApplicationContext spring =
new ClassPathXmlApplicationContext("spring-config.xml");
//获取spring框架new的对象,根据类名首字母小写为条件获取对象
Person p = (Person)spring.getBean("person");
//调用子类的资源
System.out.println(p.name);
}
2. DI依赖注入
DI(Dependency Injection)依赖注入 。
相对于IoC而言,依赖注入(DI)更加准确地描述了IoC的设计理念。所谓依赖注入,即组件之间的依赖关系由容器在应用系统运行期来决定,也就是由容器动态地将某种依赖关系的目标对象实例注入到应用系统中的各个关联的组件之中。
@Autowired注解
利用注解方式,我们只需要写@Autowired注解,底层就会去容器中找对应的对象,如果有获取到,反射调用其对应的set方法,设置。而这个调用过程都是自动,我们没有手工去写set方法。所以这个过程也称为自动装配
Dept.java
package spring.pojo;
import org.springframework.stereotype.Component;
@Component
public class Dept {
public String deptName = "软件部";
}
User.java
package spring.pojo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class User {
//相当于框架完成了:new User().setDept(new Dept());
@Autowired
private Dept dept; //对象的关联
public String name = "tony";
}
测试DI
package test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import spring.pojo.Dept;
import spring.pojo.User;
public class TestDI {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
Dept d = (Dept)ac.getBean("dept");
User u = (User)ac.getBean("user");
System.out.println(d);
System.out.println(u);
System.out.println(u.getDept().deptName);
}
}
@Autowrie注解描述属性时,注入规则:
spring框架会依据@Autowrie注解描述的类型属性,从spring容器中查找对应的Bean,假如只找到一个则直接注入,假如找到多个还会比对属性名是否与容器中的Bean的名字有相同的,有则直接注入,没有则抛出异常
3. AOP面向切面编程
Spring核心特征中除了IoC控制反转、DI依赖注入,还有一个核心就是强大的面向切面编程AOP(Aspect Oriented Programming)的实现。Spring的AOP功能,其实就是为了增强方法的功能,AOP的使用场景:事务管理、权限管理、缓存管理、日志管理、性能测试。
3.1 组成
切面Aspect
其实就是一个类,由通知和切点组成,创建一个类,用@Aspect注解标记是一个切面
@Aspect
public class AspectTest {
}
切点PointCut
1.使用@Pointcut注解,需要写切点表达式, 切点表达式用来给指定包,类,方法加功能,execution的参数规则如下:
(返回值 包名.类名.方法名(参数列表))
@Pointcut("execution(* cn.tedu.service..*.*(..))")
*通配符,该通配符主要用于匹配单个单词,或者是以某个词为前缀或后缀的单词
…通配符,该通配符表示0个或多个项
通知Advice
就是类里的一个方法,分为:
①前置通知before(方法执行前要加的)
②后置通知after(方法执行后要加的)
③环绕通知around(方法执行前后都要加的)
④返回后通知afterReturning
⑤异常通知afterThrowing
3.2 测试环绕通知
package cn.tedu.service;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Component
@Aspect //标记是一个切面
public class AspectTest {
@Pointcut("execution(* cn.tedu.service..*.*(..))")
public void point() {}
//定义通知,本质就是一个方法,增强功能
@Around("point()")//标记环绕通知,方法执行前后都加功能
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
Object object = joinPoint.proceed();//继续执行原来的业务
long endTime = System.currentTimeMillis();
System.out.println("aop计算的耗时是:"+(endTime-startTime));
//返回这个结果
return object;
}
}
执行结果: