为什么要学习spring?
spring提供了ioc容器,不需要自己创建和管理对象,由spring来创建和管理。
spring提供了面向切面编程,不修改源代码的情况下对功能进行增强。
spring提供了事务支持,使事务 *** 作变得更加方便。
spring方便集成其他框架,例如mybatis。
IOC
控制反转,由spring来创建对象以及对象之间的调用。最主要的作用就是降低耦合度。
传统方式:
class A{ class B{
add(){ put(){}
B b = new B(); }
b.put();
}
}
工厂模式:
class A{ class B{
add(){ put(){}
B b =Factory.getB() }
b.put();
}
}
class Factory{
public static B getB(){
return new B();
}
}
耦合度不可能不存在,只能是降低到最小。
IOC底层原理:
ioc主要是由xml解析、工厂模式以及反射实现的。
1.在xml文件里配置要创建的对象
2.创建工厂类
class Factory{
public static B getB(){
String classValue =类路径 //这是由xml解析得到的
Class clazz =Class.forName(classValue); //反射机制,通过类名得到该类的字节码文件
return (强转)clazz.newInstance(); //newInstance()方法默认调用类的空参构造器创建对象
}
ioc容器底层的本质就是对象工厂。
基于注解方式创建对象以及注入属性
创建对象的注解
@Component 普通组件
@Controller 用于web层
@Service 用于业务逻辑层
@Repository 用于持久层(数据层)
属性注入(对象类型的属性)
@AutoWired (最常用) 根据属性类型自动注入
@Qualifier 根据属性名称注入,这个注解需要和@AutoWired 一起使用,当一个接口有多个实现类,仅@AutoWired无法确定是注入哪个实现类的对象,需要用 @Qualifier (value="类名小写")
@Resource 可以根据类型或名称注入
@AutoWired 和@Resource 的区别:
@AutoWired默认按照属性类型注入,根据名称需要加@Qualifier
@Resource默认按照属性名称注入,名称找不到才会按照属性类型注入。
AOP
面向切面编程
底层原理(动态代理)
1.有接口情况,使用jdk动态代理
public interface UserDao { public int add(int a, int b); public String update(String id); }
public class UserDaoImpl implements UserDao{ @Override public int add(int a, int b) { System.out.println("add方法执行了"); return a+b; } @Override public String update(String id) { System.out.println("update方法执行了"); return id; } }
创建代理对象需要用到Proxy类的newProxyInstance()方法,三个参数为类加载器,接口,InvocationHandler接口的实现类对象
public class JDKProxy { public static void main(String[] args) { Class[] interfaces = {UserDao.class}; UserDaoImpl userDao = new UserDaoImpl(); //接口等于实现类创建代理对象 UserDao dao =(UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao)); int result = dao.add(1, 2); System.out.println("result"+result); } } //创建代理对象代码 class UserDaoProxy implements InvocationHandler { //把需要增强的方法所在的类的对象传递过来 //通过有参构造传递 private Object obj; public UserDaoProxy(Object obj) { this.obj = obj; } //增强的逻辑代码 //proxy代表代理类,method是代理类和被代理的同名方法,args方法参数 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //方法之前的增加处理 System.out.println("方法之前执行"+method.getName()+":传递的参数.."+ Arrays.toString(args)); //被增加的方法的执行 Object res = method.invoke(obj, args); //方法之后的增加处理 System.out.println("方法之后输出"+obj); return res; } }
2.没有接口情况,使用cglib动态代理
public class UserDao { public void addUser() { System.out.println("添加方法"); } public void deleteUser() { System.out.println("删除方法"); } }
public class CglibProxy implements MethodInterceptor{ //创建代理方法 public Object createProxy(Object object) { //创建一个动态类对象 Enhancer enhancer = new Enhancer(); //确定需要增强的类 设置其父类 enhancer.setSuperclass(object.getClass()); //添加回调函数 enhancer.setCallback(this); //返回创建的代理类 return enhancer.create(); } //proxy cglib根据定义的父类生成的代理对象 //method 拦截的方法 //args 拦截的方法的参数数组 //methProxy 方法的代理对象 用于执行父类的方法 @Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methProxy) throws Throwable { //方法执行之前 //目标方法执行 Object obj = methProxy.invokeSuper(proxy, args); //方法执行之后 return obj; } }
public class CglibTest { public static void main(String[] args) { //创建代理对象 CglibProxy cglibProxy = new CglibProxy(); //创建目标对象 UserDao userDao = new UserDao(); //将目标对象传入代理对象中 获取增强后的方法 UserDao userDao2 = (UserDao) cglibProxy.createProxy(userDao); //执行 userDao2.addUser(); userDao2.deleteUser(); } }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)