spring框架总结
spring框架的重点
1.IOC/DI:控制反转/依赖注入
2.AOP:面向切面编程
IoC(控制反转)/DI(依赖注入)
(1)IoC:指原先有程序员主动new实例化对象的事情,转交给Spring负责
(2)控制反转中的控制:指控制类的对象
(3)控制反转中的反转:指交给Spring控制(spring的xml文件配置bean工厂)
(4)IoC最大的作用:解耦,程序员不需要管理对象,解除了管理对象与程序员之间的耦合。
(5)当一个类(A)需要依赖另一个类(B)对象时,将类B赋值给类A的过程就叫做依赖注入。
简单来说依赖注入为:
依赖:一个对象需要使用另一个对象
注入:通过setter方法进行另一个对象实例设置
依赖注入的三种方式
1、构造方法依赖注入
把2中的set方法变成构造函数就ok了。
2、setter方法注入
public class BookServiceImpl implements BookService {
private BookDao bookDao;
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
@Override
public void addBook() {
this.bookDao.addBook();
}
}
3、接口注入
好像是用的不多,暂时不做了解。
代码块
BookDao接口
public interface BookDao {
public void addBook();
}
BookDao接口实现类
public class BookDaoImpl implements BookDao {
@Override
public void addBook() {
System.out.println(" di add book");
}
}
BookService接口
public interface BookService {
public abstract void addBook();
}
BookService接口实现类
public class BookServiceImpl implements BookService {
private BookDao bookDao;
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
@Override
public void addBook() {
this.bookDao.addBook();
}
}
bean对应的applicationContext.xml的配置
<bean id="bookServiceId" class="com.my.service.BookServiceImpl">
<property name="bookDao" ref="bookDaoId"></property>
</bean>
<!-- 创建dao实例 -->
<bean id="bookDaoId" class="com.my.dao.BookDaoImpl"></bean>
测试类:
public class BookServiceImplTest {
@Test
public void demo01(){
//从spring容器获得
String xmlPath = "applicationContext.xml";
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
BookService bookService = (BookService) applicationContext.getBean("bookServiceId");
bookService.addBook();//di add book
}
}
控制台输出
di add book
AOP编程
一 AOP的基本概念
(1)Aspect(切面):通常是一个类,里面可以定义切入点和通知
(2)JointPoint(连接点):程序执行过程中明确的点,一般是方法的调用
(3)Advice(通知):AOP在特定的切入点上执行的增强处理,有before,after,afterReturning,afterThrowing,around
(4)Pointcut(切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式
(5)AOP代理:AOP框架创建的对象,代理就是目标对象的加强。Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类
4.通知执行的优先级
进入目标方法时,先织入Around,再织入Before,退出目标方法时,先织入Around,再织入AfterReturning,最后才织入After。
注意:Spring AOP的环绕通知会影响到AfterThrowing通知的运行,不要同时使用!同时使用也没啥意义。
5.切入点的定义和表达式
切入点表达式的定义算是整个AOP中的核心,有一套自己的规范
Spring AOP支持的切入点指示符:
(1)execution:用来匹配执行方法的连接点
A:@Pointcut("execution(* com.aijava.springcode.service..*.*(..))")
第一个表示匹配任意的方法返回值,…(两个点)表示零个或多个,上面的第一个…表示service包及其子包,第二个表示所有类,第三个*表示所有方法,第二个…表示方法的任意参数个数
B:@Pointcut("within(com.aijava.springcode.service.*)")
within限定匹配方法的连接点,上面的就是表示匹配service包下的任意连接点
C:@Pointcut("this(com.aijava.springcode.service.UserService)")
this用来限定AOP代理必须是指定类型的实例,如上,指定了一个特定的实例,就是UserService
D:@Pointcut("bean(userService)")
bean也是非常常用的,bean可以指定IOC容器中的bean的名称
后言: spring 的环绕通知和前置通知,后置通知有着很大的区别,主要有两个重要的区别:
1) 目标方法的调用由环绕通知决定,即你可以决定是否调用目标方法,而前置和后置通知 是不能决定的,他们只是在方法的调用前后执行通知而已,即目标方法肯定是要执行的。
2) 环绕通知可以控制返回对象,即你可以返回一个与目标对象完全不同的返回值,虽然这很危险,但是你却可以办到。而后置方法是无法办到的,因为他是在目标方法返回值后调用
aop的xml形式的配置
<aop:config>
<aop:aspect id="loggerAspect" ref="logger">
<aop:around method="record" pointcut="(execution(* com.aijava.distributed.ssh.service..*.add*(..))
or execution(* com.aijava.distributed.ssh.service..*.update*(..))
or execution(* com.aijava.distributed.ssh.service..*.delete*(..)))
and !bean(logService)"/>
</aop:aspect>
</aop:config>
代码块
point类 切入点函数
public class point {
public int add(int a,int b){
System.out.println("切入点");
return a+b;
}
}
IOC的入口(java代码配置bean,等同于xml方式)
//IOC的入口
@Configuration
@EnableAspectJAutoProxy
public class config {
@Bean
public point point(){
return new point();
}
@Bean
public point1 point1(){
return new point1();
}
}
切面类
@Aspect
public class point1 {
@Pointcut("execution(public int com.ok.point.*(..))")
public void kk(){}
@Before("kk()")
public void k(){
System.out.println("@before执行");
}
@Around("kk()")
public Object testAround(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("@around函数前");
Object A=joinPoint.proceed();
System.out.println("@around函数后");return A;
}
}
测试类
public class pointcut1Test {
@Test
public void test01(){
AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(config.class);
point c = app.getBean(point.class);
int result = c.add(4, 7);
System.out.println("结果是:"+result);
app.close();
}
}
控制台输出
@around函数前
@before执行
切入点
@around函数后
结果是:11