一、 注解:
1、 基础回顾
1、注解就是为了说明java中的某一个部分的作用(Type)
2、注解都可以用于哪个部分是@Target注解起的作用
3、注解可以标注在ElementType枚举类所指定的位置上(类、接口、注解类型、或枚举声明上)
4、
@Documented
//该注解是否出现在帮助文档中
@Retention(RetentionPolicy.RUNTIME)
//该注解在java,class和运行时都起作用
@Target(ElementType.ANNOTATION_TYPE)
//该注解只能用于注解上
public @interface Target {
ElementType[] value();
}
5、用来解析注解的类成为注解解析器
2、 依赖注入的注解解析器
1、 @Resource注解的使用规则:
1、在spring的配置文件中导入命名空间
xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
2、引入依赖注入的注解解析器
3、在spring的配置文件中把bean引入进来
4、在一个类的属性上加
@Resource(name="student_annotation")
private Student student;
注:从该注解本身
@Target({TYPE, FIELD, METHOD})
@Retention(RUNTIME)
public @interface Resource {
String name() default "";
}
1、该注解可以用于属性上或者方法上,但是一般用户属性上
2、该注解有一个属性name,默认值为""
3、atuowired和qualifier一起使用的作用与resource等同
@Autowired
@Qualifier("student_annotation")
private Student student;
2、 例子
--------------------------------------------------------------------------------
类:
public class Student {
public void show(){
System.out.println("show student");
}
}
public class Person {
private Long pid;
private String pname;
// 只有引用类型使用注解,基本类型不适用
@Resource(name="student_annotation")
// 注: atuowired和qualifier一起使用的作用与resource等同
//
@Autowired
//
@Qualifier("student_annotation")
private Student student;
public void showStudent(){
this.student.show();
}
}
配置文件:
测试:
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person = (Person) context.getBean("person_annotation");
person.showStudent();
}
--------------------------------------------------------------------------------
3、 分析加入注解后的spring整个过程:
1、当启动spring容器的时候,spring容器加载了配置文件
2、在spring配置文件中,只要遇到bean的配置,就会为该bean创建对象
3、在纳入spring容器的范围内查找所有的bean,看哪些bean的属性或者方法上加有@Resource
4、找到@Resource注解以后,判断该注解name的属性是否为""(name没有写)
如果没有写name属性,则会让属性的名称的值和spring中bean的id值做匹配,如果匹配成功则赋值
如果匹配不成功,则会按照类型进行匹配,如果匹配不成功,则报错
如果有name属性,则会按照name属性的值和spring的bean中ID进行匹配,匹配成功,则赋值,不成功则
3、 类扫描的注解
1、 @component注解的使用规则:
1、在spring的配置文件中导入命名空间
xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
2、引入类扫描的注解解析器
1、 component:指的就是一个类;
2、 该注解解析器包含了两个功能:依赖注入和类扫描
3、 在base-package包及子包下查找所有的类
4、如果一个类上加了@Component注解,就会进行如下的法则
如果其value属性的值为""
@Component
public class Person {}
等价于
如果其value属性的值不为""
@Component("p")
public class Person {}
等价于
5、按照@Resource的法则再次进行操作
2、 例子
--------------------------------------------------------------------------------
类:
@Component("b")
public class Student {
public void show(){
System.out.println("scan student");
}
}
@Component("a")
public class Person {
@Resource(name="b")
private Student student;
public void showStudent(){
System.out.println("show student scan");
}
}
配置文件:
测试:
@Test
public void testPerson(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person = (Person) context.getBean("a");
person.showStudent();
}
--------------------------------------------------------------------------------
4、 XML配置实现依赖注入于注解实现依赖注入的区别
1、xml书写麻烦,但是效率高
2、注解书写简单,但是效率低,扫描companent一次,扫描resource又一次
5、 类扫描的注解的细化
1、 @component在MVC模式中可细化为: @Controller @Service @Repository
2、 用注解的方式实现MVC的案例
---------------------------------------------------------------------------------------------
Action层:
@Controller("personAction")
public class PersonAction {
@Resource(name="personService")
private PersonService personService;
public void savePerson(){
this.personService.savePerson();
}
}
Service层:
public interface PersonService {
public void savePerson();
}
ServiceImpl层:
@Service("personService")
public class PersonServiceImpl implements PersonService {
@Resource(name="personDao")
private PersonDao personDao;
public void savePerson() {
this.personDao.savePerson();
}
}
Dao层:
public interface PersonDao {
public void savePerson();
}
DaoImpl层:
@Repository("personDao")
public class PersonDaoImpl implements PersonDao {
public void savePerson() {
System.out.println("dao层操作数据库的代码");
}
}
配置文件:
测试:
public class MVCTest {
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("
cn/itcast/annotation/spring/mvc/applicationContext-spring-mvc-annotation-test.xml");
PersonAction personAction = (PersonAction) context.getBean("personAction");
personAction.savePerson();
}
}
---------------------------------------------------------------------------------------------
二、 spring的继承
1、如果一个类在spring配置文件中,但是不想让整个类创建对象,则用abstract="true"
2、如果让一个子类拥有父类的属性,则parent="commonDao"
例子:
------------------------------------------------------------------------------------------------------
父类:
public class CommonDao {
private String s;
public void saveEntity(){
System.out.println("save entity");
}
public void updateEntity(){
System.out.println("update entity");
}
public String getS() {
return s;
}
public void setS(String s) {
this.s = s;
}
}
子类:
public class PersonDao extends CommonDao {
public void show(){
System.out.println("show personDao");
}
}
配置文件:
测试:
public class ExtendTest {
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("
cn/itcast/spring/extend/applicationContext-extend.xml");
// 注: CommonDao类在配置文件中声明为abstract 所以不能创建对象
//
CommonDao commonDao = (CommonDao) context.getBean("commonDao");
//
commonDao.saveEntity();
PersonDao personDao = (PersonDao) context.getBean("personDao");
System.out.println(personDao.getS());
personDao.saveEntity();
personDao.updateEntity();
personDao.show();
}
}
------------------------------------------------------------------------------------------------------
三、 代理模式
1、 作用: 对于代码的增强
2、 体系结构: 有一个目标借口, 有一个目标类和一个代理类都实现了该目标借口,
且代理类中存在目标类的引用
3、 静态代理模式
静态代理模式的缺点:
1、如果一个系统中有100Dao,则创建100个代理对象
2、如果一个dao中有很多方法需要事务,则代理对象的方法中重复代码还是很多
3、由第一点和第二点可以得出:proxy的重用性不强
解决途径: 动态代理
例1:
-------------------------------------------------------------------------------------------------------
public interface PersonDao {
public void savePerson();
}
// 目标类
public class PersonDaoImpl implements PersonDao {
public void savePerson() {
System.out.println("save person");
}
}
public class TransactionX {
public void beginTransaction(){
System.out.println("开启事务");
}
public void commit(){
System.out.println("提交事务");
}
}
public class PersonDaoProxy implements PersonDao {
private PersonDao personDao;
private TransactionX transactionx;
public PersonDaoProxy(PersonDao personDao,TransactionX transactionX) {
super();
this.personDao = personDao;
this.transactionx = transactionX;
}
public void savePerson() {
this.transactionx.beginTransaction();
this.personDao.savePerson();
this.transactionx.commit();
}
}
public class ProxyTest {
@Test
public void test(){
PersonDao target = new PersonDaoImpl();
TransactionX transactionX = new TransactionX();
PersonDao proxy = new PersonDaoProxy(target, transactionX);
proxy.savePerson();
}
}
-------------------------------------------------------------------------------------------------------
例2:
-------------------------------------------------------------------------------------------------------
public interface PersonDao {
public void savePerson();
}
public class PersonDaoImpl implements PersonDao {
public void savePerson() {
System.out.println("save person");
}
}
public class TransactionX {
public void beginTransaction(){
System.out.println("开启事务");
}
public void commit(){
System.out.println("提交事务");
}
}
public class PersonDaoProxy implements PersonDao {
private PersonDao personDao;
private TransactionX transactionx;
public PersonDaoProxy(PersonDao personDao,TransactionX transactionX) {
super();
this.personDao = personDao;
this.transactionx = transactionX;
}
public void savePerson() {
this.transactionx.beginTransaction();
this.personDao.savePerson();
this.transactionx.commit();
}
}
配置文件:
测试:
public class ProxyTest {
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("
cn/itcast/spring/proxy/applicationContext-spring-proxy.xml");
PersonDaoProxy personDaoProxy = (PersonDaoProxy) context.getBean("personDaoProxy");
personDaoProxy.deletePerson();
}
}
-------------------------------------------------------------------------------------------------------
4、 动态代理
1、分类:
1、产生的代理对象和目标对象实现了共同的接口
jdk动态代理
2、代理对象是目标对象的子类
hibernate: Person person = session.load(Person.class,1L); javassisit
spring:cglib动态代理
2、jdk动态代理详解
1、因为是用jdk的API做到的
2、代理对象是动态产生的
3、JDK动态代理的拦截器的写法步骤
引入目标类
引入重复的代码类(如: 事务的开启关闭)
通过构造函数给目标类和事务赋值
填充invoke方法
4、标志: 生成的动态对象的debug为$proxy4
5、注意事项:
1、拦截器中invoke方法体的内容就是代理对象方法体的内容
2、当客户端执行代理对象.方法时,进入到了拦截器的invoke方法体
3、拦截器中invoke方法的method参数是在调用的时候赋值的
例1 模拟jdk动态代理:
-------------------------------------------------------------------------------
public interface PersonDao {
public void savePerson();
}
public class PersonDaoImpl implements PersonDao {
public void savePerson() {
System.out.println("save person");
}
}
public class TransactionX {
public void beginTransaction(){
System.out.println("开启事务");
}
public void commit(){
System.out.println("提交事务");
}
}
public class PersonInterceptor implements InvocationHandler {
private Object target;
// 目标类
private TransactionX transactionX; // 事务
public PersonInterceptor(Object target, TransactionX transactionX) {
super();
this.target = target;
this.transactionX = transactionX;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
this.transactionX.beginTransaction();
method.invoke(this.target, args);
// 调用目标类的方法
this.transactionX.commit();
return null;
}
}
public class ProxyTest {
@Test
public void test(){
Object target = new PersonDaoImpl();
TransactionX transactionX = new TransactionX();
PersonInterceptor personInterceptor = new PersonInterceptor(target, transactionX);
// 生成动态的代理对象参数: 目标类的类加载器; 目标类实现的所有接口; 拦截器
PersonDao personDao = (PersonDao) Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), personInterceptor);
personDao.deletePerson();
}
}
-------------------------------------------------------------------------------
例2 结合hibernate使用jdk动态代理(配置文件和工具类略)
-------------------------------------------------------------------------------
public class Person implements Serializable {
private Long pid;
private String pname;
private String psex;
// set/get属性
}
public interface PersonDao {
public void savePerson(Person person);
}
public class PersonDaoImpl extends HibernateUtil implements PersonDao {
public void savePerson(Person person) {
sessionFactory.getCurrentSession().save(person);
}
}
public class MyTransaction extends HibernateUtil{
private Transaction transaction;
public void beginTransaction(){
this.transaction = sessionFactory.getCurrentSession().beginTransaction();
}
public void commit(){
this.transaction.commit();
}
}
public class PersonDaoInterceptor implements InvocationHandler {
private Object target;
private MyTransaction myTransaction;
public PersonDaoInterceptor(Object target, MyTransaction myTransaction) {
super();
this.target = target;
this.myTransaction = myTransaction;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
this.myTransaction.beginTransaction();
method.invoke(this.target, args);
this.myTransaction.commit();
return null;
}
}
public class ProxyTest {
@Test
public void test(){
Object target = new PersonDaoImpl();
MyTransaction myTransaction = new MyTransaction();
PersonDaoInterceptor personDaoInterceptor = new PersonDaoInterceptor(target, myTransaction);
PersonDao personDao = (PersonDao) Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), personDaoInterceptor);
Person person = new Person();
person.setPname("aaa");
person.setPsex("男");
personDao.savePerson(person);
}
}
-------------------------------------------------------------------------------
3、cglib动态代理
1、 所需jar包: cglib.jar
2、 使用代码加强机制产生代理对象
3、 cglib产生的代理对象是目标对象的子类
例子
----------------------------------------------------------------------------------------------
public interface Interceptor {
public void interceptor();
}
public class Logger implements Interceptor{
public void interceptor() {
System.out.println("启动日志");
}
}
public class Privilege implements Interceptor{
public void interceptor() {
System.out.println("权限");
}
}
public class Security implements Interceptor{
public void interceptor() {
System.out.println("安全性框架");
}
}
public interface SalaryManager {
public void showSalary();
}
public class SalaryManagerImpl implements SalaryManager{
public void showSalary() {
System.out.println("查看工资");
}
}
public class SalaryInterceptor implements MethodInterceptor{
private Object target;
private List interceptors;
public SalaryInterceptor(Object target, List interceptors) {
super();
this.target = target;
this.interceptors = interceptors;
}
// 使用代码加强机制产生代理对象
public Object createProxy(){
Enhancer enhancer = new Enhancer();
enhancer.setCallback(this);
enhancer.setSuperclass(this.target.getClass());
return enhancer.create();
}
// cglib的拦截器写法
public Object intercept(Object arg0, Method arg1, Object[] arg2,
MethodProxy arg3) throws Throwable {
for (Interceptor interceptor : interceptors) {
interceptor.interceptor();
}
arg1.invoke(this.target, arg2);
return null;
}
public class SalaryTest {
@Test
public void test(){
// 目标类
Object target = new SalaryManagerImpl();
Logger logger = new Logger();
Security security = new Security();
Privilege privilege = new Privilege();
List interceptors = new ArrayList();
interceptors.add(logger);
interceptors.add(security);
interceptors.add(privilege);
SalaryInterceptor salaryInterceptor = new SalaryInterceptor(target, interceptors);
SalaryManagerImpl salaryManagerImpl = (SalaryManagerImpl) salaryInterceptor.createProxy();
salaryManagerImpl.showSalary();
}
}
}
----------------------------------------------------------------------------------------------