通过注解方式进行bean管理准备
- jar包(红框内为aop操作需要的依赖)
- 引入约束
<?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>
- 开启注解扫描
<!-- 开启注解扫描(类、方法、属性) -->
<!-- base-package:扫描的包(即该包下的所有类、方法、属性都会进行扫描) -->
<context:component-scan base-package="tqb.anno.test"></context:component>
<!-- 了解(只扫描属性上的注解) -->
<!-- <context:spring-configured ></context:spring-configured> -->
注解方式进行bean管理
- 创建A类
@Component(value="a")
class A{
public void test(){
System.out.println("this is a anno test");
}
}
- 测试类
class TestDemo{
@Test
public void fun(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
A a = (A) context.getBean("a");
a.test();
}
}
创建对象的四个注解及其它注解
注:在Spring的开发中,开发人员为了之后对Spring的扩展,衍生出了三个注解,但目前功能一致,只不过用在不同层上,阅读起来更加的清晰,如上边的案例我们就可以将@Component换成下面的任意一个,但是功能不发生变化
- Web层:@Controller
- Service层:@Service
- 持久层:@Repository
- 其它注解:
1)@Scope(value=“prototype”):等同于下面的配置
<bean id="a" class="tqb.anno.test.A" scope="prototype"></bean>
注解方式注入属性
注:注入属性的注解方式除了@Autowired,还有@Resourse(name="")
- UserDao
@Component(value="userDao")
public class UserDao {
public void add(){
System.out.println("userDao............");
}
}
- UserService
@Component(value="userService")
public class UserSevice {
//自动装配
@Autowired
private UserDao userDao;
public void add(){
System.out.println("userService................");
userDao.add();
}
}
- 测试类
public class UserTest {
@Test
public void fun(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserSevice userService = (UserSevice) context.getBean("userService");
userService.add();
}
}
- @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();
}
}
配置文件和注解方式的混合使用
- 配置文件
<?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>
- OrderDao类
public class OrderDao {
public void add(){
System.out.println("OrderDao..........");
}
}
- OrderService类
public class OrderService {
@Resource(name="orderDao")
private OrderDao orderDao;
public void add(){
orderDao.add();
System.out.println("OrderService..........");
}
}
- 测试类
class OrderTest{
@Test
public void fun(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
OrderService orderService = (OrderService) context.getBean("orderService");
orderService.add();
}
}
AOP原理
- AOP:面向切面编程,即扩展功能时不修改源代码
- AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码
- AOP底层使用动态代理模式实现
1)存在接口,使用动态代理创建接口实现类代理对象
2)不存在接口,使用动态代理创建继承类的子类代理对象 - 图片理解(图片来源:传智播客)
AOP操作术语
- 连接点(Joinpoint):某个类中可以被增强的方法,称为连接点
- 切入点(Pointcut):我们要对哪些Pointcut进行拦截的定义,称为切入点。即真正被增强的方法
- 通知/增强(Advice):拦截到Joinpoint后要做的事情,称为通知/增强,有以下5个通知
1)前置通知
2)后置通知
3)异常通知
4)最终通知
5)环绕通知 - 切面(Aspect):切入点和通知的结合
- 引介(Introduction):引介是一种特殊的通知在不修改类代码的前提下, Introduction可以在运行期为类动态地添加一些方法或Field
- 目标对象(Target):代理的目标对象(要增强的类)
- 织入(Weaving):把增强应用到目标的过程
- 代理(Proxy):一个类被AOP织入增强后,就产生了一个结果代理类
Spring的AOP操作准备
- 在Spring中进行AOP操作,主要依赖AspectJ实现
1)AspectJ不是Spring的一部分,但是和Spring一起进行AOP操作
2)Spring2.0增加了对AspectJ的支持 - 使用AspectJ操作AOP的两种方式
1)xml配置
2)注解方式 - 进行AOP操作的jar包(红框内)
- 配置文件(引入约束)
<?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)execution(<访问修饰符>?<返回类型><方法名>(<参数>)<异常>)
2)execution(* cn.itcast.aop.Book.add(..))
3)execution(* cn.itcast.aop.Book.*(..))
4)execution(* *.*(..))
5)匹配所有save开头的方法execution(* save*(..))
AspectJ的AOP操作
- 配置文件内容
<?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>
- 目标对象(要增强的类)
/** * 被增强的类 * @author tqb * */
public class User {
public void add(){
System.out.println("add............");
}
}
- 增强的内容
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("环绕通知。。。。。。。。后");
}
}
- 测试类
public class TestDemo {
@Test
public void fun(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User) context.getBean("user");
user.add();
}
}