spring注解、aop(二)
使用注解配置spring
1.导入 spring-aop-5.0.6.RELEASE.jar包
2.为主配置文件引入新的命名空间 xmlns:context="http://www.springframework.org/schema/context"
<?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-4.0.xsd"> <!--指定扫描com.david.bean下的所有包所有类中的注解 -->
<context:component-scan base-package="com.david.bean"></context:component-scan> </beans>
3.在类中使用注解
@Component("user")
//相当于<bean name="user" class="com.david.bean.User" />
public class User {
private String name;
private Integer age;
private Car car; ...
}
注解后来又出现了三种,可以体现层级关系
@Component("user")
@Service("user") //service层
@Controller("user") //web层
@Repository("user") //dao层
指定作用范围
@Component("user")
//相当于<bean name="user" class="com.david.bean.User" />
@Scope(scopeName = "prototype")
//相当于<bean name="user" class="com.david.bean.User" scope="prototype"></bean>
值类型注入
public class User {
@Value("david") //字段注入 破坏了封装性
private String name;
private Integer age;
private Car car; @Value("18") //set方法注入 推荐使用
public void setAge(int age) {
this.age = age;
}
...
}
引用类型(对象)注入
@Component("car")
public class Car {
@Value("奥拓")
private String name;
@Value("red")
private String color;
...
}
@Component("user")
public class User {
@Autowired //自动装配 对象注入
private Car car;
...
}
@autowired 自动装配的方式 如果匹配到多个类型一致的对象,无法选择具体注入哪一个对 如:
<bean name="car2" class="com.david.bean.Car">
<property name="name" value="奥迪"></property>
<property name="color" value="black"></property>
</bean>
此时需要使用@Qualifier("car2")注解告诉容器具体注入哪个对象 和@autowired一起使用
@Autowired
@Qualifier("car2")
private Car car;
上面这种要使用两个注解,还有一个注解@Resource 可以手动指定注入哪个对象
@Resource(name="car2") //手动指定
private Car car;
初始化和销毁
public class User {
...
@PostConstruct //相当于init-method 对象创建后调用
public void init(){
System.out.println("init");
} @PreDestroy //销毁前调用 相当于destory-method
public void destory(){
System.out.println("destory");
}
...
}
aop:面向切面编程,是对oop面向对象编程的补充和完善。
spring中的aop
spring能够为容器中管理的对象生成动态代理对象。
spring实现aop的原理
1.动态代理(优先使用)
被代理对象必须要实现接口,才能产生代理对象,如果没有接口将不能使用动态代理技术
2.cglib代理(没有接口时)
第三方代理技术,可以对任何类生成代理对象。代理的原理是对目标对象进行继承代理
spring AOP 名词解释:
1.Joinpoint连接点:目标对象中,所有可以增强的方法。(可以增强的方法)如:UserServiceImpl implements UserService 中实现的方法 save() delete()
2.Pointcut切入点:目标对象中,已经增强的方法。(已增强的方法)如:已通过代理增强的save() 或delete() 可以单独指定某些增强或不增强。
3.Advice通知/增强:需要增强的代码。(代理对象调用目标方法前后执行的代码)如://前增强 method.invoke(us,arg) //后增强。
4.Target目标对象:被代理对象。如UserServiceImpl。
5.Weaving织入:将通知织入(应用到)切入点的过程。
6.Proxy代理:将通知织入道目标对象之后,形成代理对象。
所以进行AOP编程的关键就是定义切入点和定义增强处理,一旦定义了合适的切入点和增强处理,AOP框架将自动生成AOP代理,即:代理对象的方法=增强处理+被代理对象的方法。
基于spring的aop实现
1.导包 aopalliance.jar aspectjweaver.jar spring aop需要这两个包的支持 下载地址:
http://www.java2s.com/Code/Jar/a/Downloadaopalliancejar.htm
http://www.java2s.com/Code/Jar/a/Downloadaspectjweaverjar.htm
2.准备目标对象
先定义一个接口
public interface IHelloWorld {
void printHelloWorld();
void doPrint();
}
在定义两个接口实现类
public class HelloWorldImpl1 implements IHelloWorld
{
public void printHelloWorld()
{
System.out.println("Enter HelloWorldImpl1.printHelloWorld()");
} public void doPrint()
{
System.out.println("Enter HelloWorldImpl1.doPrint()");
return ;
}
} public class HelloWorldImpl2 implements IHelloWorld{
public void printHelloWorld()
{
System.out.println("Enter HelloWorldImpl2.printHelloWorld()");
} public void doPrint()
{
System.out.println("Enter HelloWorldImpl2.doPrint()");
return ;
}
}
3.准备通知
package com.david.bean; import org.aspectj.lang.ProceedingJoinPoint; public class MyAdvice {
//前置通知-目标方法调用之前调用
public void before() {
System.out.println("前置通知");
} //后置通知-目标方法之后调用,如果异常不会调用
public void afterRuning() {
System.out.println("后置通知,出现异常不会调用");
} //环绕通知-在目标方法之前和之后都调用
public void around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("环绕前通知");
Object proceed = pjp.proceed();//调用目标方法
System.out.println("环绕后通知");
} //异常通知-如果出现异常就会被调用
public void afterException(){
System.out.println("出现异常");
} //后置通知-目标方法之后调用,无论异常与否都会调用
public void after() {
System.out.println("后置通知,无论异常与否都会调用");
}
}
4.配置进行织入,将通知织入目标对象中
新建一个aop.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--导入aop命名空间 -->
<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:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">
<!--配置目标对象 -->
<bean id="helloWorldImpl1" class="com.david.bean.HelloWorldImpl1" />
<bean id="helloWorldImpl2" class="com.david.bean.HelloWorldImpl2" />
<!--配置通知对象 -->
<bean id="myAdvice" class="com.david.bean.MyAdvice" />
<!--配置将通知织入目标对象 -->
<aop:config>
<!--配置切入点:所有方法都增强 -->
<aop:pointcut id="allMethod" expression="execution(* com.david.bean.IHelloWorld.*(..))"></aop:pointcut>
<aop:aspect id="advice" ref="myAdvice">
<!--通知方法 -->
<aop:before method="before" pointcut-ref="allMethod" />
<aop:after-returning method="afterRuning" pointcut-ref="allMethod"></aop:after-returning>
<aop:around method="around" pointcut-ref="allMethod"></aop:around>
<aop:after method="after" pointcut-ref="allMethod" />
</aop:aspect>
</aop:config>
</beans>
5.编写测试类
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("aop.xml"); IHelloWorld hw1 = (IHelloWorld)ac.getBean("helloWorldImpl1");
IHelloWorld hw2 = (IHelloWorld)ac.getBean("helloWorldImpl2");
hw1.printHelloWorld();
System.out.println();
hw1.doPrint(); System.out.println();
hw2.printHelloWorld();
System.out.println();
hw2.doPrint();
}
使用spring aop开发 就不需要我们手写动态代理代码了,还封装了cglib代理。可以对任何类进行代理增强。
spring的aop注解配置
<?xml version="1.0" encoding="UTF-8"?>
<!--导入aop命名空间 -->
<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:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">
<!--配置目标对象 -->
<bean id="helloWorldImpl1" class="com.david.bean.HelloWorldImpl1" />
<bean id="helloWorldImpl2" class="com.david.bean.HelloWorldImpl2" />
<!--配置通知对象 -->
<bean id="myAdvice" class="com.david.bean.MyAdvice" /> <!--开启使用注解织入目标对象 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy> </beans>
通知类 使用注解设置
@Aspect //表示该类是一个通知类
public class MyAdvice {
@Before("execution(* com.david.bean.IHelloWorld.*(..))") //是一个前置通知并指定切入点
public void before() {
System.out.println("前置通知");
}
@After("execution(* com.david.bean.IHelloWorld.*(..))")
public void after() {
System.out.println("后置通知,无论异常与否都会调用");
} @AfterReturning("execution(* com.david.bean.IHelloWorld.*(..))")
public void afterRuning() {
System.out.println("后置通知,出现异常不会调用");
} @Around("execution(* com.david.bean.IHelloWorld.*(..))")
public void around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("环绕前通知");
Object proceed = pjp.proceed();//调用目标方法
System.out.println("环绕后通知");
} }
再次运行 效果一样的。 抽取切入点
package com.david.bean; import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*; @Aspect //表示该类是一个通知类
public class MyAdvice {
//定义一个切入点规则
@Pointcut("execution(* com.david.bean.IHelloWorld.*(..))")
public void pc(){ } @Before("MyAdvice.pc()")
public void before() {
System.out.println("前置通知");
}
@After("MyAdvice.pc()")
public void after() {
System.out.println("后置通知,无论异常与否都会调用");
} @AfterReturning("MyAdvice.pc()")
public void afterRuning() {
System.out.println("后置通知,出现异常不会调用");
} @Around("MyAdvice.pc()")
public void around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("环绕前通知");
Object proceed = pjp.proceed();//调用目标方法
System.out.println("环绕后通知");
} }
spring注解、aop(二)的更多相关文章
- Spring 注解(二)注解工具类 AnnotationUtils 和 AnnotatedElementUtils
Spring 注解(二)注解工具类 AnnotationUtils 和 AnnotatedElementUtils Spring 系列目录(https://www.cnblogs.com/binary ...
- Spring 注解(二)注解工具类
本文转载自Spring 注解(二)注解工具类 导语 首先回顾一下 AnnotationUtils 和 AnnotatedElementUtils 这两个注解工具类的用法: @Test @GetMapp ...
- Spring之AOP二
在Spring之AOP一中使用动态代理将日志打印功能注入到目标对象中,其实这就是AOP实现的原理,不过上面只是Java的实现方式.AOP不管什么语言它的几个主要概念还是有必要了解一下的. 一.AOP概 ...
- Spring学习(六)—— Spring注解(二)
核心原理 1. 用户发送请求给服务器.url:user.do 2. 服务器收到请求.发现Dispatchservlet可以处理.于是调用DispatchServlet. 3. ...
- Spring注解 - AOP 面向切面编程
基本概念: AOP:Aspect Oriented Programming,即面向切面编程 指在程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式 前置通知(@Before):在目标 ...
- 基于spring注解AOP的异常处理
一.前言 项目刚刚开发的时候,并没有做好充足的准备.开发到一定程度的时候才会想到还有一些问题没有解决.就比如今天我要说的一个问题:异常的处理.写程序的时候一般都会通过try...catch...fin ...
- Spring注解AOP及单元测试junit(6)
2019-03-10/20:19:56 演示:将xml配置方式改为注解方式 静态以及动态代理推荐博客:https://blog.csdn.net/javazejian/article/details/ ...
- spring 注解AOP
aspectAnnotation的切面信息,加到了AnnotationAwareAspectJAutoProxyCreator的advisorsCache属性里面去了. 解析annotationSe ...
- 重新学习Spring注解——AOP
面向切面编程——思想:在一个地方定义通用功能,但是可以通过声明的方式定义这个功能要以何种方式在何处运用,而无须修改受影响的类. 切面:横切关注点可以被模块化为特殊的类. 优点: 1.每个关注点都集中在 ...
- spring注解 aop
@Resource(name="as") 为空按类型装配 @autowired 按类型 @quafiler (name="xx") 按名称 spring继承关 ...
随机推荐
- yagmail邮件模块
昨天接到一个需求,就是要求用邮件发送一html文件.这里我想到了用yagmail #!/usr/bin/env python #-*- coding:utf-8 -*- import yagmail ...
- 关于JS闭包的一点理解
通常来讲,闭包通常是指函数内部可以访问到外部作用域的一个过程. 一.广义的定义:任何函数都产生了闭包. 二.狭义的定义:函数内部能访问到其他变量函数的作用域. 我们来看个例子 var a = 10; ...
- sysbench基准测试工具
一.简介SysBench是一个模块化的.跨平台.多线程基准测试工具,主要用于评估测试各种不同系统参数下的数据库负载情况.当前功能允许测试的系统参数有:file I/O performance (文件I ...
- awk 新手入门笔记
转自:http://www.habadog.com/2011/05/22/awk-freshman-handbook/ awk新手入门笔记 @作者 : habadog@邮箱 : habadog1203 ...
- Python学习【第7篇】:Python之常用模块2
hashlib,configparser,logging模块 一.常用模块二 hashlib模块 hashlib提供了常见的摘要算法,如md5和sha1等等. 那么什么是摘要算法呢?摘要算法又称为哈希 ...
- 原型&&原型链一语道破梦中人
一直对原型和原型链模模糊糊,今天看到一句话,通过这句话再结合我目前对原型和原型链的理解算是让我对原型和原型链有一个更清醒的认识;并且记忆更加深刻; 任何一个对象都有一个隐式原型:__proto__属性 ...
- odoo 权限杂记
最近做一个任务督办模块,涉及到一些权限问题,折磨了几天,终于是解决了. 任务表中关联了hr_employee,分别有默认字段创建人,Many2one的发布人.监督人和Many2many类型的主责人,这 ...
- 【codeforces 768D】Jon and Orbs
[题目链接]:http://codeforces.com/contest/768/problem/D [题意] 你有一个水晶; 它每天都会产生一个球??(球有k种) 然后每种球产生的可能性是相同的-& ...
- centos7.0_redhat7.0安装vncserver和Desktop桌面
http://blog.51cto.com/gushiren/1681616 https://blog.csdn.net/techsupporter/article/details/50628399
- pg 学习资料
文/谭峰 DBA,PostgreSQL专家 开源数据库 PostgreSQL 中文资料非常缺乏,很多社区朋友苦于上手的中文资料少,因此汇总收集以下 PostgreSQL 中文资料,包括 Postgre ...