[Java] Spring_1400_AOP_Introduction
13, AOP
@1, 慎用继承 (因为继承直接就写死了!)
经常组合代替了继承,组合灵活性更高!
@2, Spring 解决了单例的问题
动态代理 jdk 如果想产生动态代理,那么这个类就需要实现一个接口,没有implements接口的类,JDK是给它产生不了动态代理的。
jdk proxy invocationhander
package com.bjsxt.aop;
LogInterceptor 很好!很好!写的!
package com.bjsxt.aop; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class LogInterceptor implements InvocationHandler { private Object target; public Object getTarget() { return target; } public void setTarget(Object target) { this.target = target; } public void beforeMethod(Method m) { System.out.println(m.getName() + " start"); } public Object invoke(Object proxy, Method m, Object[] args) throws Throwable { beforeMethod(m); m.invoke(target, args); return null; } }
package com.bjsxt.dao;
interface UserDAO
package com.bjsxt.dao; import com.bjsxt.model.User; public interface UserDAO { public void save(User user); public void delete(); }package com.bjsxt.dao.impl;
UserDAOImpl
package com.bjsxt.dao.impl; import com.bjsxt.dao.UserDAO; import com.bjsxt.model.User; public class UserDAOImpl implements UserDAO { public void save(User user) { //Hibernate //JDBC //XML //NetWork System.out.println("user saved!"); } public void delete() { System.out.println("user deteleted"); } }UserDAOImpl2 extends UserDAOImpl 继承的方式
package com.bjsxt.dao.impl; import com.bjsxt.model.User; public class UserDAOImpl2 extends UserDAOImpl { @Override public void save(User user) { System.out.println("save start..."); super.save(user); } }UserDAOImpl3 implements UserDAO 实现接口的方式
package com.bjsxt.dao.impl; import com.bjsxt.aop.LogInterceptor; import com.bjsxt.dao.UserDAO; import com.bjsxt.model.User; public class UserDAOImpl3 implements UserDAO { private UserDAO userDAO = new UserDAOImpl(); public void save(User user) { new LogInterceptor().beforeMethod(null); userDAO.save(user); } public void delete() { // TODO Auto-generated method stub } }packagecom.bjsxt.model;
User (用户类 : 具有 名字 和 密码 两个属性)
package com.bjsxt.model; public class User { private String username; private String password; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }package com.bjsxt.service;
UserService 用户服务层
package com.bjsxt.service; import com.bjsxt.dao.UserDAO; import com.bjsxt.model.User; public class UserService { private UserDAO userDAO; public void add(User user) { userDAO.save(user); } public UserDAO getUserDAO() { return userDAO; } public void setUserDAO(UserDAO userDAO) { this.userDAO = userDAO; } }packagecom.bjsxt.spring;
interface BeanFactory
package com.bjsxt.spring; public interface BeanFactory { public Object getBean(String id); }ClassPathXmlApplicationContext
package com.bjsxt.spring; import java.lang.reflect.Method; import java.util.HashMap; import java.util.List; import java.util.Map; import org.jdom.Document; import org.jdom.Element; import org.jdom.input.SAXBuilder; public class ClassPathXmlApplicationContext implements BeanFactory { private Map<String , Object> beans = new HashMap<String, Object>(); //IOC Inverse of Control DI Dependency Injection public ClassPathXmlApplicationContext() throws Exception { SAXBuilder sb=new SAXBuilder(); Document doc=sb.build(this.getClass().getClassLoader().getResourceAsStream("beans.xml")); //构造文档对象 Element root=doc.getRootElement(); //获取根元素HD List list=root.getChildren("bean");//取名字为disk的所有元素 for(int i=0;i<list.size();i++){ Element element=(Element)list.get(i); String id=element.getAttributeValue("id"); String clazz=element.getAttributeValue("class"); Object o = Class.forName(clazz).newInstance(); System.out.println(id); System.out.println(clazz); beans.put(id, o); for(Element propertyElement : (List<Element>)element.getChildren("property")) { String name = propertyElement.getAttributeValue("name"); //userDAO String bean = propertyElement.getAttributeValue("bean"); //u Object beanObject = beans.get(bean);//UserDAOImpl instance String methodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1); System.out.println("method name = " + methodName); Method m = o.getClass().getMethod(methodName, beanObject.getClass().getInterfaces()[0]); m.invoke(o, beanObject); } } } public Object getBean(String id) { return beans.get(id); } }beans.xml
<beans> <bean id="u" class="com.bjsxt.dao.impl.UserDAOImpl" > </bean> <bean id="userService" class="com.bjsxt.service.UserService" > <property name="userDAO" bean="u"/> </bean> </beans>Test 目录
package com.bjsxt.service;
package com.bjsxt.service; import java.lang.reflect.Proxy; import org.junit.Test; import com.bjsxt.aop.LogInterceptor; import com.bjsxt.dao.UserDAO; import com.bjsxt.dao.impl.UserDAOImpl; import com.bjsxt.model.User; import com.bjsxt.spring.BeanFactory; import com.bjsxt.spring.ClassPathXmlApplicationContext; public class UserServiceTest { @Test public void testAdd() throws Exception { BeanFactory applicationContext = new ClassPathXmlApplicationContext(); UserService service = (UserService)applicationContext.getBean("userService"); User u = new User(); u.setUsername("zhangsan"); u.setPassword("zhangsan"); service.add(u); } @Test public void testProxy() { UserDAO userDAO = new UserDAOImpl(); LogInterceptor li = new LogInterceptor(); li.setTarget(userDAO); UserDAO userDAOProxy = (UserDAO)Proxy.newProxyInstance(userDAO.getClass().getClassLoader(), userDAO.getClass().getInterfaces(), li); System.out.println(userDAOProxy.getClass()); userDAOProxy.delete(); userDAOProxy.save(new User()); } /*class $Proxy4 implements UserDAO * { * save(User u) { * Method m = UserDAO.getclass.getmethod * li.invoke(this, m, u) * } * } */ }
14,
UserDAO userDAO = new UserDAOImpl();
LogInterceptor li = new LogInterceptor();
li.setTarget(userDAO);
UserDAO userDAOProxy = (UserDAO)Proxy.newProxyInstance(userDAO.getClass().getClassLoader(), userDAO.getClass().getInterfaces(), li);
(1), 产生的代理对象的 classLoader 和 被代理对象的 classLoader 要一样,因为代理对象中有一个 被代理对象,所以需要互相访问。
(2), userDAO.getClass().getInterfaces() 代理类(对象) 要实现这个接口。
(3), 第三个参数,代理用哪一个 Handler 进行处理。
(4), 因为代理类实现了 UserDAO 接口,抽象主题,所以进行强制转换。(UserDAO)
System.out.println(userDAOProxy.getClass());
userDAOProxy.delete();
userDAOProxy.save(new User());
写程序推荐,面向接口编程。