关于IOC
- 控制反转(Inversion of Control),那么是什么方面的控制被反转了呢?是依赖对象的获得被反转,简单来说就是Spring容器来实现这些相互依赖对象的创--建、协调工作。对象只需要关系业务逻辑本身就可以了。从这方面来说,对象如何得到他的协作对象的责任被反转了。
关于AOP
- 面向切面编程(Aspect Oriented Programming)可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善
- 它是一种思想,可在不改变程序源码的情况下为程序添加额外的功能。
- 允许通过分离应用的业务逻辑与系统级服务进行内聚性的开发。应用对象只实现业务逻辑即可,并不负责其他的系统级关注点。
- AOP专门用于处理系统中分布于各个模块中的交叉关注点的问题,在J2EE应用中,常常通过AOP来处理一些具有横切性质的系统级服务,如事务管理、安全检查、缓存、对象池管理等,AOP已经成为一种非常常用的解决方案。
AOP核心概念
1、横切关注点 对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点
2、切面(aspect) 类是对物体特征的抽象,切面就是对横切关注点的抽象
3、连接点(joinpoint) 被拦截到的点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器
4、切入点(pointcut) 对连接点进行拦截的定义
5、通知(advice) 所谓通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕通知五类
6、目标对象 代理的目标对象
7、织入(weave) 将切面应用到目标对象并导致代理对象创建的过程
8、引入(introduction) 在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段
下面我们来看一个例子来做说明
USB.java usb接口
Keyboard.java usb的实现类键盘类
Keycap.java 键位类,在键盘类中有一个键位的集合属性
ConnHandler.java 捕获USB设备连接类
BaseUnitTest.java 单元测试基类
FirstTest.java 我们做测试的一个类
spring-first.xml spring的配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">
<!-- context:component-scan 自动扫面basepackage所指定的包下的所有带有@component的类并将这个类放置到IOC容器中
要是其生效需要在更标签下配置context命名空间
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
-->
<context:component-scan base-package="com.lagersoft.po"></context:component-scan>
<!-- aop:config对一个切面问题的描述 aop:aspect 描述切面 其中ref指定切面处理对象 aop:pointcut切入点
要是其生效需要在更标签下配置aop命名空间
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
-->
<aop:config>
<aop:aspect id="aspect" ref="connHandler">
<aop:pointcut expression="execution(* com.lagersoft.po.*.*conn(..))"
id="pointcutConn" />
<aop:before method="doBeforeConn" pointcut-ref="pointcutConn" />
<aop:after method="doAfterConn" pointcut-ref="pointcutConn" />
<aop:around method="doAroundConn" pointcut-ref="pointcutConn" />
<aop:after-returning method="doReturnConn"
pointcut-ref="pointcutConn" />
<aop:after-throwing method="doThrowingConn"
throwing="ex" pointcut-ref="pointcutConn" />
</aop:aspect>
</aop:config>
</beans>
package com.lagersoft.po;
/**
* 接口类 USB接口
* @author xiaoping
*
*/
public interface USB {
/**
* 连接usb设备方法
*/
void conn();
}
package com.lagersoft.po;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* 键盘类 实现了usb接口
* @author xiaoping
*
*/
@Component
public class Keyboard implements USB {
@Autowired
List<Keycap> caps;
public List<Keycap> getCaps() {
return caps;
}
public void setCaps(List<Keycap> caps) {
this.caps = caps;
}
@PostConstruct
public void init(){
System.out.println("USB:connection preparation");
}
@Override
public void conn() {
System.out.println("USB:Keyboard conn");
}
@PreDestroy
public void destroy(){
System.out.println("USB:Keyboard disconnect ");
}
}
package com.lagersoft.po;
import org.springframework.stereotype.Component;
/**
* 键位类
* @author xiaoping
*
*/
@Component
public class Keycap {
private String cap;
public Keycap(){
System.out.println("Keycap:I'm Keycap");
}
public Keycap(String cap){
this.cap = cap;
}
}
package com.lagersoft.po;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.stereotype.Component;
/**
* 捕获USB连接
* @author xiaoping
*
*/
@Component
public class ConnHandler {
public void doBeforeConn(){
System.out.println("ConnHandler:USB device connection...");
}
public void doAfterConn(){
System.out.println("ConnHandler:Disconnect the USB device....");
}
public Object doAroundConn(ProceedingJoinPoint pjp)throws Throwable{
System.out.println("ConnHandler:begin doAroundConn the USB device....");
Object obj = pjp.proceed();
System.out.println("ConnHandler:end doAroundConn the USB device....");
return obj;
}
public void doReturnConn(){
System.out.println("ConnHandler:doReturnConn the USB device....");
}
public void doThrowingConn(){
System.out.println("ConnHandler:doThrowingConn the USB device....");
}
}
package com.lagersoft.base;
import org.junit.After;
import org.junit.Before;
import org.springframework.beans.BeansException;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* 单元测试基类
* @author xiaoping
*
*/
public class BaseUnitTest {
private ClassPathXmlApplicationContext context;
private String springXmlpath;
public BaseUnitTest() {}
public BaseUnitTest(String springXmlpath) {
this.springXmlpath = springXmlpath;
}
@Before
public void before() {
if ("".equals(springXmlpath)) {
springXmlpath = "classpath*:spring-*.xml";
}
try {
context = new ClassPathXmlApplicationContext(springXmlpath.split("[,\\s]+"));
context.start();
} catch (BeansException e) {
e.printStackTrace();
}
}
@After
public void after() {
context.destroy();
}
@SuppressWarnings("unchecked")
protected <T extends Object> T getBean(String beanId) {
try {
return (T)context.getBean(beanId);
} catch (BeansException e) {
e.printStackTrace();
return null;
}
}
protected <T extends Object> T getBean(Class<T> clazz) {
try {
return context.getBean(clazz);
} catch (BeansException e) {
e.printStackTrace();
return null;
}
}
}
package com.lagersoft.test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.BlockJUnit4ClassRunner;
import com.lagersoft.base.BaseUnitTest;
import com.lagersoft.po.USB;
@RunWith(BlockJUnit4ClassRunner.class)
public class FirstTest extends BaseUnitTest{
public FirstTest(){
super("classpath:spring-first.xml");
}
@Test
public void t1(){
USB keyboard = getBean("keyboard");
keyboard.conn();
}
}
运行测试方法t1()的结果
Keycap:I'm Keycap
USB:connection preparation
ConnHandler:USB device connection...
ConnHandler:begin doAroundConn the USB device....
USB:Keyboard conn
ConnHandler:Disconnect the USB device....
ConnHandler:end doAroundConn the USB device....
ConnHandler:doReturnConn the USB device....
USB:Keyboard disconnect