package com.jt.demo8;public interface Pet {void hello();}
package com.jt.demo8;import org.springframework.stereotype.Component;@Component //将该类交给Spring容器管理 key:dog(当前类别首字母小写),value:反射机制创建对象
public class Dog implements Pet{public Dog(){System.out.println("Dog的无参构造");}@Overridepublic void hello() {System.out.println("小狗汪汪汪!!!");}
}
package com.jt.demo8;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component//将User对象交给Spring容器管理
public class User {public User(){System.out.println("我是User的无参构造");}/*** 注入:将spring容器中的对象进行引用* @Autowired: 可以将容器中对象进行注入* 1.按照类型注入* 如果注入的类型是接口,则自动的查找其实现类对象进行注入* 注意事项:一般spring框架内部的接口都是单实现,特殊条件下可以多实现* 2.按照名称注入*/@Autowiredprivate Pet pet;public void hello(){pet.hello();}}
package com.jt.demo8;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;@ComponentScan("com.jt.demo8")
@Configuration
public class SpringConfig {}
package com.jt.demo8;import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class SpringDI {public static void main(String[] args) {ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);User user = applicationContext.getBean(User.class);user.hello();}
}
Spring容器启动,加载配置类SpringConfig;
配置类SpringConfig扫描包,全局扫描,扫描到dog类;
把dog类利用反射的机制,创建对象,会调用dog的无参构造方法;
key指定为dog(当前类名小写),value:反射机制创建的对象
继续扫描,扫描到User类,
扫描到@Autowired,找到Pet接口的实现类dog,并注入给User的pet属性
把User交给Spring容器管理
一般条件下 Spring中的接口,都是单实现,如果遇到多实现,则如图所示
由于没有做其它操作,所以程序必然报错.
异常解决:
User.java
说明: 如果将所有的业务代码都写到一个方法中,则导致后期维护耦合性高,为了提高程序的扩展性.将程序按照MVC设计思想 进行管理.
M: Model 数据层
V: View 视图层
C: Control 控制层
总结: MVC 主要的目的降低代码的耦合性,提高扩展性.方便后续开发.
说明: 基于MVC设计思想的启发,在后端为了提高代码的扩展性,一般将后端代码分为三层.
分层:
包名: mapper 类2个 一个接口UserMapper/一个实现类 UserMapperImpl
包名: service 类2个 一个接口UserService/ 一个实现类UserServiceImpl
包名: controller 一个类: UserController
知识说明: 被调用的一般会有接口和实现类
1.编辑UserMapper
package com.jt.demo9.mapper;public interface UserMapper {void addUser();}
2.编辑Mapper 实现类
package com.jt.demo9.mapper;import org.apache.catalina.User;
import org.springframework.stereotype.Repository;@Repository//表示持久层 该类交给Spring容器管理 key:userMapperImpl value:对象
public class UserMapperImpl implements UserMapper {@Overridepublic void addUser() {System.out.println("新增用户成功!!!!");}
}
package com.jt.demo9.service;public interface UserService {void addUser();
}
2.编辑UserServiceImpl
package com.jt.demo9.service;import com.jt.demo9.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class UserServiceImpl implements UserService{@Autowiredprivate UserMapper userMapper;//IOC+DI 解耦!!!!@Overridepublic void addUser() {userMapper.addUser();}
}
package com.jt.demo9.controller;import com.jt.demo9.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;@Controller//key=userController
public class UserController {@Autowiredprivate UserService userService;public void addUser(){userService.addUser();}
}
package com.jt.demo9.config;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;@ComponentScan("com.jt.demo9")
@Configuration
public class SpringConfig {}
package com.jt.demo9;import com.jt.demo9.config.SpringConfig;
import com.jt.demo9.controller.UserController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class Spring_MVC {public static void main(String[] args) {ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);UserController userController = applicationContext.getBean(UserController.class);userController.addUser();}}
# 1.数据结构 key=value
# 2.无需添加多余的引号
# 3.注意多余的空格
# 4.程序读取properties文件时,默认采用ISO-8859-1编码!中文必定乱码
name=张三
package com.jt.demo10.mapper;public interface UserMapper {void addUser();
}
package com.jt.demo10.mapper;import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Repository;//Spring根据指定的路径,加载properties配置文件 数据添加到Spring容器中
@PropertySource(value = "classpath:/addUser.properties",encoding = "UTF-8")
@Repository
public class UserMapperImpl implements UserMapper{/*** @Value 注解的作用:为属性赋值* 需求:从Spring容器中动态获取数据*///@Value("张三")//直接写法,扩展性不好@Value("${name}")private String name;@Overridepublic void addUser() {System.out.println("新增用户:"+name);}
}
package com.jt.demo10;import com.jt.demo10.config.SpringConfig;
import com.jt.demo10.mapper.UserMapper;
import com.jt.demo10.mapper.UserMapperImpl;import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class SpringValue {public static void main(String[] args) {ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);//获取的对象 实现类和接口都可以
// UserMapper userMapper = applicationContext.getBean(UserMapperImpl.class);UserMapper userMapper = applicationContext.getBean(UserMapper.class);userMapper.addUser();}
}
总结: 使用IOC-DI可以极大程度上实现代码的松耦合(解耦)
2. 勾选jar包
2.2 AOP代码铺垫
2.2.1 业务说明
事务特性: 1. 原子性 2. 一致性 3.隔离性 4.持久性
业务说明: 在增/删除/修改的操作过程中添加事务控制.
Demo效果演示
配置类
package com.jt.demo1.config;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;@ComponentScan("com.jt.demo1")
@Configuration
public class SpringConfig {}
Service层
service层接口
package com.jt.demo1.service;public interface UserService {void addUser();void deleteUser();
}
service层实现类
package com.jt.demo1.service;import org.springframework.stereotype.Service;@Service
public class UserServiceImpl implements UserService {@Overridepublic void addUser() {System.out.println("完成用户新增");}@Overridepublic void deleteUser() {System.out.println("完成用户删除操作");}
}
测试类
package com.jt.demo1;import com.jt.demo1.config.SpringConfig;
import com.jt.demo1.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class SpringTx {public static void main(String[] args) {ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);UserService userService = applicationContext.getBean(UserService.class);userService.addUser();userService.deleteUser();}
}
service层实现类
package com.jt.demo1.service;import org.springframework.stereotype.Service;@Service
public class UserServiceImpl implements UserService {@Overridepublic void addUser() {try {System.out.println("事务开始");System.out.println("完成用户新增");System.out.println("事务提交");} catch (Exception e) {e.printStackTrace();System.out.println("事务回滚");}}@Overridepublic void deleteUser() {try {System.out.println("事务开始");System.out.println("完成用户删除操作");System.out.println("事务提交");} catch (Exception e) {e.printStackTrace();System.out.println("事务回滚");}}
}
结论:
说明: 在业务层不方便做,但是又不得不做的事情,可以放到代理对象中. 通过这样的设计就可以解决业务层耦合的问题. 代理对象看起来和真实的对象 一模一样.所以用户使用不会察觉.
类比:
在上面的基础之上,创建一个proxy包,里面创建一个JDKProxy类
package com.jt.demo1.proxy;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;public class JDKProxy {/*** 获取代理对象* 参数说明:* 1.ClassLoader loader 类加载器 读取真实的类数据* 2.Class>[] interfaces 要求传递接口的信息* 3.InvocationHandler h 当代理对象执行方法时执行* 注意事项:JDK代理必须要求 “被代理者” 有接口要么实现接口** @param target* @return*/public static Object getProcy(Object target){//1.获取类加载器ClassLoader classLoader = target.getClass().getClassLoader();//2.获取接口Class>[] interfaces = target.getClass().getInterfaces();//通过代理的类新创建一个代理的对象return Proxy.newProxyInstance(classLoader, interfaces, getInvocationHandler(target));}//代理对象执行方法时调用public static InvocationHandler getInvocationHandler(Object target){//这些代码都是写死的return new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("================事务开始==============================");//执行目标(真实对象的)方法Object result = method.invoke(target, args);System.out.println("=========================事务提交=======================");return result;}};}}
package com.jt.demo1;import com.jt.demo1.config.SpringConfig;
import com.jt.demo1.proxy.JDKProxy;
import com.jt.demo1.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class SpringTx {public static void main(String[] args) {ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);UserService userService = applicationContext.getBean(UserService.class);System.out.println(userService.getClass());UserService proxy = (UserService)JDKProxy.getProcy(userService);System.out.println(proxy.getClass());System.out.println(proxy);System.out.println(proxy.toString());//基于代理对象,执行业务操作 实现方法扩展proxy.addUser();proxy.deleteUser();}
}
因为它默认打印的是proxy.toString
方法,即调用了被代理类的toString方法,所以会打印事务开始和事务结束,以及其地址信息。
@Configuration 标识当前类是配置类
@ComponentScan 包扫描注解 扫描注解
@Bean 标识该方法的返回值交给Spring容器管理
@Scope 控制多例和单例
@Lazy 懒加载
@PostConstruct 初始化方法
@PreDestroy 销毁方法
@Component 将当前类未来的对象交给容器管理
@Autowired 按照类型进行注入
@Qualifier 按照名称进行注入
@Repository 标识持久层注解
@Service 标识Service层
@Controller 标识Controller层
@Value 为属性赋值 @Value("${key}")
@PropertySource 加载指定路径的配置文件properties
上一篇:一款OutLook信息收集工具