通过注解方式进行bean管理准备

  1. jar包(红框内为aop操作需要的依赖)
  2. 引入约束
<?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:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- bean definitions here -->

</beans>
  1. 开启注解扫描
<!-- 开启注解扫描(类、方法、属性) -->
<!-- base-package:扫描的包(即该包下的所有类、方法、属性都会进行扫描) -->
<context:component-scan base-package="tqb.anno.test"></context:component>
<!-- 了解(只扫描属性上的注解) -->
<!-- <context:spring-configured ></context:spring-configured> -->

注解方式进行bean管理

  1. 创建A类
@Component(value="a")
class A{
	public void test(){
		System.out.println("this is a anno test");
	}
}
  1. 测试类
class TestDemo{
	@Test
	public void fun(){
		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		A a = (A) context.getBean("a");
		a.test();
	}
}

创建对象的四个注解及其它注解

注:在Spring的开发中,开发人员为了之后对Spring的扩展,衍生出了三个注解,但目前功能一致,只不过用在不同层上,阅读起来更加的清晰,如上边的案例我们就可以将@Component换成下面的任意一个,但是功能不发生变化

  1. Web层:@Controller
  2. Service层:@Service
  3. 持久层:@Repository
  4. 其它注解:
    1)@Scope(value=“prototype”):等同于下面的配置
<bean id="a" class="tqb.anno.test.A" scope="prototype"></bean>

注解方式注入属性

注:注入属性的注解方式除了@Autowired,还有@Resourse(name="")

  1. UserDao
@Component(value="userDao")
public class UserDao {
	public void add(){
		System.out.println("userDao............");
	}
}
  1. UserService
@Component(value="userService")
public class UserSevice {
	//自动装配
	@Autowired
	private UserDao userDao;
	
	public void add(){
		System.out.println("userService................");
		userDao.add();
	}
}
  1. 测试类
public class UserTest {
	@Test
	public void fun(){
		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		UserSevice userService = (UserSevice) context.getBean("userService");
		
		userService.add();
	}
}
  1. @Resourse注解
@Component(value="userService")
public class UserSevice {
	// 必须指定name值为UserDao注解的value值
	@Resource(name="userDao")
	private UserDao userDao;
	
	public void add(){
		System.out.println("userService................");
		userDao.add();
	}
}

配置文件和注解方式的混合使用

  1. 配置文件
<?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:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- bean definitions here -->
	<!-- 开启注解扫描(类、方法、属性) -->
	<context:component-scan base-package="tqb.anno.test"></context:component-scan>
	<!-- 配置文件和注解的混合使用 -->
	<bean id="orderService" class="tqb.anno.test.OrderService"></bean>
	<bean id="orderDao" class="tqb.anno.test.OrderDao"></bean>
</beans>
  1. OrderDao类
public class OrderDao {
	public void add(){
		System.out.println("OrderDao..........");
	}
}
  1. OrderService类
public class OrderService {
	@Resource(name="orderDao")
	private OrderDao orderDao;
	
	public void add(){
		orderDao.add();
		System.out.println("OrderService..........");
	}
}
  1. 测试类
class OrderTest{
	@Test
	public void fun(){
		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		OrderService orderService = (OrderService) context.getBean("orderService");
		orderService.add();
	}
}

AOP原理

  1. AOP:面向切面编程,即扩展功能时不修改源代码
  2. AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码
  3. AOP底层使用动态代理模式实现
    1)存在接口,使用动态代理创建接口实现类代理对象
    2)不存在接口,使用动态代理创建继承类的子类代理对象
  4. 图片理解(图片来源:传智播客)


AOP操作术语

  1. 连接点(Joinpoint):某个类中可以被增强的方法,称为连接点
  2. 切入点(Pointcut):我们要对哪些Pointcut进行拦截的定义,称为切入点。即真正被增强的方法
  3. 通知/增强(Advice):拦截到Joinpoint后要做的事情,称为通知/增强,有以下5个通知
    1)前置通知
    2)后置通知
    3)异常通知
    4)最终通知
    5)环绕通知
  4. 切面(Aspect):切入点和通知的结合
  5. 引介(Introduction):引介是一种特殊的通知在不修改类代码的前提下, Introduction可以在运行期为类动态地添加一些方法或Field
  6. 目标对象(Target):代理的目标对象(要增强的类)
  7. 织入(Weaving):把增强应用到目标的过程
  8. 代理(Proxy):一个类被AOP织入增强后,就产生了一个结果代理类

Spring的AOP操作准备

  1. 在Spring中进行AOP操作,主要依赖AspectJ实现
    1)AspectJ不是Spring的一部分,但是和Spring一起进行AOP操作
    2)Spring2.0增加了对AspectJ的支持
  2. 使用AspectJ操作AOP的两种方式
    1)xml配置
    2)注解方式
  3. 进行AOP操作的jar包(红框内)
  4. 配置文件(引入约束)
<?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:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- bean definitions here -->

</beans>
  1. 使用表达式配置切入点(*:通配符、..:任意参数)
    1)execution(<访问修饰符>?<返回类型><方法名>(<参数>)<异常>)
    2)execution(* cn.itcast.aop.Book.add(..))
    3)execution(* cn.itcast.aop.Book.*(..))
    4)execution(* *.*(..))
    5)匹配所有save开头的方法execution(* save*(..))

AspectJ的AOP操作

  1. 配置文件内容
<?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: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-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
	<!-- aspectj的aop操作 -->
	<!-- 、 约束:xmlns:aop="http://www.springframework.org/schema/aop" http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd -->
	<bean id="user" class="tqb.aop.User"></bean>
	<bean id="myUser" class="tqb.aop.MyUser"></bean>
	<!-- 配置aop操作 -->
	<aop:config>
		<!-- 配置切入点 第一个*:匹配所有的修饰符 第二个*:匹配该类下的所有方法 -->
		<aop:pointcut expression="execution(* tqb.aop.User.*(..))" id="userPointcut"/>
		<!-- 配置切面(把增强用到切入点的过程) ref:增强类的id值 method:增强类的方法 pointcut-ref:切入点 -->
		 <aop:aspect ref="myUser">
		 	<!-- 前置增强 -->
		 	<aop:before method="before" pointcut-ref="userPointcut"/>
		 	<!-- 后置增强 -->
		 	<aop:after-returning method="after" pointcut-ref="userPointcut" />
		 	<!-- 环绕增强 -->
		 	<aop:around method="around" pointcut-ref="userPointcut"/>
		 </aop:aspect>
	</aop:config>
</beans>
  1. 目标对象(要增强的类)
/** * 被增强的类 * @author tqb * */
public class User {
	public void add(){
		System.out.println("add............");
	}
}
  1. 增强的内容
public class MyUser {
	public void before(){
		System.out.println("前置增强。。。。。。。。。");
	}
	
	public void after(){
		System.out.println("后置增强。。。。。。。。。");
	}
	
	public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
		System.out.println("环绕通知。。。。。。。。前");
		
		//执行被增强的方法
		proceedingJoinPoint.proceed();
		
		System.out.println("环绕通知。。。。。。。。后");
	}
}
  1. 测试类
public class TestDemo {
	@Test
	public void fun(){
		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		User user = (User) context.getBean("user");
		user.add();
	}
}