关注点代码,就是指重复执行的代码。
业务代码与关注点代码分离,好处?
--à 关注点代码写一次即可;
-à开发者只需要关注核心业务;
-à运行时期,执行核心业务代码时候动态植入关注点代码; 【代理】
Aop, aspect object programming 面向切面编程
功能: 让关注点代码与业务代码分离!
关注点,
重复代码就叫做关注点;
切面,
关注点形成的类,就叫切面(类)!
面向切面编程,就是指 对很多功能都有的重复的代码抽取,再在运行的时候网业务方法上动态植入“切面类代码”。
切入点,
执行目标对象方法,动态植入切面代码。
可以通过切入点表达式,指定拦截哪些类的哪些方法; 给指定的类在运行的时候植入切面类代码。
package loaderman.d_myaop; import org.springframework.stereotype.Component; @Component // 加入IOC容器 public class Aop { // 重复执行的代码 public void begin(){ System.out.println("开始事务/异常"); } public void commite(){ System.out.println("提交事务/关闭"); } }
package loaderman.d_myaop; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class App { ApplicationContext ac = new ClassPathXmlApplicationContext("loaderman/d_myaop/bean.xml"); @Test public void testApp() { IUserDao userDao = (IUserDao) ac.getBean("userDao"); userDao.save(); } }
package loaderman.d_myaop; // 接口 public interface IUserDao { void save(); }
package loaderman.d_myaop; import javax.annotation.Resource; import org.springframework.stereotype.Component; /** * 目标对象 * */ @Component // 加入容器 public class UserDao implements IUserDao{ // 重复执行代码形成的一个类 @Resource private Aop aop; @Override public void save() { aop.begin(); System.out.println("-----核心业务:保存!!!------"); aop.commite(); } }
<?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: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"> <!-- 开启注解扫描 --> <context:component-scan base-package="loaderman.d_myaop"></context:component-scan> </beans>
package loaderman.d_myaop1; import org.springframework.stereotype.Component; @Component // 加入IOC容器 (切面) public class Aop { // 重复执行的代码 public void begin(){ System.out.println("开始事务/异常"); } public void commite(){ System.out.println("提交事务/关闭"); } }
package loaderman.d_myaop1; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class App { ApplicationContext ac = new ClassPathXmlApplicationContext("loaderman/d_myaop1/bean.xml"); @Test public void testApp() { IUserDao userDao = (IUserDao) ac.getBean("userDao_proxy"); System.out.println(userDao.getClass()); userDao.save(); } }
package loaderman.d_myaop1; public interface IUserDao { void save(); }
package loaderman.d_myaop1; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * 代理工厂 * */ public class ProxyFactory { // 目标对象 private static Object target; private static Aop aop; // 生成代理对象的方法 public static Object getProxyInstance(Object target_,Aop aop_){ target = target_; aop = aop_; return Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { aop.begin();// 执行重复代码 // 执行目标对象的方法 Object returnValue = method.invoke(target, args); aop.commite(); // 执行重复代码 return returnValue; } }); } }
package loaderman.d_myaop1; import org.springframework.stereotype.Component; /** * 目标对象 * */ @Component // 加入容器 public class UserDao implements IUserDao{ @Override public void save() { System.out.println("-----核心业务:保存!!!------"); } }
<?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: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"> <!-- 开启注解扫描 --> <context:component-scan base-package="loaderman.d_myaop1"></context:component-scan> <!-- 调用工厂方法,返回UserDao代理后的对象 --> <bean id="userDao_proxy" class="loaderman.d_myaop1.ProxyFactory" factory-method="getProxyInstance"> <constructor-arg index="0" ref="userDao"></constructor-arg> <constructor-arg index="1" ref="aop"></constructor-arg> </bean> </beans>