面向切面的编程(AOP)
目前我对面向对象的理解是:
动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程
可以和面向对象的编程做对比,具体百度百科就描述的不错,所以我就不赘述了。
而面向对象的编程是通过动态代理实现的。
下面通过一个简单示例通了解一下面向对象编程的思想。
一.面向切面编程的引入
1.1创建Person类
package edu.xatu;
import org.springframework.stereotype.Repository;
@Repository
public class Person implements PersonInterface {
public void travel (){
System.out.println ("旅游");
}
public void work (){
System.out.println ("上班");
}
public void visit (){
System.out.println ("探亲");
}
}
@Repository注解的作用是实例化对象Person,来自lombok插件
@Controller 主要用到web层
@Service 服务service层
@Repository 数据访问层 dao层
1.1.2 @Autowired、@Qualifier(“ser”)、@Resource
- 首先所有装配的对象要先实例化到工厂当中
- 其次可以通过三个注解实现依赖注入
- @Autowired 根据类型装配
- @Qualifier(“ser”) 和@Autowired结合使用,根据名称进行装配
- @Resource相当中@Autowired加@Qualifier(“ser”),即可根据类型进行装配,也可以根据名称进行装配
1.2生成person的接口PersonInterface
package edu.xatu;
public interface PersonInterface {
void travel ();
void work ();
void visit ();
}
1.3创建personService
package edu.xatu;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component
public class PersonService {
@Resource(name = "sss")
private Ser ser;
@Resource
private Student student;
@Resource
private Person person;
public void service(){
ser.getdress ();
ser.eatbreakfirst ();
person.travel ();
ser.getdress ();
ser.eatbreakfirst ();
person.visit ();
ser.getdress ();
ser.eatbreakfirst ();
person.work ();
student.havelesson ();
}
}
1.4创建Ser类
package edu.xatu;
import org.springframework.stereotype.Component;
@Component("sss")
public class Ser {
public void getdress(){
System.out.println ("穿衣服");
}
public void eatbreakfirst(){
System.out.println ("吃早饭");
}
}
1.5创建Student类
package edu.xatu;
import org.springframework.stereotype.Component;
@Component
public class Student implements StudentInterface {
public void havelesson (){
System.out.println ("上课");
}
}
1.6生成Student接口StudentInterface
package edu.xatu;
public interface StudentInterface {
void havelesson ();
}
1.7测试
package edu.xatu;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test1 {
public static void main (String[] args) {
//创建工厂
BeanFactory factory = new ClassPathXmlApplicationContext ( "applicationContext.xml" );
PersonService personService = factory.getBean ( PersonService.class );
personService.service ();
}
}
1.8配置文件applicationContext.xml添加内容:
<context:component-scan base-package="edu.xatu"/>
component-scan是component-scanner的缩写,表示组件扫描,整体意思是从包edu.xatu开始逐一扫描类。
1.9测试结果:
由1.3中的service方法可知,相同代码重复出现:
ser.getdress ();
ser.eatbreakfirst ();
为了避免这种动作代码重复出现,优化代码风格,采取类似于Filter(过滤器)这种想法编程,也就是面向切面的编程,虽然不全面,意思到了就行。
二.首先引入动态代理
2.1创建动态代理类
package edu.xatu;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class DynamicProxy implements InvocationHandler {
private Object target; //目标对象
public DynamicProxy(Object target){
this.target = target;
}
//动态代理所执行的代码如下
public Object invoke (Object proxy, Method method, Object[] args) throws Throwable {
//因为在这儿没法注入,所以只能new
Ser ser = new Ser ();
ser.getdress ();
ser.eatbreakfirst ();
return method.invoke ( target,args );
}
public Object createProxy(){
//创建代理
return Proxy.newProxyInstance ( this.getClass ().getClassLoader (),
target.getClass ().getInterfaces (),
this);//this.getClass ().getClassLoader ()类加载器
}
}
2.2修改PersonInterface类:
package edu.xatu;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component
public class PersonService {
private PersonInterface person = (PersonInterface) new DynamicProxy (new Person () ).createProxy (); //注入的是person对象
private StudentInterface student = (StudentInterface) new DynamicProxy ( new Student () ).createProxy ();
public void service(){
student.havelesson ();
person.travel ();
person.visit ();
person.work ();
}
}
其他类注解删掉即可